• ベストアンサー

PHPのSQL文のデバッグ方法とコーディング方法について

http://okwave.jp/qa3663217.html 上記のANo.2の回答についての疑問です 本来上記の回答者に対して便乗質問すればよかったのですが、 早々に締め切られてしまったので新しく質問させていただきます。 ☆上記のANo.2でSQLのデバッグ方法が回答されいる(下記に抜粋)のですが、 (1)は一般的なSQLデバッグ方法なのでしょうか? (2)は一般的なSQLの記述方法なのでしょうか? ●ANo.2の抜粋 (1)SQL文はヒアドキュメントをつかう (2)テーブルやフィールドはバッククォート、値はシングルクォートでくくる (3)変数は{$hoge}形式で参照する (4)SQL文の最後になるべく;はつけない (5)エラーはmysql_error()で確認する。 ●抜粋終わり ○私が疑問に思う理由は下記のとおりです。 (1)はHTML文を出力するには有効な機能だと思います しかし、SQLをデバッグする場合(特に動的SQLをデバッグする場合)、 最終的に加工されたSQL文をvar_dump,echo,print等で一切加工せずにデバッグしないと、 ヒアドキュメントへ加工中にSQLが(タイプミスとかカットアンドペーストミス)変わってしまう可能性があり、正しくデバッグできない可能性があると思います。 特にデバッグする人は、SQLをヒアドキュメントへ転記中に無意識のうちに正常なSQLに変換してしまっていて、バグの原因が掴めないなんてケースは結構見てきました。 デバッグする人は何がバグっているのかを探っているはずので、出来るだけデバッグ対象コードはまず生のまま見るべきだと思っています。 また、デバッグ終了後にデバッグ文を消す作業が発生し、 誤ってデバッグコード以外の必要なコードも削除してしまう恐れもあります。 var_dumpであれば、一括置換でコメントアウトしたり出来ますし、 あるいは、var_dumpをラップする関数を用意しておき、 デバッグフラグがONの場合のみvar_dumpを走らせるようにしておけば、 var_dumpを削除する作業そのものが不要で、 必要な時にデバッグON/OFF出来るかと思います。 (2)は「値はシングルクォート」(※1)は納得できるのですが、 「テーブルやフィールドはバッククォート」(※2)は、※1と混在してSQLを書いた場合、どれが列名でどれが変数(または定数)なのか、判別しにくくなり、 余計なバグを混入させたり、可読性を落としたりすると思います。

質問者が選んだベストアンサー

  • ベストアンサー
  • inu2
  • ベストアンサー率33% (1229/3720)
回答No.2

あくまでも個人的な意見 1. ヒアドキュメントでSQL文の生成はしない。PHPのヒアドキュメントって処理遅いんで考えたことすらないですね。 $sql = "SELECT column1,column2 FROM table_name WHERE id = :id AND user_name = :user_name "; 等のように作りこんでおいて、プリペアドステートメントを使ってクエリーしております。 (*個人的に、SQLの予約語や関数、構文は大文字で、テーブル名、カラムは小文字で という法則で作るのが好きなだけです) 2. >「テーブルやフィールドはバッククォート」(※2)は、※1と混在してSQLを書いた場合、どれが列名でどれが変数(または定数)なのか、判別しにくくなり、、・・・ 私はプリペアドステートメントを使いますので、混乱する要素が皆無となりますので判別しにくいということはありえなくなります。 また、カラム名を ` で囲むことで SQLの予約語なのか カラム名なのかを判別しやすくなると思います。 といっても、` で囲むのってMySQLだけですので 一般的にはSQLの予約語をカラム名に使うなんてこと有り得ないので、DB設計時に予約語をカラム名にしてしまうヤツがどうかしているという事 3. ちなみに、 $sql = "SELECT column1, column2 FROM table_name WHERE id='{$id}' AND user_name='{$user_name}'"; とやるよりも $sql = "SELECT column1, column2 FROM table_name WHERE id='".$id."' AND user_name='".$user_name." "; のほうが速度的には速いです。 個人的には、プリペア主義なのでこういう悩みはありません。 4. プリペア主義なので・・・以下略 5. throwするのは設計者の自由なので、なに使ってもいいんじゃないでしょーかね?

noname#246547
質問者

お礼

