8

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

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

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

还有另一种方法可以做到这一点吗?

4

5 回答 5

4

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

您可以执行以下操作:

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

    set identity_insert YourTable ON
    
  2. 使用标识向您的表中添加一个新的 ID 列,并插入旧列中的值
  3. 关闭身份插入

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

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

于 2013-10-25T08:16:36.910 回答
2

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

于 2013-10-25T09:34:15.150 回答
2

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

于 2016-08-30T20:33:42.920 回答
0

考虑到源表不是太大:

  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
    

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

于 2019-02-26T16:15:24.663 回答
-2
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 中选择 *

于 2013-10-25T08:50:09.520 回答