Bug #9201 Insert Into ... Select incorrect result
Submitted: 15 Mar 2005 17:28 Modified: 16 Mar 2005 13:06
Reporter: Sergei Kulakov (Candidate Quality Contributor) Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server Severity:S3 (Non-critical)
Version:3.23.58 OS:Unix/Windows
Assigned to: CPU Architecture:Any

[15 Mar 2005 17:28] Sergei Kulakov
Description:
Working on a project I found the strange effect: when I executed a select query and displayed its results I got correct results, but when I added "insert into .." to it the result changed. 
I grabbed the tables and made them as small as possible to simplify debugging. I removed all columns I could so that to keep the effect, I also removed some parts of the query. Strangely, removing some columns/query parts made the effect disappear, while removing others did not. 
So finally I got the table Hotels with just 5 columns (out of some 30) and 3 rows and the table Prices without much data either. Hotels stores hotels data while Prices stores their room rates. 

How to repeat:
Here are the queries to recreate the context:

1. Table Hotels
CREATE TABLE Hotels (
  Id smallint(5) unsigned NOT NULL auto_increment,
  Name varchar(128) NOT NULL default '',
  AreaId mediumint(8) unsigned NOT NULL default '0',
  Status enum('Pending','Approved','Declined','Suspended') NOT NULL default 'Pending',
  Page text NOT NULL,
  PRIMARY KEY  (Id),
  UNIQUE KEY LocationId (AreaId,Name)
) TYPE=MyISAM; 

2. Its data
INSERT INTO Hotels VALUES (62,'Flora Beach Hotel',21,'Pending',''),(65,'Hotel Padma',21,'Suspended',''),(77,'Rama Gardens Hotel',21,'Pending','');

3. Table Prices
CREATE TABLE Prices (
  HotelId smallint(5) unsigned NOT NULL default '0',
  No tinyint(3) unsigned NOT NULL default '0',
  ServiceId smallint(5) unsigned NOT NULL default '0',
  Price float NOT NULL default '0',
  PRIMARY KEY  (HotelId,ServiceId)
) TYPE=MyISAM;

4. Its data
INSERT INTO Prices VALUES (62,1,232,35),(65,1,784,50),(77,1,313,35);

5. The next query is supposed to return hotels' id, min price and status. The idea is suspended hotels should have no price displayed. AreaId means geographic area. 

Insert Into tmpHotData
Select Hotels.Id as HotelId, Min(Price) as Price, Hotels.Status
From Hotels as Hotels
Left Join Prices On	(Status!='Suspended' And Prices.HotelId=Hotels.Id)
Where AreaId=21
Group By HotelId

Normally it returns this (correct):

HotelId  Price   Status  
62        35      Pending 
65        NULL   Suspended 
77        35      Pending

If we create a table to store the result

Create Table tmpHotData(HotelId SmallInt UnSigned Not Null, Price float Not Null, Status varchar(32));

and execute this:

Insert Into tmpHotData
Select Hotels.Id as HotelId, Min(Price) as Price, Hotels.Status
From Hotels as Hotels
Left Join Prices On	(Status!='Suspended' And Prices.HotelId=Hotels.Id)
Where AreaId=21
Group By HotelId;

the table will have 
65 0 Pending
in the second row which is impossible: the hotel is suspended!

If the query left join condition is changed to 
Left Join Prices On	(Prices.HotelId=If(Status!='Suspended', Hotels.Id, Null))
the effect remains, but removing any other seemingly insignificant query part like Where AreaId=21 or prices makes the effect disappear. 

This effect is very subtle and requires many conditions to take place. 

Suggested fix:
Please fix!
[16 Mar 2005 13:06] Hartmut Holzgraefe
This is expected behavior as you are trying to insert a NULL value into a NOT NULL column. What happens in this case is that the columns default value is used instead.

Starting with MySQL 4.1 this would also generate a warning:

> show warnings;
+---------+------+-------------------------------------------------------------------+
| Level   | Code | Message                                                           |
+---------+------+-------------------------------------------------------------------+
| Warning | 1263 | Data truncated; NULL supplied to NOT NULL column 'Price' at row 2 |
+---------+------+-------------------------------------------------------------------+
[11 Apr 2005 7:18] Sergei Kulakov
See http://bugs.mysql.com/bug.php?id=9554