SQL ステートメントパラメーターを使用すると、再利用可能な SQL ステートメントを作成できます。ステートメントパラメーターを使用する場合、ステートメント内の値は変わっても(
INSERT
ステートメントの追加される値など)、基本的なステートメントテキストは変わりません。その結果、パラメーターを使用することでパフォーマンスが向上し、アプリケーションのコーディングも容易になります。
ステートメントパラメーターについて
アプリケーションで 1 つの SQL ステートメントが、小さな変更を加えながら何度も使用されることがよくあります。例えば、ユーザーが新しい在庫品目をデータベースに追加できる在庫追跡アプリケーションでは、在庫品目をデータベースに追加するアプリケーションコードで、データを実際にデータベースに追加する SQL
INSERT
ステートメントが実行されますが、このステートメントは実行のたびに多少変更されます。テーブルに挿入される実際の値は、追加される在庫品目に固有の値であるため、毎回異なるからです。
このように異なる値で何度も使用される SQL ステートメントがある場合は、SQL テキスト内にリテラル値の代わりにパラメーターを含む SQL ステートメントを使用することをお勧めします。パラメーターは、ステートメントが実行されるたびに実際の値に置き換えられるステートメントテキスト内のプレースホルダーです。SQL ステートメント内でパラメーターを使用するには、
SQLStatement
インスタンスを通常どおりに作成し、
text
プロパティに割り当てる実際の SQL ステートメントで、リテラル値の代わりにパラメータープレースホルダーを使用します。各パラメーターの値は、SQLStatement インスタンスの
parameters
プロパティの要素の値を設定して定義します。
parameters
プロパティは連想配列であるため、特定の値を設定するには次のシンタックスを使用します。
statement.parameters[parameter_identifier] = value;
parameter_identifier
は、名前付きパラメーターを使用する場合は文字列で、名前のないパラメーターを使用する場合は整数インデックスです。
名前付きパラメーターの使用
パラメーターは、名前付きパラメーターにすることができます。名前付きパラメーターには、パラメーター値をステートメントテキスト内のそのプレースホルダーの場所に対応させるためにデータベースで使用される特定の名前があります。パラメーター名は、「:」または「@」の文字と、それに続く名前で構成されます。以下に例を示します。
:itemName
@firstName
次のコードリストは、名前付きパラメーターの使用方法を示しています。
var sql:String =
"INSERT INTO inventoryItems (name, productCode)" +
"VALUES (:name, :productCode)";
var addItemStmt:SQLStatement = new SQLStatement();
addItemStmt.sqlConnection = conn;
addItemStmt.text = sql;
// set parameter values
addItemStmt.parameters[":name"] = "Item name";
addItemStmt.parameters[":productCode"] = "12345";
addItemStmt.execute();
名前のないパラメーターの使用
名前付きパラメーターの代わりに、名前のないパラメーターを使用することもできます。名前のないパラメーターを使用する場合は、SQL ステートメント内で「?」文字を使用してパラメーターを表します。ステートメント内の順番に従って、0 から始まる数値インデックスが各パラメーターに割り当てられます。次の例では、先ほどの例が、名前のないパラメーターを使用するように変更されています。
var sql:String =
"INSERT INTO inventoryItems (name, productCode)" +
"VALUES (?, ?)";
var addItemStmt:SQLStatement = new SQLStatement();
addItemStmt.sqlConnection = conn;
addItemStmt.text = sql;
// set parameter values
addItemStmt.parameters[0] = "Item name";
addItemStmt.parameters[1] = "12345";
addItemStmt.execute();
パラメーターを使用するメリット
SQL ステートメントでパラメーターを使用すると、次のようなメリットがあります。
-
パフォーマンスの向上
-
パラメーターを使用する SQLStatement インスタンスは、実行のたびに SQL テキストを動的に作成する SQLStatement インスタンスに比べて効率的に実行できます。このようにパフォーマンスが向上するのは、1 回準備したステートメントを異なるパラメーター値で何度も実行できるため、SQL ステートメントを再コンパイルする必要がないからです。
-
明示的なデータ型の指定
-
パラメーターを使用すると、SQL ステートメントの作成時には不明な値の型指定された置き換えが可能になります。データベースに渡される値の格納クラスを保証するには、パラメーターを使用するしかありません。パラメーターを使用しない場合は、すべての値が、関連付けられている列の型の類似性に基づいてテキスト表現から格納クラスに変換されます。
格納クラスと列の親和型について詳しくは、
データ型のサポート
を参照してください。
-
セキュリティの強化
-
パラメーターを使用すると、SQL インジェクション攻撃と呼ばれる悪質なテクニックの防止に役立ちます。SQL インジェクション攻撃では、ユーザーがアクセスできる場所(データ入力フィールドなど)に SQL コードが入力されます。この場合、ユーザー入力を直接 SQL テキストに連結して SQL ステートメントを作成するアプリケーションコードでは、ユーザーが入力した SQL コードがデータベースに対して実行されます。次のリストは、ユーザー入力が SQL テキストに連結される例を示しています。
この方法は使用しないでください
。
// assume the variables "username" and "password"
// contain user-entered data
var sql:String =
"SELECT userId " +
"FROM users " +
"WHERE username = '" + username + "' " +
" AND password = '" + password + "'";
var statement:SQLStatement = new SQLStatement();
statement.text = sql;
ユーザーが入力した値をステートメントのテキストに連結する代わりにステートメントパラメーターを使用すると、SQL インジェクション攻撃を防止できます。この場合に SQL インジェクションが発生しないのは、パラメーター値はリテラルステートメントテキストの一部にはならず、置き換えられる値として明示的に扱われるからです。以下は、前のリストの代わりとして推奨されるリストです。
// assume the variables "username" and "password"
// contain user-entered data
var sql:String =
"SELECT userId " +
"FROM users " +
"WHERE username = :username " +
" AND password = :password";
var statement:SQLStatement = new SQLStatement();
statement.text = sql;
// set parameter values
statement.parameters[":username"] = username;
statement.parameters[":password"] = password;
|
|
|