SQL Server:使用 FK 删除表
Posted
技术标签:
【中文标题】SQL Server:使用 FK 删除表【英文标题】:SQL Server: Drop Table with FK 【发布时间】:2010-03-09 17:24:36 【问题描述】:在表“A”上,通过 FK 到“A.Id”依赖于大约 30 个其他表。
对于集成测试,我必须删除表并重新创建它以创建定义的状态。由于依赖对象,它们似乎无法删除和重新创建表。错误信息是:
无法删除对象“dbo.A” 因为它被 FOREIGN 引用 KEY约束
问题:
如何删除并重新创建表“A”? (或)有没有办法在全局范围内关闭模式依赖关系? (或)有什么方法可以在删除和恢复表“A”之前备份(所有!)依赖关系,然后再恢复所有依赖关系?【问题讨论】:
为什么不使用单独的数据库进行集成测试,每次都从头开始生成整个状态? 数据库太大了(几百个表和很多依赖对象)。这样一来,每个集成测试将花费大约 45 秒 +x 仅用于启动时间,而无需任何实际测试。此外,一些表包含数据。 (没有任何自定义数据的数据库转储总量约为 35MB)。我们将有许多个集成测试,我们希望在每次签入时使用集成服务器执行这些测试。 每个集成状态是否需要相同的数据库初始状态,或者您是否可以支付一次启动费用并让每个测试撤消它可能对状态所做的任何临时更改? 支付一次启动罚款是一个想法。要“倒回”更改,想法是重新创建表 + 一组定义的数据。 (它巨大的遗留应用程序,这是我们迄今为止最好的。目标是单元测试,但我们目前只能达到集成测试。) 【参考方案1】:探索sys.foreign_key_columns
系统表。这是我放置的一个示例,给定一个表格,告诉您其中的哪些列被键控到另一个表格:
DECLARE @tableName VARCHAR(255)
SET @tableName = 'YourTableName'
SELECT OBJECT_NAME(fkc.constraint_object_id) AS 'FKName', OBJECT_NAME(fkc.[referenced_object_id]) AS 'FKTable', c2.[name] AS 'FKTableColumn', @tableName AS 'Table', c1.[name] AS 'TableColumn'
FROM sys.foreign_key_columns as fkc
JOIN sys.columns AS c1 ON c1.[object_id] = fkc.[parent_object_id] AND c1.[column_id] = fkc.[parent_column_id]
JOIN sys.columns AS c2 ON c2.[object_id] = fkc.[referenced_object_id] AND c2.[column_id] = fkc.[referenced_column_id]
WHERE fkc.[parent_object_id] = OBJECT_ID(@tableName)
ORDER BY OBJECT_NAME(fkc.constraint_object_id)
有了这个,或者它的一些变体,你可以找出外键,删除它们,做你的事情,然后重新创建外键。
我应该补充一点,我知道这适用于 SQL2005 和 SQL2008。我真的不知道它是否可以在 SQL2000/MSDE 上运行。
【讨论】:
【参考方案2】:在 Management Studio 中,您可以右键单击表并编写包含所有外键的 CREATE 和 DROP 脚本。
更具体地说,这将为您提供 Table 所依赖的所有约束。但是,它不会为您提供依赖于该表的外键列表。因此,除了通过右键单击 SMS 中的表生成的脚本之外,您还需要找到所有外键并编写脚本。要获取它们的列表,您可以运行如下查询:
select FKConstraint.TABLE_NAME, FKConstraint.CONSTRAINT_NAME
from INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
Join INFORMATION_SCHEMA.TABLE_CONSTRAINTS As UniqueConstraint
On UniqueConstraint.CONSTRAINT_NAME = INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS.UNIQUE_CONSTRAINT_NAME
Join INFORMATION_SCHEMA.TABLE_CONSTRAINTS As FKConstraint
On FKConstraint.CONSTRAINT_NAME = INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS.CONSTRAINT_NAME
Where UniqueConstraint.TABLE_NAME = 'TableA'
对于其中的每一项,您都需要编写创建和删除脚本。您可以将 drop 附加到 drop 脚本的顶部,并将 create 附加到 create 脚本的末尾。
【讨论】:
这不包含引用依赖,这是问题所在。 什么意思? SMS 将创建一个脚本,该脚本将删除要删除的表的所有外键,然后在最后删除该表。另外,create 会创建所有的外键。 嗯,我试试这个.. 并得到一个脚本有很多:“如果存在(SELECT * FROM sys.check_constraints WHERE”......但是当我执行它时,我仍然得到:“可以不要删除对象 'dbo.A',因为它被 FOREIGN KEY 约束引用。”这真的很奇怪! 我很抱歉。我看到了这个问题。您需要找到所有指向您希望删除的表的 FK。我会修改我的回复。【参考方案3】:在 SSMS 中转到数据库并右键单击。选择任务,生成脚本。然后通过选项并按照您想要的方式设置它们(可能只在表中选择外键并创建依赖对象并删除并重新创建,不要;在我面前有选项,但您会看到它们。然后选择您的表想要为 FK 编写脚本并将它们编写到一个文件中。打开文件并将 drop 语句分隔到一个文件中,将 create 语句分隔到另一个文件中。现在您有了可以运行的两个文件 do autmatically do you want what you run run一个测试。我建议在运行第一个测试之前重新创建文件(以防它们自上次运行测试以来发生了变化),但不是针对每个单独的测试。
【讨论】:
谢谢,非常感谢。这对我最有效!【参考方案4】:在 Sql Server Management Studio 中展开表,展开 Constraints 文件夹。
写下您拥有的任何约束,以便您可以重新创建它们。删除约束并删除表。重建表并重新创建约束。
【讨论】:
我也想过这一点,但由于许多表有很多约束和依赖关系,这将是很多工作。 (还有很多工作是我尽量避免的:-)) 是的,我希望 Mircosoft 能够更轻松地执行此任务。每次我必须这样做时,我都会大声抱怨。 ;-)【参考方案5】:使用交易。 在测试结束时 - 回滚它。
【讨论】:
好主意,但我无法控制 SQL 连接 - 所以无法控制事务 (?)。【参考方案6】:也许考虑在初始化测试设置中使用您的数据库维护一个虚拟服务器。启动 VM,执行测试,然后丢弃更改的 VM。
【讨论】:
不,根本没有恢复。启动虚拟机需要一两分钟,仅此而已。以上是关于SQL Server:使用 FK 删除表的主要内容,如果未能解决你的问题,请参考以下文章
原因:java.sql.SQLException:无法删除表“投票”上的外键约束“FK336ctjyksuuwnpmffcogcdyet”引用的表“链接”