我需要将autoincrement(IDENTITY)属性添加到某些表的ID列。我做过一些研究表明我需要先删除ID列,然后再将它们添加为IDENTITY列。但是,当我尝试删除ID列时,我得到一个错误消息列表,主要是说:
-The object 'FK_OTHER_TABLE_MY_ID' is dependent on column 'MY_ID'. (foreign key constraint apparently)
-The object 'IDX_PK_MY_TABLE' is dependent on column 'my_ID' (Primary key constraint).
所以我可以删除约束(外键在我的表中的其他表和主键中),然后再次添加它们。
如果是这样,是否有一种方法可以在引用我的ID列时为所有外键执行此操作,这种方法比只丢失错误消息中定义的约束更容易出错。
答案 0 :(得分:0)
在执行使标识列工作所需的操作之前,您需要先删除引用的外键。
答案 1 :(得分:0)
您可以使用sp_fkeys
根据表格查找所有外键;
EXEC sp_fkeys 'TableName'
如果你想要一个脚本,那么你可以做这样的动态。中间有一个部分,您可以将脚本改为IDENTITY
字段;
DECLARE @PKTableName VARCHAR(100),
@PKName varchar(100),
@FKName varchar(100),
@sql varchar(max),
@PKcolumnName varchar(30),
@FKtable VARCHAR(100),
@FKColumnName VARCHAR(100),
@parentColumnNumber int
SET @PKTableName = 'YourTableName'
IF OBJECT_ID('tempdb..#FKAgainstTableList') IS NOT NULL
DROP TABLE #FKAgainstTableList
CREATE TABLE #FKAgainstTableList (FKTable varchar(100), FKName varchar(100), FKColumnName varchar(100))
IF OBJECT_ID('tempdb..#PKDetails') IS NOT NULL
DROP TABLE #PKDetails
CREATE TABLE #PKDetails (PKName varchar(100), PKColumnName varchar(100), Ordinal_Position int)
/* Let's gather details about our primary key */
INSERT INTO #PKDetails (PKName, PKColumnName, Ordinal_Position)
SELECT
CONSTRAINT_NAME
,COLUMN_NAME
,ORDINAL_POSITION
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE OBJECTPROPERTY(OBJECT_ID(constraint_name), 'IsPrimaryKey') = 1
AND table_name = @PKTableName
/* We need this when we're putting the FK's back on at the end */
SET @PKName = (SELECT DISTINCT PKName FROM #PKDetails)
SELECT @PKcolumnName = COALESCE(@PKcolumnName + ' ASC,', '') + PKColumnName FROM #PKDetails ORDER BY ORDINAL_POSITION ASC
/* Let's grab the foreign keys and put them into a temp table */
INSERT INTO #FKAgainstTableList (FKTable, FKName, FKColumnName)
SELECT DISTINCT
KC.TABLE_NAME
,KC.CONSTRAINT_NAME
,STUFF((SELECT ',' + KCU.COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU
JOIN sys.foreign_keys FK ON KCU.CONSTRAINT_NAME = FK.name
WHERE OBJECT_NAME(fk.referenced_object_id) = @PKTableName AND KCU.CONSTRAINT_NAME = KC.CONSTRAINT_NAME
ORDER BY ORDINAL_POSITION ASC
FOR XML PATH('')
),1,1,'')
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE KC
WHERE STUFF((SELECT ',' + KCU.COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU
JOIN sys.foreign_keys FK ON KCU.CONSTRAINT_NAME = FK.name
WHERE OBJECT_NAME(fk.referenced_object_id) = @PKTableName AND KCU.CONSTRAINT_NAME = KC.CONSTRAINT_NAME
ORDER BY ORDINAL_POSITION ASC
FOR XML PATH('')
),1,1,'') IS NOT NULL
/* Disable constraint on FK Tables */
DECLARE cursor1 CURSOR FOR
SELECT * FROM #FKAgainstTableList
PRINT @sql
OPEN cursor1
FETCH NEXT FROM cursor1 INTO @FKtable,@FKName,@FKColumnName
WHILE @@FETCH_STATUS = 0
BEGIN
SET @sql ='ALTER TABLE '+@FKtable+' DROP CONSTRAINT '+ @FKName
PRINT @sql
--EXEC(@sql)
FETCH NEXT FROM cursor1 INTO @FKtable,@FKName,@FKColumnName
END
CLOSE cursor1
DEALLOCATE cursor1
/* Let's drop that PK */
IF EXISTS (SELECT 1 FROM sys.indexes WHERE object_id = OBJECT_ID(@PKTableName) AND name = @PKName)
BEGIN
SET @sql = 'ALTER TABLE '+@PKTableName+' DROP CONSTRAINT '+ @PKName
PRINT @sql
--EXEC(@sql)
END
/* Put your script here to drop and create the IDENTITY field */
/* OK, let's apply that PK (clustered) */
SET @sql = 'ALTER TABLE '+@PKTableName +' ADD CONSTRAINT '+@PKName+' PRIMARY KEY CLUSTERED ('+@PKcolumnName+' ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY]'
PRINT(@sql)
--EXEC(@sql)
/* Put the FK's back on */
DECLARE cursor2 CURSOR FOR
SELECT * FROM #FKAgainstTableList
OPEN cursor2
FETCH NEXT FROM cursor2 INTO @FKtable,@FKName,@FKColumnName
WHILE @@FETCH_STATUS = 0
BEGIN
SET @sql = 'ALTER TABLE '+@FKtable+' WITH CHECK ADD CONSTRAINT '+ @FKName+' FOREIGN KEY(['+REPLACE(@FKColumnName,',','],[')+'])
REFERENCES ['+@PKTableName+'] (['+REPLACE(@PKcolumnName,' ASC,','],[')+'])'
PRINT(@sql)
--EXEC(@sql)
FETCH NEXT FROM cursor2 INTO @FKtable,@FKName,@FKColumnName
END
CLOSE cursor2
DEALLOCATE cursor2
/* Tidy up */
DROP TABLE #FKAgainstTableList
DROP TABLE #PKDetails
请注意,我已经将此脚本用于将非群集PK转换为群集PK所需的一些工作,并且原始代码已从各种来源获取并根据我的需要进行修改。我不能赞同所有这些代码。
我还注释掉了代码的执行情况,以便您可以在SSMS
的消息标签中查看它将要执行的操作。