我遇到一个案例,我希望返回错误的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
)
)
我认为联合两个具有不同列数的选择将返回错误。如果我删除最外面的SELECT *
,那么我会收到我期望的错误:SELECTs to the left and right of UNION ALL do not have the same number of result columns
。
答案 0 :(得分:11)
答案似乎很简单:是的,这是一个怪癖。 我想用一个简短的例子来证明这一点。但事先,请参考documentation:
两个或多个简单的SELECT语句可以连接在一起形成 使用UNION,UNION ALL,INTERSECT或EXCEPT的复合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不会省略该列,而是添加一个空值。
<强>结论强>
这让我得出结论,如果将UNION ALL
作为子查询处理,sqlite只会处理UNION
。
PS:如果您只是使用{{1}},它在任何情况下都会失败。
答案 1 :(得分:9)
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列,它仍然有用。
EX:
SELECT column1, column2, '' AS column3 FROM table a
UNION
SELECT column1, column2, column3 FROM table b
答案 2 :(得分: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
。