Оставьте все внешние ключи в таблице - PullRequest
2 голосов
/ 14 июня 2010

У меня был этот скрипт, который работал в 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 ]

7 голосов
/ 04 марта 2014

Есть более простой способ. Зачем все это? Сценарий:

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

Запишет скрипт для всех внешних ключей

1 голос
/ 14 июня 2010

Я заметил, что вы не фильтровали внешние ключи в исходном запросе. Кроме того, вы не можете фильтровать представления INFORMATION_SCHEMA по имени базы данных, поскольку они всегда будут возвращать текущую базу данных. Вместо этого попробуйте что-то вроде этого:

EDIT

Из комментариев вы сказали, что пытаетесь удалить все внешние ключи в данной таблице и все внешние ключи, которые указывают на эту же таблицу, чтобы вы могли отбросить таблицу. Я скорректировал режим, чтобы сделать именно это. Я бы предложил вам откорректировать вопрос, чтобы отразить это. Следует отметить, что все, что действительно необходимо, - это удалить внешние ключи, которые указывают на рассматриваемую таблицу (второй запрос в объединении), поскольку любые ограничения на саму таблицу будут отброшены при удалении таблицы.

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
0 голосов
/ 19 сентября 2012

Это довольно старый пост, но он может кому-то помочь.

Извлечение кода из этого поста Джона Пола Кука: Скрипт для создания всех внешних ключей

Я немного изменил код, чтобы мы могли фильтровать по именам таблиц (переменная @TARGET_TABLE) и схемы (переменная @TARGET_SCHEMA).

Мне пришлось изменить скрипт так, чтобы онтакже печатает сценарии этих внешних ключей, принадлежащих другим таблицам, ссылаясь на @TARGET_TABLE.

. Необходимо установить следующие три переменные, которые находятся в начале сценария:

  • @ TARGET: установите для него значение «DROP» или «CREATE», хотите ли вы создавать сценарии для создания FK или для их удаления.
  • @ TARGET_TABLE: имя таблицы (текущая выбранная база данныхдолжен использоваться).
  • @ TARGET_SCHEMA: затем имя схемы, которой принадлежит таблица.

ЗАМЕЧАНИЯ:

  1. Это также сценарии зависимых внешних ключей, принадлежащих другим таблицам, ссылающимся на @TARGET_TABLE table
  2. Сгенерированный скрипт не содержит оператора [USE SomeDatabase]

Скрипт выглядит так:

-- 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;
0 голосов
/ 22 ноября 2010

[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
0 голосов
/ 14 июня 2010

Написанный сценарий предполагает, что вы запускаете его в базе данных, содержащей объект, который нужно удалить. Вы запускаете его из другой базы данных (например, master или tempdb)? Возможно, ваша база данных по умолчанию (при входе в систему) изменилась?

(Я также заметил, когда пробовал на одной из моих БД, что это не учитывает схемы. Возможно, стоит добавить через некоторое время.)

...