【问题标题】:SQL Server add auto increment primary key to existing tableSQL Server 将自动增量主键添加到现有表
【发布时间】:2011-06-19 05:49:31
【问题描述】:

作为标题,我有一个已经填充了 150000 条记录的现有表。我添加了一个 Id 列(当前为空)。

我假设我可以运行查询以使用增量数字填充此列,然后设置为主键并打开自动增量。这是正确的方法吗?如果是这样,我该如何填写初始数字?

【问题讨论】:

    标签: sql-server sql-server-2008 primary-key alter-table


    【解决方案1】:

    不 - 你必须反其道而行之:从一开始就将其添加为 INT IDENTITY - 当你这样做时,它将填充身份值:

    ALTER TABLE dbo.YourTable
       ADD ID INT IDENTITY
    

    然后你可以把它设为主键:

    ALTER TABLE dbo.YourTable
       ADD CONSTRAINT PK_YourTable
       PRIMARY KEY(ID)
    

    或者如果您更喜欢一步完成所有操作:

    ALTER TABLE dbo.YourTable
       ADD ID INT IDENTITY
           CONSTRAINT PK_YourTable PRIMARY KEY CLUSTERED
    

    【讨论】:

    • 这是一个非常好的答案,但是如何将起始整数从 1 更改为 1000?我想从 1000 开始数。我怀疑我可以使用ALTER TABLE ORDER ALTER COLUMN ORDERNO RESTART WITH 1,但我不想在没有与专家核实的情况下尝试它:) 参考。 pic.dhe.ibm.com/infocenter/iseries/v7r1m0/…
    • 我刚用过这个,它似乎工作了alter table attachments add ATTACHMENT_NUMBER int identity (1000, 1)
    • @stom:如果您不指定任何内容,则将使用 seed=1 和 increment=1 - 这是最常用的设置。如果您创建了这样的表 - 它会正常工作。但我建议始终在 SQL 脚本中明确指定种子和增量——尤其是对于较大的站点。这只是一个好习惯。
    • @stom: 好吧,PRIMARY KEY 暗示NOT NULL 已经到位 - 再说一遍 - 这不是绝对必要的。但我更喜欢明确,所以我总是有NOT NULL,只是为了绝对清楚
    • @turbo88:当您定义PRIMARY KEY 时,会自动为您创建聚集索引(除非您明确指定NONCLUSTERED
    【解决方案2】:

    您不能“打开” IDENTITY:它是表重建。

    如果您不关心数字顺序,您可以一次性添加 IDENTITY 列 NOT NULL。 150k 行并不多。

    如果您需要保留一些数字顺序,请相应地添加数字。然后使用 SSMS 表设计器设置 IDENTITY 属性。这允许您生成一个脚本,该脚本将为您执行列删除/添加/保留数字/重新设置种子。

    【讨论】:

    • OP 在 SQL Server 2008 so there is a way
    • 整个实例需要在单用户模式下启动,因此在大多数情况下可能不可行,但ALTER TABLE ... SWITCH 可以做到这一点。
    【解决方案3】:

    我遇到了这个问题,但无法使用标识列(由于各种原因)。 我决定了:

    DECLARE @id INT
    SET @id = 0 
    UPDATE table SET @id = id = @id + 1 
    

    借自here

    【讨论】:

      【解决方案4】:

      如果该列已存在于您的表中并且为空,您可以使用此命令更新该列(替换 id、tablename 和 tablekey ):

      UPDATE x
      SET x.<Id> = x.New_Id
      FROM (
        SELECT <Id>, ROW_NUMBER() OVER (ORDER BY <tablekey>) AS New_Id
        FROM <tablename>
        ) x
      

      【讨论】:

      • 你用这个为我节省了时间! @gbn 的答案很好的附录。
      【解决方案5】:

      当我们在现有表中添加标识列时,它将自动填充,无需手动填充。

      【讨论】:

        【解决方案6】:

        此答案是对最高投票答案的一个小补充,适用于 SQL Server。该问题要求自动递增主键,当前答案确实添加了主键,但未将其标记为自动递增。下面的脚本检查列,存在,并在启用自动增量标志的情况下添加它。

        IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_NAME = 'YourTable' AND COLUMN_NAME = 'PKColumnName')
        BEGIN
        
        
        ALTER TABLE dbo.YourTable
           ADD PKColumnName INT IDENTITY(1,1)
        
        CONSTRAINT PK_YourTable PRIMARY KEY CLUSTERED
        
        END
        
        GO
        

        【讨论】:

        • 很遗憾,帖子上有很多赞成票,你的回答对我来说是 100%,希望我能添加更多赞成票
        【解决方案7】:

        您可以通过设计师设置身份 (1,1) 右键单击 tbl => 设计 => 在左侧(右键单击)=> 属性 => 在标识列中选择#column

        Properties

        idendtity column

        【讨论】:

        • 你知道这是否是一个好方法吗? OP正在询问这是否是“正确的继续方式”。更完整的答案可以帮助他们了解该方法的优缺点。
        • 真的我在开发环境中使用了这个选项,如果你想把这个更改传递给生产环境,你应该使用 VIEW DEPENDENCY 验证身份字段是否被某些存储过程或触发器使用。跨度>
        【解决方案8】:

        如果您的表使用其主键或 foriegen 键与其他表有关系,则可能无法更改您的表。所以你需要删除并再次创建表。
        要解决这些问题,您需要通过右键单击数据库并在高级选项中将数据类型设置为脚本到方案和数据来生成脚本。之后,使用此脚本更改您的列,通过运行查询来识别和重新生成表。
        您的查询将如下所示:

        USE [Db_YourDbName]
        GO
        SET ANSI_NULLS ON
        GO
        SET QUOTED_IDENTIFIER ON
        GO
        Drop TABLE [dbo].[Tbl_TourTable]
        
        CREATE TABLE [dbo].[Tbl_TourTable](
            [ID] [int] IDENTITY(1,1) NOT NULL,
            [Name] [nvarchar](50) NULL,
            [Family] [nvarchar](150) NULL)  
        
        GO
        
        SET IDENTITY_INSERT [dbo].[Tbl_TourTable] ON 
        
        INSERT [dbo].[Tbl_TourTable] ([ID], [Name], [Family]) VALUES (1,'name 1', 'family 1')
        INSERT [dbo].[Tbl_TourTable] ([ID], [Name], [Family]) VALUES (1,'name 1', 'family 1')
        INSERT [dbo].[Tbl_TourTable] ([ID], [Name], [Family]) VALUES (1,'name 1', 'family 1')
        INSERT [dbo].[Tbl_TourTable] ([ID], [Name], [Family]) VALUES (1,'name 1', 'family 1')
        INSERT [dbo].[Tbl_TourTable] ([ID], [Name], [Family]) VALUES (1,'name 1', 'family 1')
        INSERT [dbo].[Tbl_TourTable] ([ID], [Name], [Family]) VALUES (1,'name 1', 'family 1')
        INSERT [dbo].[Tbl_TourTable] ([ID], [Name], [Family]) VALUES (1,'name 1', 'family 1')
        
        SET IDENTITY_INSERT [dbo].[Tbl_TourTable] off 
        

        【讨论】:

          【解决方案9】:
          ALTER TABLE table_name ADD temp_col INT IDENTITY(1,1) 
          update 
          

          【讨论】:

          • 你能解释一下吗?
          • 虽然此代码可以解决 OP 的问题,但最好包含关于您的代码如何解决 OP 问题的说明。这样,未来的访问者可以从您的帖子中学习,并将其应用到他们自己的代码中。 SO 不是编码服务,而是知识资源。此外,高质量、完整的答案更有可能获得支持。这些功能,以及所有帖子都是独立的要求,是 SO 作为一个平台的一些优势,使其与论坛区分开来。您可以编辑以添加其他信息和/或使用源文档补充您的解释。
          • 我通过谷歌搜索来到这里,因为我只需要语法。这对我来说是最好的答案,可能还有很多其他没有 SO 帐户的人。我忽略了接受的答案,因为它太长了!我的观点是,有两种类型的访问者——一种寻找完整的解释,另一种使用 SO 作为快速参考。有用的是具有 TLDR 部分的答案。
          【解决方案10】:

          这是一个您可以尝试的想法。 原始表 - 无标识列 table1 创建一个新表 - 调用 table2 以及标识列。 将数据从 table1 复制到 table2 - 标识列自动填充自动递增的数字。

          重命名原始表 - table1 到 table3 将新表 - table2 重命名为 table1(原始表) 现在,您拥有包含标识列并为现有数据填充的 table1。 在确保没有问题并正常工作后,不再需要时删除 table3。

          【讨论】:

            【解决方案11】:

            创建一个具有不同名称和相同列、主键和外键关联的新表,并将其链接到代码的插入语句中。 例如:对于 EMPLOYEE,替换为 EMPLOYEES。

            CREATE TABLE EMPLOYEES(
            
                EmpId        INT NOT NULL IDENTITY(1,1), 
                F_Name       VARCHAR(20) ,
                L_Name       VARCHAR(20) ,
                DOB          DATE ,
                DOJ          DATE ,
                PRIMARY KEY (EmpId),
                DeptId int FOREIGN KEY REFERENCES DEPARTMENT(DeptId),
                DesgId int FOREIGN KEY REFERENCES DESIGNATION(DesgId),
                AddId int FOREIGN KEY REFERENCES ADDRESS(AddId)   
            ) 
            

            但是,您必须删除现有的 EMPLOYEE 表或根据您的要求进行一些调整。

            【讨论】:

              【解决方案12】:

              alter table /** 粘贴 tabal 的名字 **/ 添加 id int IDENTITY(1,1)

              delete from /** 粘贴 tabal 的名字 **/ 其中 id 在

              (

              select a.id FROM /** 粘贴 tabal 的名字 / 作为 左外连接 ( 选择 MIN(id) 作为 id FROM / 粘贴 tabal 的名字 / 通过...分组 / 粘贴列 c1,c2 .... **/

              ) as t1 
              ON a.id = t1.id
              

              哪里 t1.id 为空

              )

              alter table /** 粘贴 tabal 的名字 **/ 删除列 ID

              【讨论】:

              • 你有什么问题? How to ask
              • 编辑您的答案,使用降价来正确格式化您的代码示例。
              【解决方案13】:

              试试下面的代码:

              DBCC CHECKIDENT ('settings', RESEED, 0) 
              

              【讨论】:

                【解决方案14】:

                尝试这样的事情(首先在测试台上):

                使用 your_database_name 走 WHILE (SELECT COUNT(*) FROM your_table WHERE your_id_field IS NULL) > 0 开始 设置行数 1 更新 your_table SET your_id_field = MAX(your_id_field)+1 结尾 打印“全部完成”

                我根本没有测试过,所以要小心!

                【讨论】:

                • -1 不回答问题(这是关于添加IDENTITY 列)并且无论如何都不会工作。 UPDATE your_table SET your_id_field = MAX(your_id_field)+1 你不能只在MAX 那里加入。避免重复更新同一行的WHERE 子句在哪里?
                【解决方案15】:

                这在 MariaDB 中有效,所以我只能希望它在 SQL Server 中有效:删除您刚刚插入的 ID 列,然后使用以下语法:-

                ALTER TABLE table_name ADD id INT PRIMARY KEY AUTO_INCREMENT;

                不需要另一张桌子。这只是插入一个 id 列,使其成为主索引,并用顺序值填充它。如果 SQL Server 不这样做,我很抱歉浪费您的时间。

                【讨论】:

                  【解决方案16】:

                  ALTER TABLE table_name ADD COLUMN ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT ; 这可能很有用

                  【讨论】:

                    猜你喜欢
                    • 2016-09-11
                    • 1970-01-01
                    • 2021-09-10
                    • 2018-10-17
                    • 2013-01-23
                    • 2012-02-22
                    相关资源
                    最近更新 更多