XMe*_*i01 6 database-engine update
我想交换表中两列的值,我发现在 SQL 中我们可以通过使用 Update 来做到这一点:
update the_table set first_name = last_name, last_name = first_name;
Run Code Online (Sandbox Code Playgroud)
它有效但我想知道 SQL 如何能够做到这一点而不覆盖其他列中的列中的数据?
Cha*_*ace 10
@mustaccio 已经回答了这是如何物理实现的。
逻辑规范如下:
=
语句UPDATE SET
中右侧的列必须来自应用更新之前的值。因此交换值很简单,因为右侧始终引用旧值。
了解原因的另一种方法是考虑对语句进行等效重写:
update the_table
set (first_name, last_name) = (last_name, first_name);
Run Code Online (Sandbox Code Playgroud)
并非所有 SQL 产品都实现了这一点,但根据 SQL 标准,它是等效的,并且在实现它的地方,它的工作方式与您的完全一样。
至于是否保证:是的。它是由 SQL 规范强制执行的,据我所知,大多数 DBMS 都实现了这一要求(MySQL 和派生/分叉产品,例如 MariaDB 是一个例外,在这种情况下没有正确实现标准)。
这是因为每一行都是作为一个整体来处理的,而不是逐列处理的。简化的顺序如下:
\nSQL 标准(至少是我可以访问的版本)规定了这些术语的行为(强调我的):
\n\n\n\n
\n- 在调用由 T 的任何行更新引起的任何 <triggered action> 之前,对 T[able] 的每一行评估 S[et]C[lause]。
\n- 在更新 T 的任何行之前,将针对 T 的每一行有效评估S[et]C[lause]L[ist] 中包含的每个 <set Clause> 的 <update source> 。
\n- 对于每个主题行,通过复制主题行并按照 SCL 中包含的每个 <set Clause> 的指定,通过应用子条款 14.15 的一般规则 \xe2\x80\x9c<set Clause List> 更新它来构造候选新行。 \xe2\x80\x9d。
\n