#### 13.2.10.3 联合条款

[](<>)

```
SELECT ...
UNION [ALL | DISTINCT] SELECT ...
[UNION [ALL | DISTINCT] SELECT ...]
```

[`联盟`](union.html)结合多个结果[`选择`](select.html)语句到单个结果集中。例子：

```
mysql> SELECT 1, 2;
+---+---+
| 1 | 2 |
+---+---+
| 1 | 2 |
+---+---+
mysql> SELECT 'a', 'b';
+---+---+
| a | b |
+---+---+
| a | b |
+---+---+
mysql> SELECT 1, 2 UNION SELECT 'a', 'b';
+---+---+
| 1 | 2 |
+---+---+
| 1 | 2 |
| a | b |
+---+---+
```

-   [结果集列名和数据类型](union.html#union-result-set)

-   [联合中的表](union.html#union-table)

-   [UNION DISTINCT 和 UNION ALL](union.html#union-distinct-all)

-   [工会中的 ORDER BY 和 LIMIT](union.html#union-order-by-limit)

-   [联合限制](union.html#union-restrictions)

-   [MySQL 8.0 与 MySQL 5.7 的 UNION 交接](union.html#union-8-0-versus-5-7)

##### 结果集列名和数据类型

a 的列名[`联盟`](union.html)结果集取自第一个的列名[`选择`](select.html)陈述。

选定的列列在每个对应的位置[`选择`](select.html)语句应具有相同的数据类型。例如，第一个语句选择的第一列应该与其他语句选择的第一列具有相同的类型。如果对应的数据类型[`选择`](select.html)列不匹配，列的类型和长度在[`联盟`](union.html)结果考虑到所有检索到的值[`选择`](select.html)陈述。例如，考虑以下情况，其中列长度不受第一个值的长度限制[`选择`](select.html)：

```
mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',20);
+----------------------+
| REPEAT('a',1)        |
+----------------------+
| a                    |
| bbbbbbbbbbbbbbbbbbbb |
+----------------------+
```

##### 联合中的表

从 MySQL 8.0.19 开始，您还可以使用[`桌子`](table.html)声明或[`价值观`](values.html)中的声明[`联盟`](union.html)只要你能雇佣同等的[`选择`](select.html)陈述。假设表`t1`和`t2`如下所示创建和填充：

```
CREATE TABLE t1 (x INT, y INT);
INSERT INTO t1 VALUES ROW(4,-2),ROW(5,9);

CREATE TABLE t2 (a INT, b INT);
INSERT INTO t2 VALUES ROW(1,2),ROW(3,4);
```

前面是这种情况，并且忽略以开头的查询输出中的列名[`价值观`](values.html), 以下所有`联盟`查询产生相同的结果：

```
SELECT * FROM t1 UNION SELECT * FROM t2;
TABLE t1 UNION SELECT * FROM t2;
VALUES ROW(4,-2), ROW(5,9) UNION SELECT * FROM t2;
SELECT * FROM t1 UNION TABLE t2;
TABLE t1 UNION TABLE t2;
VALUES ROW(4,-2), ROW(5,9) UNION TABLE t2;
SELECT * FROM t1 UNION VALUES ROW(4,-2),ROW(5,9);
TABLE t1 UNION VALUES ROW(4,-2),ROW(5,9);
VALUES ROW(4,-2), ROW(5,9) UNION VALUES ROW(4,-2),ROW(5,9);
```

要强制列名相同，请将[`价值观`](values.html)在左侧`选择`并使用别名，如下所示：

```
SELECT * FROM (VALUES ROW(4,-2), ROW(5,9)) AS t(x,y)
  UNION TABLE t2;
SELECT * FROM (VALUES ROW(4,-2), ROW(5,9)) AS t(x,y)
  UNION VALUES ROW(4,-2),ROW(5,9);
```

##### UNION DISTINCT 和 UNION ALL

默认情况下，删除重复的行[`联盟`](union.html)结果。可选的`清楚的`关键字具有相同的效果，但使其明确。与可选`全部`关键字，重复行删除不会发生，结果包括所有匹配的行[`选择`](select.html)陈述。

你可以混合[`联合所有`](union.html)和[`工会区别`](union.html)在同一个查询中。混合[`联盟`](union.html)类型被处理为`清楚的`联合覆盖任何`全部`工会在它的左边。一种`清楚的`union 可以通过使用显式生成[`工会区别`](union.html)或隐含地使用[`联盟`](union.html)没有跟随`清楚的`要么`全部`关键词。

在 MySQL 8.0.19 及更高版本中，`联合所有`和`工会区别`当一个或多个[`桌子`](table.html)语句用于联合中。

##### 工会中的 ORDER BY 和 LIMIT

申请一个`订购方式`要么`限制`对个人的条款[`选择`](select.html), 括起来[`选择`](select.html)并将子句放在括号内：

```
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
```

用于`订购方式`对于个人[`选择`](select.html)语句不暗示行​​在最终结果中出现的顺序，因为[`联盟`](union.html)默认情况下会生成一组无序的行。所以，`订购方式`在这种情况下，通常与`限制`，以确定要检索的所选行的子集[`选择`](select.html)，即使它不一定会影响这些行在最终结果中的顺序[`联盟`](union.html)结果。如果`订购方式`没有出现`限制`在一个[`选择`](select.html)，它被优化掉了，因为它在任何情况下都没有效果。

使用一个`订购方式`要么`限制`子句对整个内容进行排序或限制[`联盟`](union.html)结果，括号中的个人[`选择`](select.html)声明并放置`订购方式`要么`限制`在最后一个之后：

```
(SELECT a FROM t1 WHERE a=10 AND B=1)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2)
ORDER BY a LIMIT 10;
```

没有括号的语句等同于刚刚显示的带括号的语句。

从 MySQL 8.0.19 开始，您可以使用`订购方式`和`限制`和[`桌子`](table.html)以与刚刚显示的相同的方式在联合中，记住`桌子`不支持`在哪里`条款。

这种`订购方式`不能使用包含表名的列引用（即，*`tbl_name`*.*`col_name`*格式）。相反，在第一个提供列别名[`选择`](select.html)声明并引用中的别名`订购方式`.（或者，请参阅`订购方式`使用它的列位置。但是，不推荐使用列位置。）

此外，如果要排序的列有别名，则`订购方式`条款*必须*引用别名，而不是列名。以下语句中的第一个是允许的，但第二个失败并出现`“订单子句”中的未知列“a”`错误：

```
(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY b;
(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY a;
```

导致行中的[`联盟`](union.html)结果由每个检索到的行集组成[`选择`](select.html)一个接一个，在每个中选择一个附加列[`选择`](select.html)用作排序列并添加`订购方式`在最后一列之后的那一列上排序[`选择`](select.html)：

```
(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1)
UNION
(SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col;
```

额外维护个人内部的排序顺序[`选择`](select.html)结果，将辅助列添加到`订购方式`条款：

```
(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1)
UNION
(SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col, col1a;
```

使用附加列还可以让您确定哪些[`选择`](select.html)每一行来自。额外的列也可以提供其他标识信息，例如表示表名的字符串。

##### 联合限制

在一个[`联盟`](union.html)， 这[`选择`](select.html)语句是普通的选择语句，但有以下限制：

-   `HIGH_PRIORITY`在第一[`选择`](select.html)没有效果。`HIGH_PRIORITY`在随后的任何[`选择`](select.html)产生语法错误。

-   只有最后一个[`选择`](select.html)语句可以使用`进入`条款。然而，整个[`联盟`](union.html)结果被写入`进入`输出目的地。

    从 MySQL 8.0.20 开始，这两个[`联盟`](union.html)变种包含`进入`已弃用，您应该期望在 MySQL 的未来版本中删除对它们的支持：

-   在查询表达式的尾随查询块中，使用`进入`前`从`产生警告。例子：

    ```
    ... UNION SELECT * INTO OUTFILE 'file_name' FROM table_name;
    ```

-   在查询表达式的带括号的尾随块中，使用`进入`（无论其相对于`从`) 产生警告。例子：

    ```
    ... UNION (SELECT * INTO OUTFILE 'file_name' FROM table_name);
    ```

    这些变体已被弃用，因为它们令人困惑，就好像它们从命名表而不是整个查询表达式（`联盟`）。

[`联盟`](union.html)具有聚合函数的查询`订购方式`子句被拒绝[`ER_AGGREGATE_ORDER_FOR_UNION`](https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html#error_er_aggregate_order_for_union)错误。例子：

```
SELECT 1 AS foo UNION SELECT 2 ORDER BY MAX(1);
```

##### MySQL 8.0 与 MySQL 5.7 的 UNION 交接

在 MySQL 8.0 中，解析器规则[`选择`](select.html)和[`联盟`](union.html)被重构为更加一致（相同[`选择`](select.html)语法在每个这样的上下文中统一应用）并减少重复。与 MySQL 5.7 相比，这项工作产生了几个用户可见的效果，这可能需要重写某些语句：

-   `自然加入`允许一个可选的`内`关键字 (`自然内连接`)，符合标准 SQL。

-   允许不带括号的右深连接（例如，`... 加入 ... 加入 ... 开 ... 开`)，符合标准 SQL。

-   `STRAIGHT_JOIN`现在允许一个`使用`子句，类似于其他内部连接。

-   解析器接受查询表达式周围的括号。例如，`（选择...联合选择...）`是允许的。也可以看看[第 13.2.10.4 节，“带括号的查询表达式”](parenthesized-query-expressions.html).

-   解析器更好地符合记录的允许放置`SQL_CACHE`和`SQL_NO_CACHE`查询修饰符。

-   以前只在子查询中允许的联合的左手嵌套，现在在顶级语句中允许。例如，此语句现在被接受为有效：

    ```
    (SELECT 1 UNION SELECT 1) UNION SELECT 1;
    ```

-   锁定子句 (`更新`,`锁定分享模式`) 只允许在非`联盟`查询。这意味着必须使用括号`选择`包含锁定子句的语句。此声明不再被接受为有效：

    ```
    SELECT 1 FOR UPDATE UNION SELECT 1 FOR UPDATE;
    ```

    相反，请像这样编写语句：

    ```
    (SELECT 1 FOR UPDATE) UNION (SELECT 1 FOR UPDATE);
    ```
