我有SQL Server数据库,我想更改Identity列,因为它以一个大数字开头10010
并且与另一个表相关,现在我有200条记录,并且我想在记录增加之前解决此问题。
更改或重置此列的最佳方法是什么?
我有SQL Server数据库,我想更改Identity列,因为它以一个大数字开头10010
并且与另一个表相关,现在我有200条记录,并且我想在记录增加之前解决此问题。
更改或重置此列的最佳方法是什么?
Answers:
您无法更新身份列。
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
UPDATE YourTable SET IdentityCol = 13
)。SET IDENTITY_INSERT YourTable ON
仅允许INSERT,不允许UPDATE。
如果您的问题正确,您想做类似的事情
update table
set identity_column_name = some value
让我告诉你,这不是一个容易的过程,建议不要使用它,因为可能会有一些foreign key
关联。
但是这里有一些步骤,请坐一张back-up
桌子
步骤1-选择表格的设计视图
第2步-关闭身份列
现在您可以使用update
查询了。
现在redo
执行步骤1和步骤2,然后打开“身份”列
:)
--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
尝试使用DBCC CHECKIDENT
:
DBCC CHECKIDENT ('YourTable', RESEED, 1);
DBCC CHECKIDENT(table_name, RESEED, value)
table_name =提供要重置的表的值
value =初始值为零,以1开头标识列
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不允许您在未指定列名的情况下进行插入
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
但是,以上代码仅在没有主外键关系的情况下有效
使用命令生成器的C#程序员的完整解决方案
首先,您必须了解以下事实:
因此,一旦知道这一点,您所要做的就是。编写自己的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 ();
}
我首先使用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值较高的重复行。
如果您特别需要将主键值更改为其他数字(例如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相同。