0

创建两个表,其中一些 id 重叠。

create table outer_table (
    id integer,
    overlap_in smallint default 0
);
create table inner_table (
    inner_id integer
);

接下来,用 id 填充它们,一些常见的。

insert into outer_table(id) values 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
insert into inner_table(inner_id) values 0, 1, 2;

接下来,更新重叠指示器。但是,错误地,您输入了错误的列名,您只写了“id”而不是“inner_id”,并且您决定不使用别名。

update outer_table o
set o.overlap_in = 1
where o.id in (select id from inner_table);

结果:

  1. 没有 SQL 错误
  2. 它在 outer_table 的所有行中将overlap_in 字段更新为 1

这还算正常吗?任何解释为什么 db2 允许这样做?

注意:DB2 版本:

>db2level
DB21085I  Instance "....." uses "64" bits and DB2 code release "SQL09075"
with level identifier "08060107".
Informational tokens are "DB2 v9.7.0.5", "...", "IP23285", and Fix Pack
"5".
4

1 回答 1

2

这是正常的预期行为。与大多数编程语言一样,标识符在 SQL 中以这种方式解析。如果最内层范围内不存在标识符,则名称解析向外工作。如果在最内层范围内没有名为“id”的列,则在该范围之外解析列名。在这里,“id”被解析为 o.id。您应该始终使用表前缀!

假设你写了

where exists (
  select * from inner_table
  where inner_table.inner_id = id
)

您当然希望将标识符“id”解析为 o.id,就像在您的示例中一样。如果在子查询中不能引用查询中其他表的列,那将是愚蠢的。

也就是说,如果某些 SQL 实现可以对这样的标记查询进行完整性检查,那也很好,因为如果子查询中只提到一个带有 FROM 子句的列,它通常应该是子查询中表中的一列. 如果不是,这通常是一个错字(但仍然是一个合法的查询)。

于 2012-04-03T20:25:27.490 回答