删除给定表的FK的存储过程

时间:2014-08-19 15:05:22

标签: sql sql-server-2012

我需要创建一个存储过程:

  1. 接受表名作为参数
  2. 查找其依赖项(FK)
  3. 删除它们
  4. 截断表格
  5. 到目前为止,我基于http://www.mssqltips.com/sqlservertip/1376/disable-enable-drop-and-recreate-sql-server-foreign-keys/创建了以下内容。我的问题是以下脚本成功执行1和2并生成查询以更改表但实际上并不执行它们。换句话说,如何执行生成的“Alter Table ...”查询以实际删除FK?

    CREATE PROCEDURE DropDependencies(@TableName VARCHAR(50))
    AS
    BEGIN
    SELECT 'ALTER TABLE ' + OBJECT_SCHEMA_NAME(parent_object_id) + '.[' + OBJECT_NAME(parent_object_id) + '] DROP CONSTRAINT ' + name
    FROM sys.foreign_keys WHERE referenced_object_id=object_id(@TableName)
    END
    
    
    
    EXEC DropDependencies 'TableName'
    

    任何想法都表示赞赏!

    更新: 我将光标添加到SP但我仍然得到并且错误: “消息203,级别16,状态2,过程DropRestoreDependencies,第75行     名称'ALTER TABLE [dbo]。[ChildTable] DROP CONSTRAINT [FK__ChileTable__ParentTable__745C7C5D]'不是有效的标识符。“

    这是更新后的SP: CREATE PROCEDURE DropRestoreDependencies(@schemaName sysname,@ tableName sysname)     如     开始     设置NOCOUNT

    DECLARE @operation VARCHAR(10)  
    
    
    SET @operation = 'DROP' --ENABLE, DISABLE, DROP  
    
    
    DECLARE @cmd NVARCHAR(1000) 
    
    DECLARE   
       @FK_NAME sysname,  
       @FK_OBJECTID INT,  
       @FK_DISABLED INT,  
       @FK_NOT_FOR_REPLICATION INT,  
       @DELETE_RULE    smallint,     
       @UPDATE_RULE    smallint,     
       @FKTABLE_NAME sysname,  
       @FKTABLE_OWNER sysname,  
       @PKTABLE_NAME sysname,  
       @PKTABLE_OWNER sysname,  
       @FKCOLUMN_NAME sysname,  
       @PKCOLUMN_NAME sysname,  
       @CONSTRAINT_COLID INT  
    
    
    DECLARE cursor_fkeys CURSOR FOR   
       SELECT  Fk.name,  
               Fk.OBJECT_ID,   
               Fk.is_disabled,   
               Fk.is_not_for_replication,   
               Fk.delete_referential_action,   
               Fk.update_referential_action,   
               OBJECT_NAME(Fk.parent_object_id) AS Fk_table_name,   
               schema_name(Fk.schema_id) AS Fk_table_schema,   
               TbR.name AS Pk_table_name,   
               schema_name(TbR.schema_id) Pk_table_schema  
       FROM    sys.foreign_keys Fk LEFT OUTER JOIN   
               sys.tables TbR ON TbR.OBJECT_ID = Fk.referenced_object_id --inner join   
       WHERE   TbR.name = @tableName  
               AND schema_name(TbR.schema_id) = @schemaName  
    
    OPEN cursor_fkeys  
    
    FETCH NEXT FROM   cursor_fkeys   
       INTO @FK_NAME,@FK_OBJECTID,  
           @FK_DISABLED,  
           @FK_NOT_FOR_REPLICATION,  
           @DELETE_RULE,     
           @UPDATE_RULE,     
           @FKTABLE_NAME,  
           @FKTABLE_OWNER,  
           @PKTABLE_NAME,  
           @PKTABLE_OWNER  
    
    WHILE @@FETCH_STATUS = 0   
    BEGIN   
    
       -- create statement for dropping FK and also for recreating FK  
       IF @operation = 'DROP'  
       BEGIN  
    
           -- drop statement  
           SET @cmd = 'ALTER TABLE [' + @FKTABLE_OWNER + '].[' + @FKTABLE_NAME   
           + ']  DROP CONSTRAINT [' + @FK_NAME + ']'     
    
          EXEC @cmd  
    
           -- create process  
           DECLARE @FKCOLUMNS VARCHAR(1000), @PKCOLUMNS VARCHAR(1000), @COUNTER INT  
    
           -- create cursor to get FK columns  
           DECLARE cursor_fkeyCols CURSOR FOR   
           SELECT  COL_NAME(Fk.parent_object_id, Fk_Cl.parent_column_id) AS Fk_col_name,   
                   COL_NAME(Fk.referenced_object_id, Fk_Cl.referenced_column_id) AS Pk_col_name  
           FROM    sys.foreign_keys Fk LEFT OUTER JOIN   
                   sys.tables TbR ON TbR.OBJECT_ID = Fk.referenced_object_id INNER JOIN   
                   sys.foreign_key_columns Fk_Cl ON Fk_Cl.constraint_object_id = Fk.OBJECT_ID   
           WHERE   TbR.name = @tableName  
                   AND schema_name(TbR.schema_id) = @schemaName  
                   AND Fk_Cl.constraint_object_id = @FK_OBJECTID -- added 6/12/2008  
           ORDER BY Fk_Cl.constraint_column_id  
    
           OPEN cursor_fkeyCols  
    
           FETCH NEXT FROM    cursor_fkeyCols INTO @FKCOLUMN_NAME,@PKCOLUMN_NAME  
    
           SET @COUNTER = 1  
           SET @FKCOLUMNS = ''  
           SET @PKCOLUMNS = ''  
    
           WHILE @@FETCH_STATUS = 0   
           BEGIN   
    
               IF @COUNTER > 1   
               BEGIN  
                   SET @FKCOLUMNS = @FKCOLUMNS + ','  
                   SET @PKCOLUMNS = @PKCOLUMNS + ','  
               END  
    
               SET @FKCOLUMNS = @FKCOLUMNS + '[' + @FKCOLUMN_NAME + ']'  
               SET @PKCOLUMNS = @PKCOLUMNS + '[' + @PKCOLUMN_NAME + ']'  
    
               SET @COUNTER = @COUNTER + 1  
    
               FETCH NEXT FROM    cursor_fkeyCols INTO @FKCOLUMN_NAME,@PKCOLUMN_NAME  
           END  
    
           CLOSE cursor_fkeyCols   
           DEALLOCATE cursor_fkeyCols   
    
    
    
       END  
    
       FETCH NEXT FROM    cursor_fkeys   
          INTO @FK_NAME,@FK_OBJECTID,  
               @FK_DISABLED,  
               @FK_NOT_FOR_REPLICATION,  
               @DELETE_RULE,     
               @UPDATE_RULE,     
               @FKTABLE_NAME,  
               @FKTABLE_OWNER,  
               @PKTABLE_NAME,  
               @PKTABLE_OWNER  
    END  
    
    CLOSE cursor_fkeys   
    DEALLOCATE cursor_fkeys 
    END
    

    用于跑步使用:

    EXEC DropRestoreDependencies dbo, ParentTable
    

3 个答案:

答案 0 :(得分:1)

问题是你只准备SQL语句而不是执行它(我认为)

CREATE PROCEDURE DropDependencies(@TableName VARCHAR(50))
AS
BEGIN
DECLARE @SQL nvarchar(max)
SELECT @SQL = 'ALTER TABLE ' + OBJECT_SCHEMA_NAME(parent_object_id) + '.[' + OBJECT_NAME(parent_object_id) + '] DROP CONSTRAINT ' + name
FROM sys.foreign_keys WHERE referenced_object_id=object_id(@TableName)
EXEC @SQL
END


EXEC DropDependencies 'TableName'

每当从构造的字符串中使用EXEC时,请确保您不会受到SQL注入攻击的攻击。<​​/ p>

答案 1 :(得分:1)

使用游标浏览SELECT结果,使用单列填充变量,并使用EXEC(@YourVariable)执行该查询。一定要在变量周围使用parens!

答案 2 :(得分:0)

试用SP_ExecuteSQLExec。我看到你正在使用Exec。也许SP_ExecuteSQL可行吗?