
No.2ベストアンサー
- 回答日時:
「?」付きのSQLは、prepareしてからexecuteする文に対して使用する構文です。
?の部分は、パラメータです。つまり、prepareした後で、パラメータに必要な値をセットしてからexecuteを発行します。効率に関しては、先の方の回答の通りです。
プログラムにSQL文が埋め込んであるのですから、多分、何度も何度も同じSQLを発行するのでしょう。RDBMSは、このSQL文を受け取るたびに、SQLをコンパイルして、アクセス計画を生成してという作業をするので、コンパイル済み・アクセス計画生成済みというSQL文が使えるメリットは大きいです。
もう一つ、大きなメリットがあります。
それは、エラーチェックというか、パラメータチェックに関する部分です。
SQLインジェクションという技術というか、ハッキング手法があります。これは、例えば、ホームページでフォームに入力された文字列をSQLに渡して検索などに使用する際に発生します。
"SELECT name FROM category WHERE id=" + id_field なんて形でSQL文を作る時は、id_fieldに何が入っているかを必ず事前にチェックしなければなりません。例えば、id_fieldに、「50;DELETE FROM category」なんて値が入っていたら、どうなると思いますか?サーバーは、二つの文章が同時にexecuteされたものと解釈し、素直にカテゴリーテーブルの全データを抹消します。
これは、ごく単純なパターンです。でも、威力は絶大です。
このため、人の入力が関わる総てのパラメータは完全にチェックする必要があります。
ところで、このようなハッキングに使われる総てのパターンをすらすらと言えますか?どれだけの文字をエスケープすればよいか、ちゃんと漏れなくリストアップできますか?
まぁ、これが完全に出来る人は、そうそういません。
パラメータを使用したSQLの場合、パラメータに値を代入し使用する際にRDBMS側でこのようなパターンのチェックをちゃんとやって、必要なエスケープ処理を自前でやってくれます。(MySQLの場合、バージョンによっては、この為に設定が必要なようです。調べておいてください。確か、この機能がデフォルトではoffになっているバージョンが存在したと思います。)
これにより、セキュリティーの面からも安心して利用できるようになります。(少なくとも、自分で作ったチェックルーチンより信用できるでしょう。)
まぁ、こんな利点もありますと言うことで。
一部を変数を用いて変化させる必要があるSQL文は、基本的には、preparを使用し、変数部分は?でパラメータを使用するのが基本的には良いと言うことです。
No.1
- 回答日時:
SQLを文字列を組み立てて、prepare + executeする場合を考えましょう。
表名や列名、条件式の演算子などを変えた場合は、そのたびにオプティマイザによるアクセス計画の作成が行われます。
一方、SQLの中で、条件式の値部分、挿入値や更新値だけが変わるものを複数回実行したい場合は、? を使うことで、最初の一回だけアクセス計画を作成し、それ以降は既に作成済のアクセス計画を使えることで、オーバーヘッドを抑止できるようになります。
これは、条件式の値を変えながら複数のSELECT文を実行したり、値を変えながら複数回のUPDATE、DELETE、INSERTする場合に有用です。
また、いつくかのRDBMSでは、異なるセッション間でもアクセス計画の再利用ができる機能を提供しているものもあり、これらは各RDBMSにより、クエリキャッシュ、SQLプールなど、いろいろな名前が付いています。
なお、再利用するためには、「キーワード間の空白の個数も同じでなければならない」など、制限がある場合が多いです。
再利用不可の例
"select * from " + 表1 + " where 列1=値"
"select * from 表1 where " + "列 between a and b"
再利用可能な例
"select * from 表1 where 列1=?"
"select * from 表1 where 列1 in(?,?,?)"
"update 表1 set 列2=? where 列1=?"
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
人気Q&Aランキング
-
4
select文のwhere句に配列を入れ...
-
5
VIEWの元のテーブルのindexって...
-
6
副問合せの書き方について
-
7
”photo id” とは何ぞや?
-
8
同一テーブルの同一フィールド...
-
9
SQL Left Join で重複を排除す...
-
10
[MySQL] 3つのテーブルの結合で...
-
11
別テーブルからSELECTした値を...
-
12
複数テーブルのGROUP BY の使い...
-
13
バインド変数について
-
14
キー毎の、ある列のmaxのレコー...
-
15
inner joinをすると数がおかし...
-
16
存在しないレコードの抽出方法...
-
17
【Transact-sql】 execの結果を...
-
18
WHERE id = ? について
-
19
SELECT文で片方のテーブルを優...
-
20
DB設計について
おすすめ情報
公式facebook
公式twitter