是否有更简单,更快速的方法来删除具有外键引用到其他表的表?

时间:2012-10-03 18:56:49

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

我有一个新表,它具有对许多现有表的外键引用。当我第一次创建新表时,我按以下方式创建了外键:

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语句的结果。

我需要更自动化的东西。为什么我必须单独删除每个外键约束,然后才能删除表?

我想以更简单的方式删除表格。它必须比我上面要做的更容易。

3 个答案:

答案 0 :(得分:4)

关系数据库旨在强制实施数据库完整性。您的陈述可能会破坏为保护数据质量而谨慎添加的约束。自动从生产数据库中删除完整性约束可能对公司来说是一场灾难。因此,当开发SQL语言时,使得删除其他表引用的表变得容易,重要任务的优先级并不高。借助用于企业数据的数据库引擎,该产品更适合DBA而非临时用户。

想要删除外键中引用的多个表的原因是什么?你能确定你不会破坏别人的疑问吗?

假设您正在处理非关键系统,那么编写脚本来编写drop脚本的方法就是我所知道的最佳解决方案。

答案 1 :(得分: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

答案 2 :(得分:1)

如果您正在使用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'

您可以在“select into”查询的where子句中添加您不想清除的表。 希望这有帮助