2010-06-14 3 views
2

У меня был сценарий, который работал в 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. Как я могу легко отказаться от всех ограничений внешнего ключа для определенной таблицы? У кого-нибудь есть лучший сценарий?

+1

Вы получаете ошибку в 2008 году? Не удаляет ли он некоторые FK? –

+0

Кажется, это не – trnTash

ответ

0

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

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

+0

О, и я бы основал его на sys.foreign_keys тоже. Хотя я уверен, что INFORMATION_SCHEMA будет подключаться к Oracle, DB2, MySQL, et. al., я подозреваю, что sp_executesql и точный синтаксис ALTER TABLE не могут. –

1

Я заметил, что вы не фильтр для внешних ключей в ваш исходный запрос. Кроме того, вы не можете отфильтровать представления 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

«Команда (ы) завершена успешно.», Но я все еще не могу удалить таблицу, против которой я запускаю сценарий. – trnTash

+1

@trnTash. Вы никогда не говорили, что пытаетесь удалить таблицу. Вы сказали, что пытаетесь удалить внешние ключи на данной таблице. Если вы не можете отказаться от таблицы, вероятным виновником является то, что рассматриваемая таблица является родительской таблицей в внешних ключах на * других * таблицах. – Thomas

-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 
+2

Вы понимаете, что это тот же самый сценарий, который задал вопрос в вопросе, не так ли? –

0

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

Принимая ядро ​​кода с этого поста Джон Пол Кук: Script to create all foreign keys

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

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

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

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

ПРИМЕЧАНИЕ:

  1. Он также сценарии зависимых иностранные клавиши, принадлежащие другими таблицами ссылающихся на таблицу @TARGET_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; 
5

Там более простой способ. Почему все это? Сценарий:

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

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

Смежные вопросы