返答ありがとうございます >$sql = "SELECT column1,column2 FROM table_name WHERE id = :id AND user_name = :user_name "; >等のように作りこんでおいて、プリペアドステートメントを使ってクエリーしております。 この書き方はOracleのProC*を使用していたころに書いたことがあります。 いままでのSQLの書き方では一番可読性がよいと思いました。 ただ、ProC*のプリペアドステートメントでは、WHERE句をifやfor等で可変条件に出来なかったため、使い勝手が悪かったですね。 PHPだと、文字列変数内に記述できるため使いやすそうです。 >` で囲むのってMySQLだけですので なるほど、MySQLの方言だったのですね。 当方MySQLはほとんど触ったことが無かったので知りませんでした。 方言であるならば、やはり他のDBにならって"` "を使用しないほうが、 保守性が良い感じがしますね。 ソースコードは一度作成したらシステムが運用終了するまで、 保守する必要があるが、保守する人間が必ずしもMySQLに精通しているとは限らないので、他のDBでも一般的なコーディングスタイルのほうが保守性が良い気がします。 >DB設計時に予約語をカラム名にしてしまうヤツがどうかしているという事 同意です。 これを許すと不要なバグを増やすだけだと思います。 これを許さなければ、「カラム名を ` で囲むこと」は不要な気がします。

その他の回答 (3)

  • wp_
  • ベストアンサー率54% (132/242)
回答No.4

>私がつかう理由は手が抜けて、バグが減るから。 確かに初期作成時は楽でよいのですが、それをそのままにされると運用・改修時に見づらくなるのですよ。 昨今のエディタではコード部とデータ部の色分けが可能なので、ヒアドキュメントでずらーっと書かれると逆に鬱陶しくなります。^^; もっとも、一番大きな理由としてはやはり「パース後に内部変換を行うので処理が非常に重い」ということですけどね。No.2の方も言及されてますけど。 「見づらい」に関連しますが、私的に大きな要因としてインデントが崩れるということがあります。 特にSQLの場合、桁を上げたら上げっぱなしで終わる(明示的な終了がない)のでどこからどこまでがクエリが比較的分かりづらくなります。 ヒアドキュメント内でも同じだけインデントすればいいじゃんと言った新人が居ましたが、彼には一時間正座してもらいました。^^; やはりクエリはクエリで単体テストを行い、正しいクエリであることが保証された上でコードに組み込むのがベストかと思います。 ともあれ、「現在作成時の作業簡素化」か、「処理の最適化・後続の人間のための可読性」かを取るならやはり後者が一般的ではないかなぁと。 >SQL 当方は新人のころOracleメインだった影響で全部大文字にするのが好きですね。 たまにSelectとかFromとか見て発狂しそうになります。 当然、書いた奴は正座ですが。

noname#246547
質問者

お礼

返答ありがとうございます。 >確かに初期作成時は楽でよいのですが、それをそのままにされると運用・改修時に見づらくなるのですよ。 同意です。 大半のプログラマは現在の仕様を満たすだけでその後のことを考えずにコードを書くことが多い気がします。 運用後の保守や、再利用のことを考えてコーディングする人ってまずお目にかかったことがありません。納期に追われてそれどころじゃないんでしょうけど。 あと、コーディングは若い人が担当することが多いので、 そもそも、運用・改修のことなんて気が付きもしない感じですね。 >特にSQLの場合、桁を上げたら上げっぱなしで終わる(明示的な終了がない)のでどこからどこまでがクエリが比較的分かりづらくなります。 最後に明示的な終わりもありますし、これはヒアドキュメントを使ったほうが有利な気がしますね。 >ともあれ、「現在作成時の作業簡素化」か、「処理の最適化・後続の人間のための可読性」かを取るならやはり後者が一般的ではないかなぁと 同意です。 趣味でプログラムして他の人間がコードを読むことがない場合なら前者ですが、仕事等で不特定多数が読む可能性がある場合は後者であると思います。 >当方は新人のころOracleメインだった影響で全部大文字にするのが好きですね。 >たまにSelectとかFromとか見て発狂しそうになります。 同意です(笑) 当方もOracle上がりなので予約語は大文字が基本ですね。 これをするだけでかなり可読性が上がりますね。

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.3

元文書を書いた身としては一応、意見をだしておきます。 #1さんのいう「クエリは変数化しておけ」が、メインですね。 変数化の手段としてのヒアドキュメントということで。 ま、一言でいえば「いやならつかわなければいいんじゃない?」 ってことで・・・ (1)意外にヒアドキュメントは結構嫌われているのですね。 いろんなやり方を模索してきましたが私的にはヒアドキュメントが もっともしっくりくる作業効率化の手段になっています。 私がつかう理由は手が抜けて、バグが減るから。具体的には・・・ ・無駄にクォーテーションのエスケープでパースする必要がない ・変数をたしこんでいくやり方だと、区切り文字を入れ忘れるバグなどがある ・コマンドや条件を行単位でつけられきる ・SQLのエラーが行番号をかえしてくれる場合があり、エラー箇所を確定しやすい ・行単位の処理なのでSQLのコメントアウトがつかえる(#処理) ・なによりもSQLがSQL文として表示されるので直観的でデバッグしやすい 特に動的なSQLになるほど、ヒアドキュメントのありがたみがでてきます $条件1="AND ・・・・"; $条件2="AND ・・・・"; $条件3="AND ・・・・"; $sql=<<<eof SELECT * FROM hoge WHERE 1 {$条件1} {$条件2} {$条件3} eof; こんな風に書きますね。 (2)バッククォートは一般的です。 このQ&Aでも何度もバッククォートさえつければ、引っかからなかった バグの質問があがっています。 テストテーブルつくってついつい直観的な予約語をフィールド名に つかってしまうなど、ままあるでしょう。 もちろん使わない方が見やすくて、バグをださない自信があるなら 無理につけなくても構いませんが、保険でつけておいても損はありません。 たしかに他のSQLへの乗り換えの際には確かに変更が面倒かもしれませんね。

