首页 > 解决方案 > DB2 错误:无法识别 SQL 子选择错误

问题描述

我想我只是在 DB2 本身中发现了一个错误。当我运行此代码时,我希望它在执行删除语句时抛出错误(子选择错误地使用 A_NAME 而不是 NAME)。但是:它就像没有 where 子句一样,并删除了表 NAMES 中的所有行!

CREATE TABLE NAMES    (A_NAME VARCHAR(20));
CREATE TABLE OLDNAMES (NAME   VARCHAR(20));

INSERT INTO NAMES VALUES ('ANNA'), ('ELLA'), ('JOHN'), ('EARL');
INSERT INTO OLDNAMES VALUES ('ELLA'), ('EARL');

-- this should throw an error message:
DELETE FROM NAMES WHERE A_NAME IN (SELECT A_NAME FROM OLDNAMES);

-- this should show ANNA & JOHN if the subselect 
-- was correct, but shows nothing
SELECT * FROM NAMES;

-- cleanup
DROP TABLE NAMES;
DROP TABLE OLDNAMES;

我在 DB2/LINUXX8664 10.5.9 上运行它

还是“不是错误,而是功能”?!

标签: sqldb2

解决方案


你错了。SQL 具有用于解析子查询中的列引用的范围规则。如果在内部查询中没有解析列引用,那么它会查找外部查询。

这些是 SQL 的规则,并非特定于 DB2。

那就是 SQL 将您的逻辑解释为:

DELETE FROM NAMES
    WHERE NAMES.A_NAME IN (SELECT NAMES.A_NAME FROM OLDNAMES ON);

这是有效的——如果没有意义的话——SQL。

这就是建议对所有列引用进行限定的原因。编写此查询的更好方法是:

DELETE FROM NAMES
    WHERE NAMES.A_NAME IN (SELECT ON.A_NAME FROM OLDNAMES ON);

推荐阅读