BLOGスタッフブログ

システムエンジニア

Hiroshi Uematsu

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

Hiroshi Uematsuが書いた他の記事

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

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

同意します