删除表中的所有外键

时间:2010-06-14 16:01:10

标签: tsql sql-server-2008 foreign-keys

我有这个脚本在sql server 2005中运行

-- t-sql scriptlet to drop all constraints on a table
DECLARE @database nvarchar(50)
DECLARE @table nvarchar(50)

set @database = 'dotnetnuke'
set @table = 'tabs'

DECLARE @sql nvarchar(255)
WHILE EXISTS(select * from INFORMATION_SCHEMA.TABLE_CONSTRAINTS where constraint_catalog = @database and table_name = @table)
BEGIN
    select    @sql = 'ALTER TABLE ' + @table + ' DROP CONSTRAINT ' + CONSTRAINT_NAME 
    from    INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
    where    constraint_catalog = @database and 
            table_name = @table
    exec    sp_executesql @sql
END

它在SQL Server 2008中不起作用。如何轻松删除某个表的所有外键约束?有人有更好的剧本吗?

5 个答案:

答案 0 :(得分:7)

有一种更简单的方法。 那为什么呢? 脚本:

`select ' alter table ' + schema_name(Schema_id)+'.'+ object_name(parent_object_id)
+ '  DROP CONSTRAINT  ' +  name   from sys.foreign_keys f1`

将为所有外键编写drop的脚本

答案 1 :(得分:1)

我注意到您没有在原始查询中过滤外键。此外,您无法过滤数据库名称上的INFORMATION_SCHEMA视图,因为它们将始终返回当前数据库。而是尝试这样的事情:

修改

从评论中,您说您正在尝试删除指定表上的所有外键和指向同一个表的所有外键,以便您可以删除该表。我已经调整了例程来做到这一点。我建议你调整问题以反映这一点。应该注意的是,所有真正需要的是删除指向相关表的外键(联合中的第二个查询),因为当表被删除时,表本身的任何约束都将被删除。

Declare @Database nvarchar(128)
Declare @ConstraintName nvarchar(128)
Declare @TableName nvarchar(128)
Declare @BaseSql nvarchar(max)
Declare @Sql nvarchar(max)
Declare @Tables Cursor

Set @Database = 'dotnetnuke'
Set @TableName = 'tabs'
Set @BaseSQL = 'Use DATABASENAME; Alter Table TABLENAME Drop Constraint CONSTRAINTNAME'

Set @Tables = Cursor Fast_Forward For
    Select TABLE_NAME, CONSTRAINT_NAME
    From INFORMATION_SCHEMA.TABLE_CONSTRAINTS
    Where CONSTRAINT_CATALOG = @Database
        And TABLE_NAME = @TableName
        And CONSTRAINT_TYPE = 'FOREIGN KEY'
    Union All
    Select FK.TABLE_NAME, RC.CONSTRAINT_NAME
    From INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS As RC
        Join INFORMATION_SCHEMA.TABLE_CONSTRAINTS As TC
            On TC.CONSTRAINT_NAME = RC.UNIQUE_CONSTRAINT_NAME
                And TC.TABLE_NAME = @TableName
        Join INFORMATION_SCHEMA.TABLE_CONSTRAINTS As FK
            On FK.CONSTRAINT_NAME = RC.CONSTRAINT_NAME

Open @Tables
Fetch Next From @Tables Into @TableName, @ConstraintName

While @@Fetch_Status = 0
Begin
    Set @Sql = Replace(@BaseSql, 'DATABASENAME', Quotename(@Database))
    Set @Sql = Replace(@Sql, 'TABLENAME', Quotename(@TableName))
    Set @Sql = Replace(@Sql, 'CONSTRAINTNAME', Quotename(@ConstraintName))

    Exec(@Sql)
    Fetch Next From @Tables Into @TableName, @ConstraintName
End

Close @Tables
Deallocate @Tables

答案 2 :(得分:0)

编写的脚本假定您在包含要删除的对象的数据库中运行它。您是从另一个数据库(例如master或tempdb)运行它吗?也许您的默认(登录时)数据库已更改?

(我在其中一个数据库上尝试时也注意到它不考虑模式。这可能值得在一段时间内添加。)

答案 3 :(得分:0)

这是相当古老的帖子,但可能有助于某人。

从John Paul Cook的这篇文章中获取代码的核心:Script to create all foreign keys