noname#246547
質問者

補足

返答ありがとうございます。 質問の性質上、本来はアンケートカテゴリがふさわしいかと思いましたが、 yambejp様の意見をぜひ伺いたいと思いまして、 目に触れる可能性の有るこのカテゴリで投稿させていただきました。 yambejp様の回答を勝手に転用してしまい不快な思いをさせてしまったとおもいます。この点深くお詫び申し上げます。 それでは本題に入らせていただきます。 >ま、一言でいえば「いやならつかわなければいいんじゃない?」 たしかにそうなのですが、コレを言い出すとQ&Aの意味が無いので スルーさせていただきます。 >(1)意外にヒアドキュメントは結構嫌われているのですね。 嫌われているかどうかは解りませんが、私はこの方法でSQLを埋め込んでいるソースを見たことがありませんでした。 簡単なツールや一時的な確認用のソースなど、将来にわたって保守する必要がないプログラムには使い勝手が良いと思いました。 >・無駄にクォーテーションのエスケープでパースする必要がない たしかにこれは有効ですね >・変数をたしこんでいくやり方だと、区切り文字を入れ忘れるバグなどがある これはヒアドキュメントならば入れ忘れることが少ないとはいいがたい気がします。 >・コマンドや条件を行単位でつけられる これはヒアドキュメントにアドバンテージがあるとは思えません。 条件によって検索条件が変動する場合、ifやforなどの制御文で条件を変える必要があるはずなので、この部分はヒアドキュメントの外で作らざる得ないのでは? >・SQLのエラーが行番号をかえしてくれる場合があり、エラー箇所を確定しやすい これは優れていますね >・行単位の処理なのでSQLのコメントアウトがつかえる(#処理) プログラム内部から発行するSQL文なので、代入文ごとプログラムが提供する1行コメントアウトで消しても問題ないと思うのですが。 唯一SQL文内にSQLのコメントが必要だったプログラムは、 Oracleでルールベースオプティマイザの制御をSQLのヒントとして与える必要があった場合でした。 >・なによりもSQLがSQL文として表示されるので直観的でデバッグしやすい ですが、 >$条件1="AND ・・・・"; 中略 >eof; を見る限り 動的な部分はヒアドキュメント以外の方法で処理されており、 「SQL文がSQL文として表示される」のは不変的な部分のみで、 ヒアドキュメント以外の方法と大差ないような気がします。 >テストテーブルつくってついつい直観的な予約語をフィールド名に つかってしまうなど、ままあるでしょう。 すいませんが、私はありませんでした。 理由はNo.2のお礼の最後の部分に記載してあります。 最後に、貴重な時間を割いて返答していただき誠にありがとうございました

  • wp_
  • ベストアンサー率54% (132/242)
回答No.1

>(1)は一般的なSQLデバッグ方法なのでしょうか? おそらくヒアドキュメント云々、ではなく「クエリは変数化しておけ」と言うことを言いたかったのではないかと邪推しますが。 ちなみに当方はヒアドキュメントは使わせません。HTMLだろうがSQLだろうが使った奴は殴ります。 // というかSQLとPHPは別個で単体テストすべきでは。 >(2)は一般的なSQLの記述方法なのでしょうか? これに関しては一般的といわざるを得ません。 >余計なバグを混入させたり、可読性を落としたりすると思います。 というのは完全に記述者の腕です。読み取れない方or読みづらく記述した方が悪いです。

noname#246547
質問者

お礼

返答ありがとうございます。 >完全に記述者の腕です。読み取れない方or読みづらく記述した方が悪いです。 埋め込みSQLを可読性、保守性、品質すべてを保つようにコーディングするのは難しいですよね。 SQLが複雑になればなるほど、今後保守する人にいかに見やすいコードにするか悩むところですよね。 しばしば、SQLの整合性を考えるより、いかに見やすくするかに時間をかけることのほうが多い場合もありました。

関連するQ&A