BLOGスタッフブログ

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のバージョンアップで対応されていればいいんですが、そうでない場合は注意したほうがいいですね。

上松 博志が書いた他の記事

見積もり・ご依頼など、
お気軽にご相談ください

本サイトはユーザーエクスペリエンスの向上などを目的に、Cookieを使用しています。
右記のバナーで「同意する」をクリックする、または本サイトを利用することにより、
お客様は弊社のCookieポリシーに同意したことになります。

同意します