最近Haskellの勉強をしていて、型って大事だな〜っていうのを改めて思っていたんですが型でふと思い出したことがありました。
長年、PHPを使用して仕事をしているのですが、PDOを使って数値のデータを取得するとなぜか文字列に変換されてしまうあれです。
あれのせいで型を意識せずになんとなくPHPを使っている方も多いのでは?なんて思いながらHaskellを勉強していたのですが、そもそもあの訳わからない変換はなぜ起きてしまうのか、今回きちんと向き合ってみようと思いました。
###まずPDOとは
PHP Data Objectsの略。
PHPからデータベースへアクセスするのを便利にしてくれるもの。
もっとちゃんと書くと、MySQLやPostgreSQLなどデータベースには様々な種類があって、
本来であればそのデータベースごとにそれぞれ合わせた書き方をしてデータ取得をしなくてはならないところ、
このPDOを使用するとどんなデータベース相手でも同じ書き方で操作出来るようになる便利な子。
###今回の謎
PDOを使ってデータベースから数値のデータを取ってくると、文字列で返ってくる
つまり「100」が「’100’」で返ってきたりします。
気になる方は実際に試してみてください。
###なぜこうなるのか
いきなり結論ですが、PDOのプリペアドステートメントという設定が原因
###プリペアドステートメントとは
SQLを実行するときに「変更されると思われる箇所」を変数にしてSQLの命令文を作る機能のことです。
例えば
SELECT * FROM table_name WHERE table_id = 1;
table_idが1のデータを取りたいときはこのようにSQLを書きますが、table_idが2のデータを取りたいときはこうなります
SELECT * FROM table_name WHERE table_id = 2;
最後のtable_idの指定が変わっただけです。
このWHERE句に指定しているtable_idの値を変数化する動きのことをプリペアドステートメントといいます。
つまり、時と場合によって変更が必要と思われるSQLの一部を変数化して命令文を作る設定が「プリペアドステートメント」です。
ここで言われている変数というのは「バインド変数」と呼ばれています。
###メリットは?
①実際にSQLの全文を解析する必要があるのは最初の1回だけになり、あとはバインド変数を変えればいいだけなのでSQLの解析〜コンパイルまでの時間を短縮できる
=高速化
②SQL インジェクション(悪意を持ってSQLを書き換え、システムに害を与えるようなSQLを実行させる攻撃)に対して有効。なぜ有効かというと、SQLの解析が終わったあとにバインド変数を実際の値に置換するので、致命的なSQLインジェクションが発生する余地を極力減らしてくれる
=セキュリティ担保
上記の理由から見ても、プリペアドステートメントは基本的にONにしておいた方が良い設定だと言えます。
ですが、リペアドステートメントをONにしていると、本来は数値型のデータが文字列として返却されてしまうということです。
取得結果をキャストすれば良いかも知れませんが、値によっては予期せぬ結果になってしまいそうな気はします。
注意が必要ですね。