如何创建禁用的外键

时间:2018-02-08 13:38:39

标签: sql-server

我很确定我无法做到这一点,但仍然要求。 我的要求有点奇怪'但请忍受我。

情况:

  • 表A在字段x
  • 上有UQ
  • 表B对表A.x
  • 有FK

我想删除A中的所有值(因此B),但它们可能包含大量数据。

为了做到这一点,我有一个存储过程,它将遍历所有FK向A(递归)和(暂时)删除所有FK的表。完成后,我TRUNCATE TABLE每个参与的表格,然后再次恢复所有FK。

在某种程度上,我正在做一个级联截断。

这已经很长时间了,并且比以正确的顺序执行DELETE要快得多,因为它几乎只有少量的元数据操作,因此我可以甚至在一次不那么大的交易中做到这一点。

然后我遇到了以下情况:

  • 表A(X)上的UQ因某种原因被禁用
  • 系统然后在(x)上自动禁用FK从B到A,这是有意义的,因为没有UQ可以再引用。

当我的存储过程现在尝试清空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

1 个答案:

答案 0 :(得分:0)

嗯,几乎和预期一样,它无法完成。 感谢所有评论者的反馈。

相关问题