在 SQL 中,给定具有相同架构的表
T
和 S
,例如,
CREATE TABLE "T" ("ID" INTEGER, "Salary" REAL);
CREATE TABLE "S" ("ID" INTEGER, "Salary" REAL);
我们可以通过命令合并这两种关系
(SELECT * FROM "S") UNION (SELECT * FROM "T");
但是以下命令给出了错误:
"S" UNION "T";
SQLite 中的错误消息:
near "UNION": syntax error
SQL Server 中的错误消息:
Incorrect syntax near the keyword 'UNION'.
为什么我们不能使用后一个命令?从代数上来说,联合运算符被定义为采用两个表操作数并输出另一个表作为结果。所以
"S" UNION "T"
必须起作用。这类似于选择和投影运算符如何获取表操作数并输出另一个表。
我知道,虽然
SELECT
语句的输出在代数上应该是一个表,但实际上它是一个“虚拟表”。我对 C. J. Date 的《数据库系统简介(第 8 版)》的理解是,像上面的 S
和 T
这样的表是“基本关系/关系”,而像 (SELECT * FROM "S")
和 (SELECT * FROM "T")
这样的虚拟表是“派生关系” ”;并且两者(基础和派生)都被视为表。那么当 UNION
对它们进行操作时,为什么它们的行为不一样呢?有趣的是,在我们分别为 view1
和
view2
的输出命名 (SELECT * FROM "S")
和 (SELECT * FROM "T")
来创建视图后,CREATE VIEW "view1" AS SELECT * FROM "S";
CREATE VIEW "view2" AS SELECT * FROM "T";
如果我们将视图作为操作数提供给
UNION
,我们将再次收到错误:
"view1" UNION "view2";
SQLite 中的错误消息:
near "UNION": syntax error
SQL Server 中的错误消息:Incorrect syntax near 'view1'.
发生什么事了?为什么操作数必须是 SELECT
语句?
按照您期望的方式定义了 UNION 运算符:
<non-join query expression> ::=
<non-join query term>
| <query expression> UNION [ ALL ] [ <corresponding spec> ] <query term>
如果我们展开一切:
<query term>
<non-join query term>
<non-join query term>
<non-join query primary>
<non-join query primary>
<simple table>
<simple table>
<explicit table>
<explicit table>
TABLE <table name>
<explicit table>
相当于TABLE <table name>
<query expression>
因此,根据标准,您应该能够使用如下语法:( SELECT * FROM <table name> )
TABLE T UNION TABLE S
但是 SQL 语言的实际实现取决于 RDBMS 开发人员,我不知道有任何支持这样的显式表语句,顺便说一句,对于 UNION JOIN 也是如此,所以回答你的问题 Why should the operands for UNION be SELECT statements and not tables?
- 因为开发人员决定不这样做遵循标准。