【问题标题】:set identity on the column在列上设置标识
【发布时间】:2011-07-08 01:37:38
【问题描述】:

如何使用 T-SQL 修改表并在 PK 列上设置标识?

感谢帮助

【问题讨论】:

标签: sql tsql sql-server-2008


【解决方案1】:

您不能将现有列修改为具有 IDENTITY“属性” - 您必须:

  • 创建一个具有相同结构(但设置了 IDENTITY)的新表,
  • 为这个新表打开IDENTITY_INSERT
  • 将旧表中的行插入新表中,
  • 删除旧表,然后,
  • 将新表重命名为旧表名。

如果涉及外键,您还需要修复它们。

【讨论】:

  • 您实际上可以通过在单用户模式下启动实例并修改系统表来做到这一点。令人烦恼的是,在当前版本中没有安全/受支持的方式来更新此元数据。
  • @Martin - 很有趣,但你会推荐这样做的人吗?
  • @Martin - 这似乎是 RedGate 会在某个时候制作的工具......
  • @Damien - 绝对不会,除非他们只是出于对测试数据库的好奇而这样做。
【解决方案2】:

这个问题的大多数解决方案的问题是它们需要向表中添加新列或完全重建表。

两者都可能需要大量的锁定和记录活动,我一直觉得这很烦人,因为这只是元数据的更改,根本不需要触摸数据页面(实际上,可以通过启动单用户模式下的实例,并在sys.syscolpars 中弄乱了一些列,但这是未记录/不受支持的。)

但是,this connect item 上发布的解决方法显示了一种完全受支持的方法,可以使用 ALTER TABLE...SWITCH 将其变为仅更改元数据(信用 SQLKiwi

示例代码。

设置没有identity 列的测试表。

CREATE TABLE dbo.tblFoo 
(
bar INT PRIMARY KEY,
filler CHAR(8000),
filler2 CHAR(49)
)


INSERT INTO dbo.tblFoo (bar)
SELECT TOP (10000) ROW_NUMBER() OVER (ORDER BY (SELECT 0))
FROM master..spt_values v1, master..spt_values v2

将其更改为具有 identity 列(或多或少是即时的)。

BEGIN TRY;
    BEGIN TRANSACTION;

    /*Using DBCC CHECKIDENT('dbo.tblFoo') is slow so use dynamic SQL to
      set the correct seed in the table definition instead*/
    DECLARE @TableScript nvarchar(max)
    SELECT @TableScript = 
    '
    CREATE TABLE dbo.Destination(
        bar INT IDENTITY(' + 
                     CAST(ISNULL(MAX(bar),0)+1 AS VARCHAR) + ',1)  PRIMARY KEY,
        filler CHAR(8000),
        filler2 CHAR(49)
        )

        ALTER TABLE dbo.tblFoo SWITCH TO dbo.Destination;
    '       
    FROM dbo.tblFoo
    WITH (TABLOCKX,HOLDLOCK)

    EXEC(@TableScript)


    DROP TABLE dbo.tblFoo;

    EXECUTE sp_rename N'dbo.Destination', N'tblFoo', 'OBJECT';


    COMMIT TRANSACTION;
END TRY
BEGIN CATCH
    IF XACT_STATE() <> 0 ROLLBACK TRANSACTION;
    PRINT ERROR_MESSAGE();
END CATCH;

测试结果。

INSERT INTO dbo.tblFoo (filler,filler2) 
OUTPUT inserted.*
VALUES ('foo','bar')

给予

bar         filler    filler2
----------- --------- ---------
10001       foo       bar      

清理

DROP TABLE dbo.tblFoo

【讨论】:

    【解决方案3】:

    这是您正在寻找的答案吗?

    DBCC CHECKIDENT( 
        'DBName.dbo.TableName'
        ,RESEED --[, new_reseed_value ]
    )
    

    使用示例:

    DBCC CHECKIDENT( 
        'DBName.dbo.TableName'
    )
    

    检查身份信息:当前身份值“1”,当前列值“1211031236”。 DBCC 执行完成。如果 DBCC 打印错误消息,请联系您的系统管理员。

    DBCC CHECKIDENT( 
        'DBName.dbo.TableName'
        ,RESEED --[, new_reseed_value ]
    )
    

    检查身份信息:当前身份值“1211031236”,当前列值“1211031236”。 DBCC 执行完成。如果 DBCC 打印错误消息,请联系您的系统管理员。

    【讨论】:

      【解决方案4】:

      实际上,您可以修改列上的 IDENTITY。 请通读这篇文章http://www.sqlmag.com/article/tsql3/adding-the-identity-property-to-an-existing-column.aspx

      不过,它需要比 ALTER TABLE tab ALTER COLUMN col SET IDENTITY 更多的代码

      【讨论】:

      • 是的,您可以通过 Enterprise Manager 或 SSMS 执行此操作 - 但它实际上在“幕后”所做的正是我上面所描述的。
      • 引用一篇 10 年前的文章可能也不是最好的选择,该文章指的是比 OP 询问的版本早 2 个版本的软件...
      • 我认为较新版本的 SQL Server 是向后兼容的。也许我错了。
      • 此外,SQL 语法比 SQL Server 2000 更古老。不过,它仍然每天用于新的查询。它是否因为它太旧而降低了准确性?
      • 我不知道为什么人们对你的推荐如此愤怒。 SSMS 中的工具使这些东西比大多数本土工具更容易和更安全。到目前为止,所有显示的方法也没有考虑重建 PK、FK、触发器、相关视图等。就我而言,你的答案实际上是最好的答案。
      【解决方案5】:

      您需要使用 ALTER TABLE 命令 - 始终首先在开发或预生产中进行测试!

      示例 G 似乎最符合您的要求:

      CREATE TABLE dbo.doc_exe (column_a INT CONSTRAINT column_a_un UNIQUE) ; 走 ALTER TABLE dbo.doc_exe 添加

      -- 添加一个 PRIMARY KEY 标识列。 column_b INT IDENTITY CONSTRAINT column_b_pk 主键,

      http://msdn.microsoft.com/en-us/library/ms190273.aspx

      【讨论】:

        【解决方案6】:

        由于您只能忽略 insert 的标识列,而不是 update,因此您需要一个中间表。这是一个例子:

        create table TestTable (pk int constraint PK_TestTable primary key, 
            name varchar(30))
        create table TestTable2 (pk int constraint PK_TestTable identity primary key, 
            name varchar(30))
        set identity_insert TestTable2 on
        insert TestTable2 (pk, name) select pk, name from TestTable
        set identity_insert TestTable2 off
        drop table TestTable
        exec sp_rename 'TestTable2', 'TestTable'
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-12-14
          • 1970-01-01
          • 2016-04-18
          • 1970-01-01
          • 1970-01-01
          • 2012-01-12
          • 1970-01-01
          • 2022-10-15
          相关资源
          最近更新 更多