如何在SQL Server中更新标识列?


192

我有SQL Server数据库,我想更改Identity列,因为它以一个大数字开头10010并且与另一个表相关,现在我有200条记录,并且我想在记录增加之前解决此问题。

更改或重置此列的最佳方法是什么?

Answers:


268

您无法更新身份列。

SQL Server不允许更新标识列,这与使用update语句处理其他列不同。

尽管有一些替代方法可以实现类似的要求。

  • 需要更新新记录的“身份”列值时

使用DBCC CHECKIDENT 来检查表的当前标识值,如果需要,可以更改标识值。

DBCC CHECKIDENT('tableName', RESEED, NEW_RESEED_VALUE)
  • 需要为现有记录更新“身份”列值时

使用IDENTITY_INSERT 允许将显式值插入表的标识列中。

SET IDENTITY_INSERT YourTable {ON|OFF}

例:

-- Set Identity insert on so that value can be inserted into this column
SET IDENTITY_INSERT YourTable ON
GO
-- Insert the record which you want to update with new value in the identity column
INSERT INTO YourTable(IdentityCol, otherCol) VALUES(13,'myValue')
GO
-- Delete the old row of which you have inserted a copy (above) (make sure about FK's)
DELETE FROM YourTable WHERE ID=3
GO
--Now set the idenetity_insert OFF to back to the previous track
SET IDENTITY_INSERT YourTable OFF

6
DBCC重置下一条新记录,但是现在我要更改现有记录。
Abdulsalam Elsharif

你能举个例子吗?
Abdulsalam Elsharif 2013年

38
@sachin,这不是更新现有
身份,而是

3
@PhillGreggan是的,这是实现此目标的最佳解决方案。您无法在更新普通列时更新“身份”列。
萨钦2015年

17
这个已接受的答案不能回答问题,即如何更新标识列(例如UPDATE YourTable SET IdentityCol = 13)。SET IDENTITY_INSERT YourTable ON仅允许INSERT,不允许UPDATE。
伊恩·博伊德

61

如果您的问题正确,您想做类似的事情

update table
set identity_column_name = some value

让我告诉你,这不是一个容易的过程,建议不要使用它,因为可能会有一些foreign key关联。

但是这里有一些步骤,请坐一张back-up桌子

步骤1-选择表格的设计视图

在此处输入图片说明

第2步-关闭身份列

在此处输入图片说明

现在您可以使用update查询了。

现在redo执行步骤1和步骤2,然后打开“身份”列

参考


1
我有另一个与此表相关的表,我想我不能这样做
Abdulsalam Elsharif 2013年

4
因此,这种说法不明智 :)
2013年

3
@AbdusalamElsherif但是您问如何更改身份列。
狗仔队

@luv至少您已经回答了所提出的问题
Phill Greggan

我使用此过程在开发数据库中设置ID。如果有一条无论如何让我执行的命令,那将是很好的,但这确实可行。
杰夫·戴维斯

55

你需要

set identity_insert YourTable ON

然后删除您的行并以其他身份重新插入。

完成插入操作后,不要忘记关闭identity_insert

set identity_insert YourTable OFF

与为列关闭身份标识相比,这更加容易和安全!
保护者

这样比较安全,并且对少量记录很容易,但是不能正确回答问题。关闭身份,虽然更危险,有时甚至是不可能的,但确实允许您更新身份列。
马修·哈德森

18
--before running this make sure Foreign key constraints have been removed that reference the ID. 

--set table to allow identity to be inserted
SET IDENTITY_INSERT yourTable ON;
GO
--insert everything into a temp table
SELECT * 
INTO #tmpYourTable
FROM yourTable

--clear your table
DELETE FROM yourTable
--insert back all the values with the updated ID column
INSERT INTO yourTable (IDCol, OtherCols)
SELECT ID+1 as updatedID --put any other update logic to the ID here
, OtherCols FROM #tmpYourTable
--drop the temp table
DROP TABLE #tmpYourTable
--put identity back to normal
SET IDENTITY_INSERT yourTable OFF;
GO

1
如果表很大,这只是性能提示,而不是在表上执行删除操作,而不是在表中截断yourTable。它是瞬时的。但是请注意,不要截断,因为它没有记录。
kuklei


5

将您的表复制到没有标识列的新表中。

    select columns into newtable from yourtable

将具有新种子的身份列添加到newtable并将其用作主键

    ALTER TABLE tableName ADD id MEDIUMINT NOT NULL AUTO_INCREMENT KEY


3
SET IDENTITY_INSERT dbo.TableName ON
INSERT INTO dbo.TableName 
(
    TableId, ColumnName1, ColumnName2, ColumnName3
)
VALUES
(
    TableId_Value, ColumnName1_Value, ColumnName2_Value, ColumnName3_Value
)

SET IDENTITY_INSERT dbo.TableName OFF

使用Identity_Insert时,请不要忘记包含列名,因为sql不允许您在未指定列名的情况下进行插入


2

您还可以SET IDENTITY INSERT用来允许您将值插入到标识列中。

例:

SET IDENTITY_INSERT dbo.Tool ON
GO

然后,您可以将所需的值插入到身份列中。


1
ALTER TABLE tablename add newcolumn int
update tablename set newcolumn=existingcolumnname
ALTER TABLE tablename DROP COLUMN existingcolumnname;
EXEC sp_RENAME 'tablename.oldcolumn' , 'newcolumnname', 'COLUMN'
update tablename set newcolumnname=value where condition

但是,以上代码仅在没有主外键关系的情况下有效


1