我已经对代码进行了一些修改,因此我们可以按表(变量@TARGET_TABLE)和模式(变量@TARGET_SCHEMA)名称进行过滤。

我不得不修改脚本,以便它还打印其他表拥有的那些外键的脚本,引用@TARGET_TABLE

您必须设置脚本开头的以下三个变量:

  • @TARGET:将其设置为“DROP”或“CREATE”是否要生成用于创建FK或删除它们的脚本。
  • @TARGET_TABLE:表的名称(将使用当前选定的数据库)。
  • @TARGET_SCHEMA:然后拥有该表的架构的名称。

<强>说明:

  1. 它还编写其他表所拥有的依赖外键的脚本 引用@TARGET_TABLE表
  2. 生成的脚本没有 包含[USE SomeDatabase]语句
  3. 脚本如下所示:

    -- User variables
    DECLARE @TARGET AS VARCHAR(10); -- SET to 'DROP' or 'CREATE'
    DECLARE @TARGET_TABLE AS SYSNAME; -- TABLE WHOSE FOREIGN-KEY WILL BE SCRIPTED
    DECLARE @TARGET_SCHEMA AS SYSNAME; -- SCHEMA OF THE TABLE
    
    SET @TARGET = 'DROP';
    SET @TARGET_SCHEMA = 'dbo';
    SET @TARGET_TABLE = 'tabs';
    
    -- Other variables
    DECLARE @schema_name sysname;
    DECLARE @table_name sysname;
    DECLARE @constraint_name sysname;
    DECLARE @constraint_object_id int;
    DECLARE @referenced_object_name sysname;
    DECLARE @is_disabled bit;
    DECLARE @is_not_for_replication bit;
    DECLARE @is_not_trusted bit;
    DECLARE @delete_referential_action tinyint;
    DECLARE @update_referential_action tinyint;
    DECLARE @tsql nvarchar(4000);
    DECLARE @tsql2 nvarchar(4000);
    DECLARE @fkCol sysname;
    DECLARE @pkCol sysname;
    DECLARE @col1 bit;
    
    DECLARE FKcursor CURSOR FOR
    (
        SELECT 
            OBJECT_SCHEMA_NAME(parent_object_id)
            , OBJECT_NAME(parent_object_id)
            , name
            , OBJECT_NAME(referenced_object_id)
            , object_id
            , is_disabled, is_not_for_replication, is_not_trusted
            , delete_referential_action, update_referential_action
        FROM 
            sys.foreign_keys
        WHERE
            OBJECT_NAME(parent_object_id) = @TARGET_TABLE
            AND
            OBJECT_SCHEMA_NAME(parent_object_id) = @TARGET_SCHEMA
    )   
    UNION ALL
    (
        SELECT 
            OBJECT_SCHEMA_NAME(parent_object_id)
            , OBJECT_NAME(parent_object_id)
            , name
            , OBJECT_NAME(referenced_object_id)
            , object_id
            , is_disabled, is_not_for_replication, is_not_trusted
            , delete_referential_action, update_referential_action
        FROM 
            sys.foreign_keys
        WHERE
            OBJECT_NAME(referenced_object_id) = @TARGET_TABLE
            AND 
            OBJECT_SCHEMA_NAME(parent_object_id) = @TARGET_SCHEMA
    )
    ORDER BY 1,2;
    
    OPEN FKcursor;
    
    FETCH NEXT FROM FKcursor INTO @schema_name, @table_name, @constraint_name
        , @referenced_object_name, @constraint_object_id
        , @is_disabled, @is_not_for_replication, @is_not_trusted
        , @delete_referential_action, @update_referential_action;
    
    WHILE @@FETCH_STATUS = 0
    
    BEGIN
        IF @TARGET <> 'CREATE'
            SET @tsql = 'ALTER TABLE '
                      + QUOTENAME(@schema_name) + '.' + QUOTENAME(@table_name)
                      + ' DROP CONSTRAINT ' + QUOTENAME(@constraint_name) + ';';
        ELSE
            BEGIN
            SET @tsql = 'ALTER TABLE '
                      + QUOTENAME(@schema_name) + '.' + QUOTENAME(@table_name)
                      + CASE @is_not_trusted
                            WHEN 0 THEN ' WITH CHECK '
                            ELSE ' WITH NOCHECK '
                        END
                      + ' ADD CONSTRAINT ' + QUOTENAME(@constraint_name)
                      + ' FOREIGN KEY ('
            SET @tsql2 = '';
            DECLARE ColumnCursor CURSOR FOR
                select COL_NAME(fk.parent_object_id, fkc.parent_column_id)
                     , COL_NAME(fk.referenced_object_id, fkc.referenced_column_id)
                from sys.foreign_keys fk
                inner join sys.foreign_key_columns fkc
                on fk.object_id = fkc.constraint_object_id
                where fkc.constraint_object_id = @constraint_object_id
                order by fkc.constraint_column_id;
            OPEN ColumnCursor;
    
            SET @col1 = 1;
    
            FETCH NEXT FROM ColumnCursor INTO @fkCol, @pkCol;
            WHILE @@FETCH_STATUS = 0
            BEGIN
                IF (@col1 = 1)
                    SET @col1 = 0
                ELSE
                BEGIN
                    SET @tsql = @tsql + ',';
                    SET @tsql2 = @tsql2 + ',';
                END;
                SET @tsql = @tsql + QUOTENAME(@fkCol);
                SET @tsql2 = @tsql2 + QUOTENAME(@pkCol);
                FETCH NEXT FROM ColumnCursor INTO @fkCol, @pkCol;
            END;
            CLOSE ColumnCursor;
            DEALLOCATE ColumnCursor;
    
            SET @tsql = @tsql + ' ) REFERENCES ' + QUOTENAME(@schema_name) + '.' + QUOTENAME(@referenced_object_name)
                      + ' (' + @tsql2 + ')';           
    
            SET @tsql = @tsql
                      + ' ON UPDATE ' + CASE @update_referential_action
                                            WHEN 0 THEN 'NO ACTION '
                                            WHEN 1 THEN 'CASCADE '
                                            WHEN 2 THEN 'SET NULL '
                                            ELSE 'SET DEFAULT '
                                        END
                      + ' ON DELETE ' + CASE @delete_referential_action
                                            WHEN 0 THEN 'NO ACTION '
                                            WHEN 1 THEN 'CASCADE '
                                            WHEN 2 THEN 'SET NULL '
                                            ELSE 'SET DEFAULT '
                                        END
                      + CASE @is_not_for_replication
                            WHEN 1 THEN ' NOT FOR REPLICATION '
                            ELSE ''
                        END
                      + ';';
            END;
    
    
        PRINT @tsql;
        IF @TARGET = 'CREATE'
            BEGIN
            SET @tsql = 'ALTER TABLE '
                      + QUOTENAME(@schema_name) + '.' + QUOTENAME(@table_name)
                      + CASE @is_disabled
                            WHEN 0 THEN ' CHECK '
                            ELSE ' NOCHECK '
                        END
                      + 'CONSTRAINT ' + QUOTENAME(@constraint_name)
                      + ';';
            PRINT @tsql;
            END;
    
        FETCH NEXT FROM FKcursor INTO @schema_name, @table_name, @constraint_name
            , @referenced_object_name, @constraint_object_id
            , @is_disabled, @is_not_for_replication, @is_not_trusted
            , @delete_referential_action, @update_referential_action;
    
    END;
    
    CLOSE FKcursor;
    DEALLOCATE FKcursor;
    

答案 4 :(得分:-3)

[T-SQL]删除表格上的所有约束

http://weblogs.asp.net/jgalloway/archive/2006/04/12/442616.aspx

-- t-sql scriptlet to drop all constraints on a table
DECLARE @database nvarchar(50)
DECLARE @table nvarchar(50)

set @database = 'dotnetnuke'
set @table = 'tabs'

DECLARE @sql nvarchar(255)
WHILE EXISTS(select * from INFORMATION_SCHEMA.TABLE_CONSTRAINTS where constraint_catalog = @database and table_name = @table)
BEGIN
    select    @sql = 'ALTER TABLE ' + @table + ' DROP CONSTRAINT ' + CONSTRAINT_NAME 
    from    INFORMATION_SCHEMA.TABLE_CONSTRAINTS 
    where    constraint_catalog = @database and 
            table_name = @table
    exec    sp_executesql @sql
END