おのれ憎きQueryめ…
プログラムの書き方はわかるけど、データベースからクエリを書いてデータを引っ張るのは…
って人多いと思います。
多いよね?
そうだよね??
…はい、多いということで
僕もそんな中の一人です。
1つのカラムを検索して、レコード1行引っ張ってくる。
くらいなら出来るけど、実践レベルではまだまだです。
そんな僕がハマったqueryのポイントを紹介します。
SQLには書き順がある。
知ってました?
適当に書いちゃ駄目なんですよSQL。
やめてください、当たり前体操を踊らないでください!
書く順序は
SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY
です。
間違ってもこっちのほうが見栄えが良いからと言って
SELECT * FROM table_name ORDER BY user_id DESC WHERE user_type = 'men'
とか書いちゃ駄目です。
上記の場合ORDER BY
がWHERE
よりも前に来てしまっています。
なので
SELECT * FROM table_name WHERE user_type = 'men' ORDER BY user_id DESC
って書くのが正しいです。
プレースホルダはまとめて確保する感じで書く。
PHPでクエリを書く時にセキュリティの観点からPDOを利用すると思います。
PDOのクエリの書き方は少し独特で、変数をクエリに含めることは悪い事です。
なので変数の代わりにプレースホルダーというものを利用するわけですが
SELECT * FROM table_name WHERE user_id = :id
って感じに書きます。
おそらくこのクエリは:id
というプレースホルダーが確保されているので
クライアントから何かしらのパラメータを受け取って動的なクエリを実行しようとしているのでしょう。
ではクライアントから受け取ったパラメータを元にLIKE検索したい時はどうするでしょう?
SELECT * FROM table_name WHERE user_name LIKE '%:text%'
あー、なるほど、:text
というプレースホルダーがそこに入る感じで書いたんですね~
駄目です、エラーが出ます、このクエリは絶対悪です。
正解は
SELECT * FROM table_name WHERE user_name LIKE :text
とクエリは書いて、バインドする際は
bindValue(':text','%'.input_text.'%',PDO::PARAM_STR);
と書いてexecute()
しましょう。
プレースホルダーはそれぞれ固有である。
プレースホルダーの話が続きます。
SELECT * FROM table_name WHERE (user_name LIKE :text OR user_addr LIKE :text OR user_mail LIKE :text)
bindValue(':text','%'.input_text.'%',PDO::PARAM_STR);
なるほど、user_name
とuser_addr
とuser_mail
から検索するようなクエリを書いてますね。
プレースホルダーは同じ:text
を確保してますね。
一見動きそうですが、これも動きません。
正しくは
SELECT * FROM table_name WHERE (user_name LIKE :text1 OR user_addr LIKE :text2 OR user_mail LIKE :text3)
bindValue(':text1','%'.input_text.'%',PDO::PARAM_STR);
bindValue(':text2','%'.input_text.'%',PDO::PARAM_STR);
bindValue(':text3','%'.input_text.'%',PDO::PARAM_STR);
です。
プレースホルダーはそれぞれ固有のものなので、:text
だけでズルして楽するのは駄目です。
なのでそれぞれ別のプレースホルダーを確保し、それぞれバインドします。
編集後記
入社7日目
任された案件、一日半あれば終わるやろ、とかなめてたらqueryにハマって終わりませんでした…
なめてたよquery、君も強い…
僕は弱かったよ。
クエリをシュババってスマートに書けるおじさんになりてぇ。