12

我遇到了一个情况,我期望返回错误的 sqlite 查询实际上是成功的,我想知道是否有人能指出为什么这个查询是有效的。

CREATE TABLE test_table(
  k INTEGER,
  v INTEGER
);

INSERT INTO test_table( k, v ) VALUES( 4, 5 );

SELECT * FROM(
  SELECT * FROM(
    SELECT k, v FROM test_table WHERE 1 = 0
  )
  UNION ALL
  SELECT * FROM(
    SELECT rowid, k, v FROM test_table
  )
)

上面的sqlfiddle

我认为联合具有不同列数的两个选择会返回错误。如果我删除最外层SELECT *,那么我会收到我期望的错误:SELECTs to the left and right of UNION ALL do not have the same number of result columns.

4

3 回答 3

11

答案似乎很简单:是的,这是一个怪癖。 我想用一个简短的例子来证明这一点。但事先,让我们查阅文档

可以使用 UNION、UNION ALL、INTERSECT 或 EXCEPT 运算符将两个或多个简单的 SELECT 语句连接在一起以形成复合 SELECT。在复合 SELECT 中,所有组成的 SELECT 必须返回相同数量的结果列。

因此,文档非常清楚地表明,两个SELECTs必须提供相同数量的列。但是,正如您所说,最外层SELECT奇怪地避免了这种“限制”。

示例 1

SELECT * FROM(
    SELECT k, v FROM test_table
  UNION ALL
    SELECT k, v,rowid FROM test_table
);

结果:

k|v
4|5
4|5

rowid正如评论中所指出的,第三列被简单地省略了。

示例 2

我们只是切换两个 select 语句的顺序。

 SELECT * FROM(
    SELECT k, v, rowid FROM test_table
  UNION ALL
     SELECT k, v FROM test_table
  );

结果

k|v|rowid
4|5|1
4|5|

现在,sqlite 不会省略该列,而是添加一个空值。

结论

这使我得出结论,如果将 sqliteUNION ALL作为子查询处理,则它只会以不同的方式处理。

PS:如果你只是使用UNION它在任何情况下都会失败。

于 2012-07-31T15:28:07.067 回答
10

UNION ALL 将在额外的列中返回具有空值的结果。

基本的 UNION 将失败,因为没有 ALL 的 UNION 必须在两个表中具有相同数量的列。

所以:

SELECT column1, column2 FROM table a
UNION ALL 
SELECT column1, column2, column3 FROM table b

在第 3 列中返回 3 列,其中包含空值。

和:

SELECT column1, column2 FROM table a
UNION 
SELECT column1, column2, column3 FROM table b

应该失败,因为列数不匹配。

总之,您可以向 UNION 添加一个空白列,以便您从每个表中选择 3 列,它仍然可以工作。

前任:

SELECT column1, column2, '' AS column3 FROM table a
UNION  
SELECT column1, column2, column3 FROM table b
于 2012-08-08T03:17:35.863 回答
2

如果您的第二个查询的列数较少,您可以这样做:

select col1, col2, col3, col4, col5
from table A

union all

select col1, col2, col3, col4, NULL as col5, 
from table B

取而代之的是NULL,也可以使用一些字符串常量 - 'KPI' as col5

于 2020-02-27T06:35:54.687 回答