我想我刚刚发现DB2本身有错误。当我运行此代码时,我希望它在执行delete语句时会引发错误(子选择错误地使用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上运行它
或者是“不是错误,而是功能”?!
您错了。 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);