我很确定我无法做到这一点,但仍然要求。 我的要求有点奇怪'但请忍受我。
情况:
我想删除A中的所有值(因此B),但它们可能包含大量数据。
为了做到这一点,我有一个存储过程,它将遍历所有FK向A(递归)和(暂时)删除所有FK的表。完成后,我TRUNCATE TABLE
每个参与的表格,然后再次恢复所有FK。
在某种程度上,我正在做一个级联截断。
这已经很长时间了,并且比以正确的顺序执行DELETE
要快得多,因为它几乎只有少量的元数据操作,因此我可以甚至在一次不那么大的交易中做到这一点。
然后我遇到了以下情况:
当我的存储过程现在尝试清空A(以及引用它的表)时,它会发现FK已禁用,删除它,截断表A并尝试重新创建FK但由于没有相应的(启用的)UQ而失败表A.
我试图使用WITH NOCHECK
但是唉。 (SQL 2012)
我现在最好的解决方案是在表A(x)上创建一个虚拟UQ,创建FK然后再次丢弃虚拟UQ,以防它发现没有适用的UQ可用。它有效,但我想知道我是否可以跳过所有额外的检查和代码。
示例代码:
-- cleanup
IF OBJECT_ID('B') IS NOT NULL DROP TABLE B
IF OBJECT_ID('A') IS NOT NULL DROP TABLE A
GO
--setup
CREATE TABLE A ( a int IDENTITY(1, 1), x int CONSTRAINT UQ_A_x UNIQUE, y varchar(100))
INSERT A (x, y)
VALUES (10, 'A'),
(20, 'B')
CREATE TABLE B (b int IDENTITY(1, 1), x int CONSTRAINT FK_B_x_A FOREIGN KEY (x) REFERENCES A (x), z varchar(100))
INSERT B (x, z)
VALUES (10, 'tralalala'),
(20, 'blablabla')
GO
-- CASCADED TRUNCATE
BEGIN TRANSACTION
ALTER TABLE B DROP CONSTRAINT FK_B_x_A
TRUNCATE TABLE B
TRUNCATE TABLE A
ALTER TABLE B ADD CONSTRAINT FK_B_x_A FOREIGN KEY (x) REFERENCES A (x)
COMMIT TRANSACTION
GO
-- what if...
ALTER INDEX UQ_A_x ON A DISABLE
-- no longer works, even with NOCHECK:
BEGIN TRANSACTION
ALTER TABLE B DROP CONSTRAINT FK_B_x_A
TRUNCATE TABLE B
TRUNCATE TABLE A
ALTER TABLE B WITH NOCHECK ADD CONSTRAINT FK_B_x_A FOREIGN KEY (x) REFERENCES A (x)
COMMIT TRANSACTION
答案 0 :(得分:0)
嗯,几乎和预期一样,它无法完成。 感谢所有评论者的反馈。