2012.01.30 システム
SQLの実行結果がプログラムからだとおかしくなる?
PHPでPDOを利用する場合に、おかしな現象が発生することがあります。
(おかしな現象が発生したのは、PHP5.2.13・mySql5.1.60です)
このおかしな現象は、下記のような結合SQLを実行した場合に発生します。
SELECT t999.id AS id ,t999.name AS name ,m001.name AS name01 ,m002.name AS name02 ,m003.name AS name03 ,m004.name AS name04 FROM hogehoge_main AS t999 INNER JOIN master_01 AS m001 ON t999.m1code = m001.code INNER JOIN master_02 AS m002 ON t999.m2code = m002.code LEFT OUTER JOIN master_03 AS m003 ON t999.m3code = m003.code INNER JOIN master_04 AS m004 ON t999.m4code = m004.code WHERE t999.id = '01'
何の変哲も無いSQLです。
このSQLを各種のSQLクライアントで実行すると…
id | name | name01 | name02 | name03 | name04 |
01 | マリンロード | デザイン | プラスEC | システム | セールス |
こんな感じの結果が取れました。実に普通ですね。
それではプログラムに組み込んで実行してみましょう。
id | name | name01 | name02 | name03 | name04 |
01 | マリンロード | デザイン | プラスEC | null | セールス |
なんと、name03が取れなくなってしまいました…。
ですが、SQLクライアントで実行した結果は正常です。
SQLには問題はなく条件も入っており、何も問題無いように見えます。
この現象の原因は、「master_03テーブルとの外部結合が内部結合中に混じっているから」でした。
SQLクライアント上はちゃんと動いているのに、どうしてこうなるのやら…
PDO上でどういう解釈をされているのかわかりませんが、内部結合と外部結合が混じったSQLでこの現象が発生するようです。
上記の問題を解決する方法は、外部結合を内部結合の後にすることで解決します。
SELECT t999.id AS id ,t999.name AS name ,m001.name AS name01 ,m002.name AS name02 ,m003.name AS name03 ,m004.name AS name04 FROM hogehoge_main AS t999 INNER JOIN master_01 AS m001 ON t999.m1code = m001.code INNER JOIN master_02 AS m002 ON t999.m2code = m002.code INNER JOIN master_04 AS m004 ON t999.m4code = m004.code LEFT OUTER JOIN master_03 AS m003 ON t999.m3code = m003.code WHERE t999.id = '01'
SQLの解釈上の問題のようですが、こんなおかしな挙動をするのは予想外でした。
こんな現象、実際の本番環境で発生したらすぐに原因特定できないでしょうね…。
PHPのバージョンアップで対応されていればいいんですが、そうでない場合は注意したほうがいいですね。