【发布时间】:2019-10-30 12:57:50
【问题描述】:
SQL Server 支持 DIE 语法(drop table if exists):
可以在任何数据库中删除多个表。如果要删除的表引用了另一个同时要删除的表的主键,则具有外键的引用表必须列在包含被引用主键的表之前。
例子:
CREATE TABLE t1(i INT PRIMARY KEY);
CREATE TABLE t2(i INT PRIMARY KEY);
CREATE TABLE t3(i INT PRIMARY KEY, t2_id INT REFERENCES t2(i));
正确的丢物方式是:t1/t3,最后是t2。
假设我们运行:
DROP TABLE IF EXISTS t1,t2,t3;
-- Could not drop object 't2' because it is referenced by a FOREIGN KEY constraint.
一切如预期,DDL无法成功完成,因为有FK持有。
现在,我期望 DDL 应该保持all-or-nothing 行为。所以我的 3 张桌子仍然应该完好无损。但事实并非如此,表 t1 和 t3 被删除了。
SELECT * FROM t1;
-- Invalid object name 't1'.
SELECT * FROM t2;
SELECT * FROM t3;
-- Invalid object name 't3'.
看起来在内部它是作为 3 个独立的 drop 语句执行的,这很奇怪。
是否有任何原因导致表 t1 和 t3 消失了,还是我遗漏了一些明显的东西?
【问题讨论】:
-
来自文档:“DROP TABLE 不能用于删除由 FOREIGN KEY 约束引用的表。必须首先删除引用 FOREIGN KEY 约束或引用表。如果引用表并且持有主键的表在同一个 DROP TABLE 语句中被删除,引用表必须首先列出。”所以你的代码应该是 DROP TABLE IF EXISTS t1,t3,t2;
-
@MJH 是的,我声明了这个事实
"The proper way of droping objects is: t1/t3, and finally t2"我的问题是为什么 DROP TABLE 不是原子操作。 -
抱歉,问题略过。我不认为该语法是“标准 SQL”并且实施得很糟糕,如果您在 DROP 语句周围添加事务,则不会删除任何表。
标签: sql sql-server tsql drop-table