Есть ли более простой и быстрый способ удалить таблицу со ссылками внешнего ключа на другие таблицы?

У меня есть новая таблица, в которой есть ссылки внешнего ключа на несколько существующих таблиц. Когда я впервые создаю новую таблицу, я создал внешние ключи следующим образом:

ALTER TABLE [dbo].[NewTable] WITH CHECK ADD FOREIGN KEY([SectionDatabaseID])
REFERENCES [dbo].[Section] ([SectionDatabaseID])

ALTER TABLE [dbo].[NewTable] WITH CHECK ADD FOREIGN KEY([TermDatabaseID])
REFERENCES [dbo].[Term] ([TermDatabaseID])

Приведенный выше способ будет генерировать имена для ограничений внешнего ключа, используя собственное автоматическое соглашение об именах.

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

Очевидно, что если я просто выполню оператор drop, база данных SQL Server будет жаловаться на то, что новая таблица имеет ссылки внешнего ключа на другие таблицы.

Я слышал о запуске следующего скрипта, чтобы выяснить, какие внешние ключи существуют, чтобы мы могли их удалить:

use perls;
SELECT 'ALTER TABLE ' + TABLE_SCHEMA + '.[' + TABLE_NAME +
'] DROP CONSTRAINT [' + CONSTRAINT_NAME + ']'
FROM information_schema.table_constraints
WHERE CONSTRAINT_TYPE = 'FOREIGN KEY' and TABLE_NAME = 'NewTable'

Вышеприведенное даст результаты, которые в основном показывают операторы alter, которые мне нужно запустить.

Мне нужно что-то более автоматизированное. Почему я должен отбрасывать каждое ограничение внешнего ключа отдельно, а затем иметь возможность отбрасывать только таблицу?

Я хочу удалить таблицу более простым способом. Это должно быть проще, чем то, что мне нужно сделать выше.


person user1338998    schedule 03.10.2012    source источник
comment
вы можете создать диаграмму, добавить все свои таблицы и перетащить FK через этот пользовательский интерфейс.   -  person Beth    schedule 03.10.2012
comment
Вы должны иметь возможность без проблем удалять таблицы с FOREIGN KEYs, ссылающимися на другие таблицы. Проблема возникает при попытке удалить таблицу, в которой есть FOREIGN KEYs, ссылающиеся на на нее. В этих случаях вы должны сначала найти и удалить ВНЕШНИЕ КЛЮЧИ.   -  person Larry Lustig    schedule 03.10.2012
comment
Насколько я понимаю, вам нужен эквивалент Drop table cascade в tsql? См. stackoverflow.com/questions/4858488/< /а>   -  person Draco Ater    schedule 03.10.2012
comment
Я бы явно назвал ограничение внешнего ключа в соответствии с соглашением об именах (на ваше усмотрение, что использовать в деталях) — таким образом вы сможете узнать, как называются ограничения FK, чтобы вы могли больше легко бросить их.   -  person marc_s    schedule 03.10.2012


Ответы (3)


Да, вы должны сначала бросить FK. Я сталкивался с этим раньше и написал только сценарий, необходимый для автоматизации задачи. Замените DBName и TABLENAME ниже.

Предупреждение для всех: этот сценарий удалит определенную таблицу (или группу таблиц), а также все ограничения FK! Используйте с осторожностью и всегда делайте резервную копию базы данных, прежде чем выполнять серьезную операцию, подобную этой.

    use DBName
    /* 
    SCRIPT TO DROP TABLES WITH FK'S, INDEXES 
    https://mellodev.snipt.net/drop-tables-with-fk-contraints/
    */

    set nocount on

declare @tables table (tablename varchar(255));
insert into @tables
select name from sys.tables where name in 
('TABLENAME')

-- Iterate tables, drop FK constraints and tables
declare @tablename varchar(255);
declare cTable cursor for
select tablename from @tables
open cTable
fetch next from cTable into @tableName
while @@FETCH_STATUS=0
begin
    -- Identify any FK constraints
    declare @fkCount int;
    SELECT @fkCount = COUNT(*)
    FROM sys.foreign_keys
    WHERE referenced_object_id = object_id(@tablename)

    -- Drop any FK constraints from the table
    if (@fkCount>0) begin
        declare @dropFkSql nvarchar(max);set @dropFkSql='';
        declare @fkName nvarchar(max);
        declare cDropFk cursor for  
            SELECT 'ALTER TABLE [' + OBJECT_NAME(parent_object_id) + '] DROP CONSTRAINT [' + name + ']',name
            FROM sys.foreign_keys
            WHERE referenced_object_id = object_id(@tablename)
        open cDropFk
        fetch next from cDropFk into @dropfksql,@fkName
        while @@FETCH_STATUS=0
        begin       
            exec sp_executesql @dropFkSql;

            select 'Dropped FK Constraint: ' + @fkName
            fetch next from cDropFk into @dropfksql,@fkName
        end
        close cDropFk
        deallocate cDropFk          
    end

    -- Drop the table
    declare @dropTableSql nvarchar(max);
    set @dropTableSql='DROP TABLE [' + @tablename + ']';
    exec sp_executesql @dropTableSql;

    select 'Dropped table: ' + @tablename

    fetch next from cTable into @tableName
end
close cTable
deallocate cTable
person mellodev    schedule 03.10.2012

Реляционные базы данных предназначены для обеспечения целостности базы данных. Ваши заявления потенциально разрушают ограничения, которые были тщательно добавлены для защиты качества данных. Автоматизация удаления ограничений целостности из производственной базы данных может обернуться катастрофой для компании. Поэтому, когда был разработан язык SQL, упрощение удаления таблиц, на которые ссылаются другие таблицы, не имело высокого приоритета для важных задач. Благодаря механизму базы данных для корпоративных данных продукт предназначен больше для администраторов баз данных, чем для обычных пользователей.

В чем причина желания удалить несколько таблиц, на которые ссылаются внешние ключи? Можете ли вы быть уверены, что не собираетесь уничтожать чужие запросы?

Предполагая, что вы работаете с некритичной системой, ваш подход к написанию сценария для написания сценария сброса является лучшим решением, о котором я знаю.

person Bob Folkerts    schedule 03.10.2012
comment
Во время разработки очень часто пишут сценарии создания таблиц таким образом, чтобы их можно было запустить снова после изменения схемы. В этом случае вам нужно удалить все таблицы и ограничения, созданные вашим скриптом, прежде чем создавать их заново. - person Crake; 12.03.2013

Если вы используете MSSQL, вы можете использовать этот сценарий, который я написал, чтобы очистить всю БД от данных, не удаляя сами таблицы.

use [MyDataBase]
GO

EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL';

select tbl.* into dbo.DeleteQueries from (SELECT 'DELETE ' + name + ';' as query
FROM sys.tables
WHERE name <> 'DeleteQueries')  as tbl

Declare @query nvarchar(100)

While (Select Count(*) From dbo.DeleteQueries Where query <> '') > 0
Begin
    Select Top 1 @query = query From dbo.DeleteQueries Where query <> ''

    exec(@query);

    Update dbo.DeleteQueries Set query = '' Where query = @query 

End

DROP TABLE dbo.DeleteQueries

EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'

вы можете добавить таблицы, которые вы не хотите очищать, в предложении where запроса «выбрать в». Надеюсь это поможет

person Mr T.    schedule 03.10.2012