如何防止 SQL 服务器中的主键自动排序
How To Prevent Automatic Sorting On Primary Key in SQL Server
我想按 table 按插入时间顺序保存我的数据,但在 SQL 服务器中,他们将按主键排序。
我能做什么?
然后您必须将 date/time 设为主键,这是个坏主意。如果 table 有一个 auto-incrementing 主键,那么当您查看 table 时,它将始终按该顺序排列。但最终,它如何存储并不重要,因为当您查询 table 时,您可以按您希望的任何方式对其进行排序。
只需添加一个 ORDER BY ASC/DESC
我建议将主键设为标识列:
create table t (
t_id int identity(1, 1) primary key,
. . .
);
这将完全满足您的要求。默认情况下,SQL 服务器在主键上集群表,并且标识列随着每次更新而递增。请注意,尽管数据页已排序,但查询结果仍然是任意顺序,除非您在查询中使用 order by
子句。
这样的标识列对于插入比任意键更有效。您可以创建现在拥有的键 unique
和 not null
—— 主键的所有好处,而不必 re-arrange 每次插入数据页的不良影响(唯一索引是另一回事)。
SQL服务器的默认行为是使用主键对数据进行集群。您可以覆盖它。例如,这使得 not_pk
成为聚簇索引:
create table t (
id uniqueidentifier primary key default newid(),
created_at datetime default getdate(),
not_pk int identity(1, 1) unique clustered
);
我不会只使用 created_at
值作为聚簇索引——您可能会在给定的时间点插入多行。
或者,您可以明确地从主键中删除集群:
create table t (
id uniqueidentifier primary key nonclustered default newid(),
created_at datetime default getdate()
);
所以这里有两个因素您可能会混淆;数据的 物理 排序(即您的计算机如何将位打印到硬盘驱动器上)和 逻辑 排序。
物理顺序始终由您的聚簇索引定义。 10 次中有 9 次,这也恰好是您的主键,但不一定是。将 "Clustered Index" 视为 "How it's physically sorted on my disk"。您希望它以不同的方式存储,更改您 "cluster" 的方式(顺便说一下,如果您没有聚簇索引,则称为 "heap",它不能保证物理顺序的数据)。
合乎逻辑的 排序不存在。 SQL基于关系代数,关系代数对数学集进行运算。集合的定义 不包含有关集合固有顺序的信息 ,仅包含其组成部分。
现在,当您查询数据时,您可以指定一个 order by
,它将按照您要求的顺序 return 向您提供数据。但是,默认情况下,不保证或假设任何顺序(即使它在磁盘上的物理存储方式也是如此;即使 return 不时以该顺序发生)。
如果您想要特定的顺序,请在您的选择中使用 ORDER BY。
根据数据库理论定义,table 中的行未排序。您需要在检索行时使用 ORDER BY 指定排序顺序(使用 SELECT)。
现在,如果您不指定 ORDER BY,而只是相信 SQL 服务器 returns 他们通过 PK,您可能会大吃一惊,因为这是不安全的。默认情况下 SQL 服务器会执行此操作,因为 table 是集群的。但是...如果稍后有人更改 table 的聚类或删除它,您所有没有 ORDER BY 的查询都会立即出错。是的,你可能有麻烦了。
再次强调,如果您想要特定的顺序,请在您的选择中使用 ORDER BY。
我想按 table 按插入时间顺序保存我的数据,但在 SQL 服务器中,他们将按主键排序。
我能做什么?
然后您必须将 date/time 设为主键,这是个坏主意。如果 table 有一个 auto-incrementing 主键,那么当您查看 table 时,它将始终按该顺序排列。但最终,它如何存储并不重要,因为当您查询 table 时,您可以按您希望的任何方式对其进行排序。
只需添加一个 ORDER BY ASC/DESC
我建议将主键设为标识列:
create table t (
t_id int identity(1, 1) primary key,
. . .
);
这将完全满足您的要求。默认情况下,SQL 服务器在主键上集群表,并且标识列随着每次更新而递增。请注意,尽管数据页已排序,但查询结果仍然是任意顺序,除非您在查询中使用 order by
子句。
这样的标识列对于插入比任意键更有效。您可以创建现在拥有的键 unique
和 not null
—— 主键的所有好处,而不必 re-arrange 每次插入数据页的不良影响(唯一索引是另一回事)。
SQL服务器的默认行为是使用主键对数据进行集群。您可以覆盖它。例如,这使得 not_pk
成为聚簇索引:
create table t (
id uniqueidentifier primary key default newid(),
created_at datetime default getdate(),
not_pk int identity(1, 1) unique clustered
);
我不会只使用 created_at
值作为聚簇索引——您可能会在给定的时间点插入多行。
或者,您可以明确地从主键中删除集群:
create table t (
id uniqueidentifier primary key nonclustered default newid(),
created_at datetime default getdate()
);
所以这里有两个因素您可能会混淆;数据的 物理 排序(即您的计算机如何将位打印到硬盘驱动器上)和 逻辑 排序。
物理顺序始终由您的聚簇索引定义。 10 次中有 9 次,这也恰好是您的主键,但不一定是。将 "Clustered Index" 视为 "How it's physically sorted on my disk"。您希望它以不同的方式存储,更改您 "cluster" 的方式(顺便说一下,如果您没有聚簇索引,则称为 "heap",它不能保证物理顺序的数据)。
合乎逻辑的 排序不存在。 SQL基于关系代数,关系代数对数学集进行运算。集合的定义 不包含有关集合固有顺序的信息 ,仅包含其组成部分。
现在,当您查询数据时,您可以指定一个 order by
,它将按照您要求的顺序 return 向您提供数据。但是,默认情况下,不保证或假设任何顺序(即使它在磁盘上的物理存储方式也是如此;即使 return 不时以该顺序发生)。
如果您想要特定的顺序,请在您的选择中使用 ORDER BY。
根据数据库理论定义,table 中的行未排序。您需要在检索行时使用 ORDER BY 指定排序顺序(使用 SELECT)。
现在,如果您不指定 ORDER BY,而只是相信 SQL 服务器 returns 他们通过 PK,您可能会大吃一惊,因为这是不安全的。默认情况下 SQL 服务器会执行此操作,因为 table 是集群的。但是...如果稍后有人更改 table 的聚类或删除它,您所有没有 ORDER BY 的查询都会立即出错。是的,你可能有麻烦了。
再次强调,如果您想要特定的顺序,请在您的选择中使用 ORDER BY。