【问题标题】:Convert an existing Column to Identity将现有列转换为标识
【发布时间】:2013-10-25 08:05:28
【问题描述】:

我在 SQL Server 中有一个包含记录包的表。我想将作为主键的 ID 列转换为标识列而不会丢失数据。我想到了以下两种方法:

  1. 创建具有标识的新表并删除现有表。
  2. 创建具有标识的新列并删除现有列。

但很明显,它们无法实施,因为保存记录是我的首要任务。

还有其他方法吗?

【问题讨论】:

  • 重复,但我也提到了限制
  • 你的ID列是否已经作为外键与其他表连接?
  • 我看不出保存记录对于两种方法中的任何一种来说是个问题。没有其他选择。您只需创建一些新的东西,如果您想保留已有的 ID - 这是一个新表。
  • @NenadZivkovic,因为提问者标记了 Sql Server 2012,所以还有一个替代方案。 steoleary 的回答会做到——在这种情况下,我自己也使用过同样的解决方案。

标签: sql sql-server tsql sql-server-2012


【解决方案1】:

此解决方案违反了您的第 2 点,但没有其他方法,我认为您的目标是保持旧值,因为没有其他任何意义......

您可以执行以下操作:

  1. 可以插入表中的标识列:

    set identity_insert YourTable ON
    
  2. 将新的 ID 列添加到您的表中,并插入旧列中的值
  3. 关闭身份插入

    set identity_insert YourTable OFF
    
  4. 删除旧的 ID 列
  5. 将新列重命名为旧名称
  6. 使其成为主键

唯一的问题可能是您的 ID 列已经作为外键连接到其他表。那么你在删除旧列时遇到问题...... 在这种情况下,您必须在第 3 步之后删除 ID 列上的外键约束,然后执行第 4 到 6 步,然后重新创建外键约束。

【讨论】:

    【解决方案2】:

    当您使用 SQL Server 2012 时,另一种可能的替代方法是创建一个序列对象,该对象的起始值的最高 ID +1 已经在您的表中,然后使用 GET NEXT VALUE FOR 为您的列创建一个默认约束并引用您刚刚创建的序列对象。

    【讨论】:

    • 我遇到了完全相同的问题,并这样做是为了解决它。效果很好。
    • 当。我打算包括一个例子:stackoverflow.com/questions/14413383/…
    • 如果您有 guid / uniqueidentifier,您会怎么做?
    【解决方案3】:

    如果你可以直接访问Server Database,直接进入表的设计,选择PK列,将标识改为“Yes”即可。确保将种子设置为该列的最大值。默认情况下增量为 1。保存表格设计,你应该很高兴。

    【讨论】:

      【解决方案4】:

      考虑到源表不是太大:

      1. 创建新表(使用 IDENTITY)
      2. 从现有表中填充新表(IDENTITY_INSERT ON)
      3. 删除旧表(首先删除任何现有的 FK)
      4. 将新表重命名为旧名称(如果需要,重新建立 FK)

           -- Create Sample Existing Table
           DROP TABLE IF EXISTS #tblTest
           CREATE TABLE #tblTest
           (
                ID      INT NOT NULL
                , Val   VARCHAR(10) NOT NULL
            )
        
            INSERT INTO #tblTest 
            (
                ID
                , Val
            )
            VALUES 
                (1, 'a')
                , (2, 'b')
                , (4, 'c')
            GO
        
            -- Create and Populate New Table (with IDENTITY_INSERT ON)
            DROP TABLE IF EXISTS #tblTestNew
            CREATE TABLE #tblTestNew
            (
                ID      INT IDENTITY(1, 1) NOT NULL 
                , Val   VARCHAR(10) NOT NULL
            )
        
            SET IDENTITY_INSERT #tblTestNew ON
        
            INSERT INTO #tblTestNew 
            (
                ID
                , Val
            )
            (
                SELECT
                    #tblTest.ID
                    , #tblTest.Val
                FROM
                    #tblTest
            )
        
            SET IDENTITY_INSERT #tblTestNew OFF
            GO
        
            -- Rename Existing Table to Old (can use sp_rename instead, but I can't for temp tables)
            SELECT * INTO #tblTestOld FROM #tblTest
            DROP TABLE #tblTest
            GO
        
            -- Rename New Table to Existing (can use sp_rename instead, but I can't for temp tables)
            SELECT * INTO #tblTest FROM #tblTestNew
            DROP TABLE #tblTestNew
            GO
        
            -- Test Inserting new record
            INSERT INTO #tblTest (Val)
            VALUES ('d')
        
            -- Verify Results
            SELECT * FROM #tblTest
            EXEC tempdb.sys.sp_help @objname = N'#tblTest'
        
            --  Drop 'Old' Table (when ready)
            DROP TABLE IF EXISTS #tblTestOld
        
            -- Cleanup
            DROP TABLE IF EXISTS #tblTest
            DROP TABLE IF EXISTS #tblTestNew
            DROP TABLE IF EXISTS #tblTestOld
        

      如果表很大,考虑日志增长、恢复模式、可能的单用户模式等。

      【讨论】:

        【解决方案5】:
        create table t1 (col1 int, col2 varchar(10))
        
        insert into t1 values (10, 'olddata')
        

        --添加标识列

        alter table t1 add col3 int identity(1,1)
        
        GO
        

        --重命名或删除旧列

        alter table t1 drop column col1
        

        --将新列重命名为旧列名

        exec sp_rename 't1.col3', 'col1', 'column'
        
        GO
        

        --添加新的测试、审核表

        insert into t1 values ( 'newdata')
        

        从 t1 中选择 *

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-03-24
          • 2019-04-29
          • 1970-01-01
          • 2018-07-08
          • 1970-01-01
          • 2010-11-23
          • 2014-01-24
          • 2016-10-18
          相关资源
          最近更新 更多