【问题标题】:add an identity column to existing table as the primary key and change order将标识列添加到现有表作为主键和更改顺序
【发布时间】:2013-06-11 08:57:19
【问题描述】:

我有一个包含超过 700 万条记录的表。该表没有主键。我想添加一个新的标识列并将其设置为主键。我尝试使用 SSMS 添加列,然后将其设置为主键。我称这个新列 ID。

这几乎奏效了,但是我想将表的默认顺序更改为基于另一列,例如降序的日期时间列。这可能吗?也许我需要使用临时表和ROW_NUMBER() 函数。

但是,我不太擅长 SQL。有人可以帮忙吗?

我还需要一个回滚脚本,这样我才能回到原来的表。

【问题讨论】:

  • 没有“表格的默认顺序”这样的东西。关系表中的行未排序
  • @MitchWheat - 大约。在一个页面中,不能保证行按聚集索引排序。
  • @Damien_The_Unbeliever - 也不保证文件中的页面符合逻辑键顺序。
  • 刚刚注意到您说“按降序排列的日期时间列”。那么在您创建了这个IDENTITY 列之后添加的新行会发生什么情况呢?

标签: sql sql-server


【解决方案1】:

这里还有一个想法:

Step1 - 在“按降序排列的日期时间列”上创建临时聚集索引

CREATE CLUSTERED INDEX ix_YourTableTEMP ON YourTable (DateTimeColumn DESC)

Step2 - 添加标识列。现在 ID 应该按照之前创建的索引的顺序排列 - 尽管我认为这不能 100% 保证。

ALTER TABLE YourTable ADD IdColumn INT IDENTITY(1,1)

Step3 - 删除临时索引

DROP INDEX  ix_YourTableTEMP ON YourTable 

Step4 - 在新列上创建新的集群 PK

ALTER TABLE YourTable 
ADD CONSTRAINT PK_YourTable PRIMARY KEY CLUSTERED (IdColumn)

【讨论】:

  • 这只是一个想法,它可能会奏效。为了确保顺序正确,我还会创建新表。
  • 非常适合我!
  • 索引未聚集时似乎不起作用
【解决方案2】:

LinkMartin Smith 给出的答案可能是最好的答案,但这里有一个替代方案:

-- CREATE TABLE WITH SOME DATA IN
CREATE TABLE T (X INT);
INSERT T VALUES (1), (2), (3);

-- CREATE A CLONE OF THIS TABLE, ADDING AN IDENTITY COLUMN
-- USING ORDER BY TO AFFECT THE ORDER OF THE INSERT
SELECT  ID = IDENTITY(INT, 1, 1),
        T.*
INTO    T_Clone
FROM    T
ORDER BY X DESC;

-- DROP ORIGINAL TABLE
DROP TABLE T;

-- RENAME CLONE TABLE TO ORIGINAL TABLE NAME
EXECUTE SP_RENAME 'dbo.T_Clone', 'T', 'OBJECT';

-- SELECT FROM TABLE TO CHECK RESULTS
SELECT  *
FROM    T;

回滚:

ALTER TABLE T DROP COLUMN ID;

编辑

已经指出SELECT ID = IDENTITY(INT, 1, 1).. INTO.. FROM .. ORDER BY ...不保证插入的顺序。因此,故障安全选项似乎是使用CREATE TABLE 语法创建克隆表并添加IDENTITY 列:

CREATE TABLE T_Clone
(       ID      INT IDENTITY(1, 1) NOT NULL PRIMARY KEY,
        <your columns>
);
INSERT T_Clone (<your columns>)
SELECT  <your columns>
FROM    T
ORDER BY ...;

然后像上面那样继续 Drop 和重命名。我找不到任何文档说这种方法对于订购插件不可靠,如果证明仍然不可靠,您可以使用:

SET IDENTITY_INSERT T_Clone ON;
INSERT T_Clone (ID, <your columns>)
SELECT  ROW_NUMBER() OVER(ORDER BY ...),
        <your columns>
FROM    T;

SET IDENTITY_INSERT T_Clone OFF;

然后在插入后重新播种 T_CLone。

【讨论】:

  • 当然,SELECT ... INTO ... ORDER BY 并不总是遵守生成标识值的顺序。参见例如KB273586
  • 根据point 4 here,您的更新很好 AFAIK。
猜你喜欢
  • 1970-01-01
  • 2012-11-04
  • 1970-01-01
  • 2012-08-01
  • 2016-01-03
  • 1970-01-01
  • 1970-01-01
  • 2019-04-29
  • 1970-01-01
相关资源
最近更新 更多