为何PostgreSQL中带子查询的ANY未抛出‘列不存在’错误?
为什么PostgreSQL在子查询引用不存在的列时未抛出错误?
这是PostgreSQL的列名解析优先级规则导致的:当子查询中引用的列在自身查询的目标表中不存在时,会自动向上查找外层查询上下文里的同名列,而非直接抛出“列不存在”的错误。
你的SQL问题拆解
在这段代码的过滤条件里:
where arowid = any(select arowid from Arows) -- 问题行
子查询select arowid from Arows中,arowid并不属于Arows的列,但PostgreSQL没有报错,而是将这个arowid解析为外层Brows表的arowid列。
这就导致子查询的逻辑变成:对Arows的每一行,都取外层当前行的arowid值作为返回结果。也就是说,子查询返回的集合里必然包含当前行的arowid,因此arowid = any(...)这个条件永远为真,最终返回Brows的所有行。
正确的写法
如果要实现“筛选Brows中arowid存在于Arows的id中的行”,需要明确指定子查询引用的是Arows的id列,且最好加上表限定符避免歧义:
where arowid = any(select id from Arows) -- 或者更严谨的写法 where Brows.arowid = any(select Arows.id from Arows)
补充说明
这种列名解析规则是SQL标准的一部分,用于支持关联子查询的写法,但如果疏忽就会出现逻辑错误。若要避免这类问题,可以开启PostgreSQL的sql_safe_updates参数,或者养成给表加别名、用别名限定列名的习惯,强制列名的来源明确。
内容的提问来源于stack exchange,提问作者Joel Sherriff
相关产品推荐
相关产品推荐

