2017-05-03 58 views
1

我需要自动增量(标识)属性添加到一些表格的ID列。我已经做了一些研究,表明我需要首先实际删除ID列,然后再将它们添加为IDENTITY列。然而,当我尝试删除ID列,收到错误消息的名单基本上是说:添加自动增量列和处理约束[SQL服务器]

-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

下降两个FKS第一 – Sami

回答

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 '[email protected]+' 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 '[email protected]+' 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 '[email protected] +' ADD CONSTRAINT '[email protected]+' PRIMARY KEY CLUSTERED ('[email protected]+' 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 '[email protected]+' WITH CHECK ADD CONSTRAINT '+ @FKName+' FOREIGN KEY(['+REPLACE(@FKColumnName,',','],[')+']) 
     REFERENCES ['[email protected]+'] (['+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转换成一个集群和原代码已经从各种渠道采取和修改,以适合我的需要。我无法承认所有这些代码。

我也注释掉的代码的执行,这样你可以看到它会在SSMS消息标签做的事情。

+0

好,非常感谢,但我的时候我会删除了所有的外键约束,我怎样才能确保我相同的重建他们算账? – Platus

+0

查看#FKAgainstTableList,它将您需要的所有信息放入脚本开始处的临时表中。然后它使用这个表格来获得重建FK时的细节。如果你运行这个命令,你会在SSMS的消息标签中看到它要运行的命令。它不会执行,因为我已经注释了exec函数。 –

0

你需要做的首先你需要做的,使你的身份列的工作是什么之前,删除被引用的外键。