Strange DB2 Scopes

Go To


Create two tables with some ids overlapping.

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

Next, populate them with ids, some common.

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;

Next, update the overlap indicator. BUT, by mistake, you type in the wrong column name, you write just "id" instead of "inner_id", and you decide not to use an alias.

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

The result:

  1. No SQL errors
  2. It update overlap_in field to 1 in all rows in outer_table

How is this even normal? Any explanations why db2 allows this?

Note: DB2 Version:

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
2012-04-03 20:08
by Isaac


This is normal, expected behavior. As in most every programming language, identifiers are resolved this way in SQL. If an identifier does not exist in the innermost scope, name resolution works outward. If there is no column named "id" in the innermost scope, the column name is resolved outside that scope. Here, "id" is resolved as You should always use table prefixes!

Suppose you had written

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

You would certainly want the identifier "id" to be resolved as, just like it is in your example. It would be silly if within a subquery, you could not refer to columns from other tables in the query.

That said, it would also be nice if some SQL implementations could do sanity checks that flagged queries like this, because if there is only one column mentioned in a subquery with a FROM clause, it usually should be a column from the table in the subquery. If not, it's typically a typo (but still a legal query).

2012-04-03 20:25
by Steve Kass