はじめに

このページでは、SQL文評価の高速化や、SQLインジェクション対策にも効果があるPrepared Statementについて説明します。

Prepared Statementとは?

Prepared Statementとは、通常DBに対してSQL文を実行する処理「(1) 構文解析」「(2)処理の実行」のうち、(1)の構文解析を切り出して行うことを指します。

Prepared Statementの基本

たとえば、以下のような2つのSQL文があるとします。

サンプルコード 1
SELECT name FROM tbl_user WHERE age=30 ORDER BY id ASC

サンプルコード 2
SELECT name FROM tbl_user WHERE age=31 ORDER BY id ASC

2つのSQL文の違いは、WHERE節で比較しているカラム「age」の値が30か31かの違いだけですが、このSQL文を一つ一つ実行すると、当然のことながら2回の構文解析と2回の処理の実行が行われます。

一方、この2つのSQL文は、以下のSQL文において、$1にそれぞれ30、31を代入することに他なりません。

サンプルコード 3
SELECT name FROM tbl_user WHERE age=$1 ORDER BY id ASC

もし上記のSQL文の構文解析を1回で済ませることができ、処理の実行時に30/31と任意の数字を代入することができれば、この2つの処理をするのに、1回の構文解析と2回の処理の実行が行われることになり、結果的に構文解析の回数を減らすことができます。

このような機能を提供するのが、Prepared Statementです。

Prepared Statementの素晴らしい副作用

上記の説明のとおり、SQL文の構文解析を予め行うのがPrepared Statementですが、このPremared Statementの素晴らしい副作用に、比較や代入する値の型が構文解析時に予め判別される点があります。

構文解析により予め変数の型が判別されると、判別された型と違う型のデータを比較/代入しようとしても、DBI側でそれを検知することができます。
一般的なDBIの実装では、型の不一致が発生した場合は、エラーを出したり、適切な型にキャストしたりするため、結果として変数にSQL文を挿入されて意図しないSQL文を実行される「SQLインジェクション」を防ぐことができます。

実現方法

以下は、PerlからPostgreSQLのPrepared Statementを使う際のサンプルコードです。

サンプルコード
use DBI;

$tDBHandler=DBI->connect('DBI:Pg:host=db_host;dbname=db_name','db_user','db_password');

$tSQLStatement='xxxx ? ? ? ?';

$tStatementHandler=$tDBHandler->prepare($tSQL);
$tStatementHandler->execute($a,$b,$c,$d);

$tDBHandler->disconnect();

「$tSQLStatement='xxxx ? ? ? ?';」の部分には、適切なSQL文を入れてください。
「prepare」により、$tSQLStatementに代入されたSQL文が構文解析され、次の「execute」では、構文解析は省略され、直ちにSQL文が実行されます。


あなたの探し物は見つかりましたか?
まさにこれだ
参考になった
ちょっと違う
これじゃない

何かメッセージがあればお願いします

このメッセージを非公開にする

ご注意

・頂いたメッセージは管理者のチェックの後、公開されます。
・メッセージの公開を希望されない場合には、「このメッセージを非公開にする」にチェックを入れてください。
・管理者が不適切と判断したメッセージは公開しませんので、予めご了承ください。


まさにこれだ
1 (50%)
ちょっと違う
1 (50%)

表示できるメッセージはありません。