Bug #17395 Syntacs error in update statement using virtual table in set clause
Submitted: 14 Feb 2006 19:58 Modified: 21 Feb 2006 13:09
Reporter: Andre Timmer Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server Severity:S2 (Serious)
Version:5.0.18 OS:Any (All)
Assigned to: CPU Architecture:Any

[14 Feb 2006 19:58] Andre Timmer
Description:
update adres aa
set    aa.code_gemeente  = (
                           select case when max(code_gemeente) = min(code_gemeente) then max(code_gemeente) else '0000' end
                           from (
                                select code_gemeente
                                from   adres_googliaans bb use index (adres_googliaans_i4)
                                where  aa.woonplaats = bb.woonplaats
                                and    aa.code_land_kvk = bb.code_land_kvk
                                and    bb.code_gemeente != '0000'
                                limit 10 -- to speed up query
                                ) xx
                           )
where  aa.code_gemeente = '0000'
and    length(aa.woonplaats) > 0
and    aa.code_land_kvk = '0001';

Statement above produces error: 
- Unknown column 'aa.woonplaats' in 'where clause'

How to repeat:
Create the 2 tables below and try statement above.

CREATE TABLE `adres` (
  `dummy_pk` int(10) unsigned NOT NULL auto_increment,
  `bkwi_id` int(11) NOT NULL default '0',
  `bkwi_volgnr` smallint(6) NOT NULL default '0',
  `type` char(2) character set latin1 NOT NULL default '',
  `table_type` char(1) character set latin1 NOT NULL default '',
  `postcode` varchar(9) default NULL,
  `woonplaats` varchar(24) NOT NULL default '',
  `code_gemeente` smallint(4) unsigned zerofill NOT NULL default '0000',
  `code_land_kvk` smallint(4) unsigned zerofill NOT NULL default '0000',
  `straat` varchar(26) default NULL,
  `huisnr` varchar(9) default NULL,
  `huisnrtoevoeging` varchar(20) default NULL,
  `antwoordnr` int(5) default NULL,
  `postbus` varchar(7) default NULL,
  `created` datetime NOT NULL default '0000-00-00 00:00:00',
  `created_by` char(1) character set latin1 NOT NULL default '',
  `updated` datetime default NULL,
  `updated_by` char(1) character set latin1 default NULL,
  PRIMARY KEY  (`dummy_pk`),
  UNIQUE KEY `adres_uk` (`bkwi_id`,`bkwi_volgnr`,`type`,`table_type`),
  KEY `adres_ref_gemeente_fk` (`code_gemeente`),
  KEY `adres_ref_land_kvk_fk` (`code_land_kvk`),
  CONSTRAINT `adres_ref_gemeente_fk` FOREIGN KEY (`code_gemeente`) REFERENCES `ref_gemeente` (`code`),
  CONSTRAINT `adres_ref_land_kvk_fk` FOREIGN KEY (`code_land_kvk`) REFERENCES `ref_land_kvk` (`code`),
  CONSTRAINT `adres_vestiging_fk` FOREIGN KEY (`bkwi_id`, `bkwi_volgnr`) REFERENCES `vestiging` (`bkwi_id`, `bkwi_volgnr`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `adres_googliaans` (
  `bkwi_id` int(11) NOT NULL default '0',
  `bkwi_volgnr` smallint(6) NOT NULL default '0',
  `type` char(2) character set latin1 NOT NULL default '',
  `table_type` char(1) character set latin1 NOT NULL default '',
  `postcode` varchar(9) character set utf8 default NULL,
  `woonplaats` varchar(24) character set utf8 NOT NULL default '',
  `code_gemeente` smallint(4) unsigned zerofill NOT NULL default '0000',
  `code_land_kvk` smallint(4) unsigned zerofill NOT NULL default '0000',
  `straat` varchar(26) character set utf8 default NULL,
  `huisnr` varchar(9) character set utf8 default NULL,
  `huisnrtoevoeging` varchar(20) character set utf8 default NULL,
  `postbus` varchar(7) character set utf8 default NULL,
  KEY `adres_googliaans_i1` (`bkwi_id`,`bkwi_volgnr`),
  KEY `adres_googliaans_i2` (`postcode`,`huisnr`),
  KEY `adres_googliaans_i3` (`straat`),
  KEY `adres_googliaans_i4` (`woonplaats`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

Suggested fix:
If this is a bug then fix it.

In the statement to tables are used: adres and adres_googliaans.
I use adres_googliaans because it's still not allowed to use table adres in the set clause as well :-(.
[21 Feb 2006 13:09] Valeriy Kravchuk
Thank you for a problem report. I was able to repeat the problem:

mysql> select version();
+-----------+
| version() |
+-----------+
| 5.0.19    |
+-----------+
1 row in set (0.00 sec)

mysql> CREATE TABLE `adres` (
    ->   `dummy_pk` int(10) unsigned NOT NULL auto_increment,
    ->   `bkwi_id` int(11) NOT NULL default '0',
    ->   `bkwi_volgnr` smallint(6) NOT NULL default '0',
    ->   `type` char(2) character set latin1 NOT NULL default '',
    ->   `table_type` char(1) character set latin1 NOT NULL default '',
    ->   `postcode` varchar(9) default NULL,
    ->   `woonplaats` varchar(24) NOT NULL default '',
    ->   `code_gemeente` smallint(4) unsigned zerofill NOT NULL default '0000',
    ->   `code_land_kvk` smallint(4) unsigned zerofill NOT NULL default '0000',
    ->   `straat` varchar(26) default NULL,
    ->   `huisnr` varchar(9) default NULL,
    ->   `huisnrtoevoeging` varchar(20) default NULL,
    ->   `antwoordnr` int(5) default NULL,
    ->   `postbus` varchar(7) default NULL,
    ->   `created` datetime NOT NULL default '0000-00-00 00:00:00',
    ->   `created_by` char(1) character set latin1 NOT NULL default '',
    ->   `updated` datetime default NULL,
    ->   `updated_by` char(1) character set latin1 default NULL,
    ->   PRIMARY KEY  (`dummy_pk`),
    ->   UNIQUE KEY `adres_uk` (`bkwi_id`,`bkwi_volgnr`,`type`,`table_type`),
    ->   KEY `adres_ref_gemeente_fk` (`code_gemeente`),
    ->   KEY `adres_ref_land_kvk_fk` (`code_land_kvk`)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.04 sec)

mysql> CREATE TABLE `adres_googliaans` (
    ->   `bkwi_id` int(11) NOT NULL default '0',
    ->   `bkwi_volgnr` smallint(6) NOT NULL default '0',
    ->   `type` char(2) character set latin1 NOT NULL default '',
    ->   `table_type` char(1) character set latin1 NOT NULL default '',
    ->   `postcode` varchar(9) character set utf8 default NULL,
    ->   `woonplaats` varchar(24) character set utf8 NOT NULL default '',
    ->   `code_gemeente` smallint(4) unsigned zerofill NOT NULL default '0000',
    ->   `code_land_kvk` smallint(4) unsigned zerofill NOT NULL default '0000',
    ->   `straat` varchar(26) character set utf8 default NULL,
    ->   `huisnr` varchar(9) character set utf8 default NULL,
    ->   `huisnrtoevoeging` varchar(20) character set utf8 default NULL,
    ->   `postbus` varchar(7) character set utf8 default NULL,
    ->   KEY `adres_googliaans_i1` (`bkwi_id`,`bkwi_volgnr`),
    ->   KEY `adres_googliaans_i2` (`postcode`,`huisnr`),
    ->   KEY `adres_googliaans_i3` (`straat`),
    ->   KEY `adres_googliaans_i4` (`woonplaats`)
    -> ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
Query OK, 0 rows affected (0.01 sec)

mysql> update adres aa
    -> set    aa.code_gemeente  = (
    ->                            select case when max(code_gemeente) =
    -> min(code_gemeente) then max(code_gemeente) else '0000' end
    ->                            from (
    ->                                 select code_gemeente
    ->                                 from   adres_googliaans bb use index
    -> (adres_googliaans_i4)
    ->                                 where  aa.woonplaats = bb.woonplaats
    ->                                 and    aa.code_land_kvk = bb.code_land_kvk
    ->                                 and    bb.code_gemeente != '0000'
    ->                                 limit 10 -- to speed up query
    ->                                 ) xx
    ->                            )
    -> where  aa.code_gemeente = '0000'
    -> and    length(aa.woonplaats) > 0
    -> and    aa.code_land_kvk = '0001';
ERROR 1054 (42S22): Unknown column 'aa.woonplaats' in 'where clause'

Moreover, the following works:

mysql> update adres aa
    -> set    aa.code_gemeente  = (select max(code_gemeente)
    ->                             from   adres_googliaans bb use index(adres_g
oogliaans_i4)
    ->                             where  aa.woonplaats = bb.woonplaats
    ->                             and    aa.code_land_kvk = bb.code_land_kvk
    ->                             and    bb.code_gemeente != '0000'
    ->                             limit 10 -- to speed up query
    ->                            )
    -> where  aa.code_gemeente = '0000'
    -> and    length(aa.woonplaats) > 0
    -> and    aa.code_land_kvk = '0001';
Query OK, 0 rows affected (0.01 sec)
Rows matched: 0  Changed: 0  Warnings: 0

So, the problem is CORRELATED subquery in FROM. Please, read the manual (http://dev.mysql.com/doc/refman/5.0/en/unnamed-views.html):

"Subqueries in the FROM clause cannot be correlated subqueries."

Exactly your case. So, it is not a bug, but documented limitation of current MySQL server versions.