3.6 UNION
关于“旧式语法”和“新式语法”就讲到这里,接下来要讲述的内容无论对哪种联结语法都是一样的——UNION运算符。UNION是一种特殊的运算符,通过它可以让两个或更多个查询产生单个结果集。
UNION并不像前面讨论过的选项那样是一个真正的联结(JOIN)——它更像是从一个查询直接向另一个查询进行的数据追加(虽然它的作用与这种说法略有不同,但这是讨论该概念最容易的方式)。JOIN水平地合并数据(添加更多的列),而UNION则垂直地合并数据(添加更多的行),如图3-2所示。

图 3-2
在使用UNION处理查询时,有几个要点:
l 所有要进行UNION的查询,其SELECT列表中列的数量必须相同。如果第一个查询的SELECT列表中有3个列,则第二个查询(以及所有进行UNION的后续查询)的SELECT列表中也必须是3个列。如果第一个有5列,那么第二个也必须有5列。无论第一个查询有多少列,随后的查询中都必须有同样数目的列。
l 为合并的结果集返回的标头仅取自第一个查询。如果第一个查询的SELECT列表类似这样:SELECT Col1,Col2 AS Second,Col3 FROM...,那么无论后续的查询中列的名称或别名如何,UNION返回的列标头都将分别是Col1、Second以及Col3。
l 一个查询中每一列的数据类型必须与其他查询中相同对应的列的数据类型隐式兼容。注意,我不是说它们的数据类型必须相同——它们只要能隐式转换即可(可以在第1章中找到显示隐式与显示转换的转换表)。如果第一个查询中第二列的数据类型是char(20),那么第二个查询中第二列的数据类型是varchar(50)也是可以的。然而,由于一切都是基于第一个查询,因此,第二个结果集中所有长度超过20的行将被截断。
l 与非UNION查询不同,UNION的默认返回方式是DISTINCT而非ALL。这确实让人有些困惑。在其他的查询中,所有的行都将被返回,无论它们是否与别的行有重复,而UNION却不是这样返回结果的。除非在查询中使用了ALL关键字,否则,只返回一个有重复的行。
接下来,照我们一贯的方式,用一个例子来更好地说明。
这里创建了两个表,数据将从这两个表中进行选取。接着,向每个表中插入三行,插入两个表的行中有一行是完全相同的。如果查询执行的是ALL,则将显示所有(6个)行。如果查询执行的是DISTINCT,则只返回5行(去除了一个重复行):



现在,来看看返回的结果中最重要的部分(在返回的结果中,将看到一些“one row(s) affected”注释——忽略它们直至看见查询的结果):


第一个结果集是由简单的没有附加参数的UNION语句返回的。可以看到有一行被去除了——虽然两个表中都插入了“CCC”,但只在结果中显示了一行,因为默认删除了重复记录。除此之外,该结果是由进行UNION的SELECT语句的查询结果合并而成的一个结果集。
返回的第二个结果集略有些改变——这一次使用了UNION ALL,ALL关键字确保返回所有的行。因此,前一个查询中去除的行突然出现了。






