【问题标题】:Dropping multiple tables at once一次删除多个表
【发布时间】: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'.

db<>fiddle demo

看起来在内部它是作为 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


【解决方案1】:

问题是,DBMS 会删除它可以删除的任何表,但这个操作不是原子的。如果你想要一个原子表达式,你可以在事务中使用条件 ROLLBACK(更多信息请参阅here

【讨论】:

  • but this operation is not atomic 是的,行为表明了这一点。您能否提供任何说明这一事实的官方消息来源?我很好奇哪些操作不保留全有或全无规则。
  • 它似乎只是将 drop table 应用于您丢失的每个表(并且这一事实由以下语句支持'如果引用表和保存主键的表都被删除在同一个DROP TABLE 语句,必须首先列出引用表。')
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-24
  • 1970-01-01
  • 2019-06-11
  • 2020-06-08
  • 1970-01-01
  • 2021-08-13
  • 2016-07-13
相关资源
最近更新 更多