使用命令生成器的C#程序员的完整解决方案

首先,您必须了解以下事实:

  • 无论如何,您都无法修改标识列,因此必须删除该行并重新添加新标识。
  • 您不能从列中删除标识属性(必须将其删除到列)
  • .net中的自定义命令构建器始终跳过身份列,因此您不能将其用于此目的。

因此,一旦知道这一点,您所要做的就是。编写自己的SQL Insert语句,或者编写自己的插入命令生成器。或者使用我为您编程的这一程序。给定一个DataTable,生成SQL Insert脚本:

public static string BuildInsertSQLText ( DataTable table )
{
    StringBuilder sql = new StringBuilder(1000,5000000);
    StringBuilder values = new StringBuilder ( "VALUES (" );
    bool bFirst = true;
    bool bIdentity = false;
    string identityType = null;

    foreach(DataRow myRow in table.Rows) 
    {
        sql.Append( "\r\nINSERT INTO " + table.TableName + " (" );

        foreach ( DataColumn column in table.Columns )
        {
            if ( column.AutoIncrement )
            {
                bIdentity = true;

                switch ( column.DataType.Name )
                {
                    case "Int16":
                        identityType = "smallint";
                        break;
                    case "SByte":
                        identityType = "tinyint";
                        break;
                    case "Int64":
                        identityType = "bigint";
                        break;
                    case "Decimal":
                        identityType = "decimal";
                        break;
                    default:
                        identityType = "int";
                        break;
                }
            }
            else
            {
                if ( bFirst )
                    bFirst = false;
                else
                {
                    sql.Append ( ", " );
                    values.Append ( ", " );
                }
                sql.Append ("[");
                sql.Append ( column.ColumnName );
                sql.Append ("]");

                //values.Append (myRow[column.ColumnName].ToString() );

                if (myRow[column.ColumnName].ToString() == "True")
                    values.Append("1");
                else if (myRow[column.ColumnName].ToString() == "False")
                    values.Append("0");
                else if(myRow[column.ColumnName] == System.DBNull.Value)    
                    values.Append ("NULL");
                else if(column.DataType.ToString().Equals("System.String"))
                {
                    values.Append("'"+myRow[column.ColumnName].ToString()+"'");
                }
                else
                    values.Append (myRow[column.ColumnName].ToString());
                    //values.Append (column.DataType.ToString() );
            }
        }
        sql.Append ( ") " );
        sql.Append ( values.ToString () );
        sql.Append ( ")" );

        if ( bIdentity )
        {
            sql.Append ( "; SELECT CAST(scope_identity() AS " );
            sql.Append ( identityType );
            sql.Append ( ")" );
        }
        bFirst = true;
        sql.Append(";");
        values = new StringBuilder ( "VALUES (" );
    } //fin foreach
    return sql.ToString ();
}

0

我首先使用DBCC解决了此问题,然后使用了插入。例如,如果您的表是

首先,在表格上将新的当前ID值设置为NEW_RESEED_VALUE

MyTable {IDCol,colA,colB}

    DBCC CHECKIDENT('MyTable', RESEED, NEW_RESEED_VALUE)

那么你可以使用

    insert into MyTable (colA, ColB) select colA, colB from MyTable

这将复制您的所有记录,但使用的新IDCol值以NEW_RESEED_VALUE开头。然后,一旦删除/移动了它们的外键引用(如果有),则可以删除ID值较高的重复行。


1
这是一个不错的主意,但是New_reseed_value是当前的种子,下一个将使用的数字将比该值大1。因此,如果希望下一个插入的行成为标识10,则必须将NEW_RESEED_VALUE设置为
9。– LarryBud

0

您可以使用以下代码创建一个新表。

SELECT IDENTITY (int, 1, 1) AS id, column1, column2
INTO dbo.NewTable
FROM dbo.OldTable

然后删除旧数据库,并将新数据库重命名为旧数据库的名称。注意:column1和column2代表旧表中要保留在新表中的所有列。


0

如果您特别需要将主键值更改为其他数字(例如123-> 1123)。身份属性阻止更改PK值。设置Identity_insert将不起作用。如果您具有级联删除操作,则不建议执行插入/删除操作(除非您关闭参照完整性检查)。

该脚本将关闭PK的身份:

***********************

sp_configure 'allow update', 1
go
reconfigure with override
go


update syscolumns set colstat = 0 --turn off bit 1 which indicates identity column
where id = object_id('table_name') and name = 'column_name'
go


exec sp_configure 'allow update', 0
go
reconfigure with override
go

***********************

接下来,您可以设置关系,以便它们将更新外键引用。否则,您需要关闭关系强制。该SO链接显示如何: 如何使用T-SQL临时禁用外键约束?

现在,您可以进行更新了。我编写了一个简短的脚本,以基于相同的列名编写所有更新SQL(在我的情况下,我需要将CaseID增加1,000,000:

select 
'update ['+c.table_name+'] SET ['+Column_Name+']=['+Column_Name+']+1000000'
from Information_Schema.Columns as c
JOIN Information_Schema.Tables as t ON t.table_Name=c.table_name and t.Table_Schema=c.table_schema and t.table_type='BASE TABLE'
where Column_Name like 'CaseID' order by Ordinal_position

最后,重新启用参照完整性,然后重新启用主键上的“标识”列。

注意:我看到一些人在这些问题上问为什么。就我而言,我必须将第二个生产实例中的数据合并到主数据库中,以便可以关闭第二个实例。我只需要操作数据的所有PK / FK不冲突即可。元数据FK相同。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.