
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ランキング
-
エクセルで最後の文字だけ置き...
-
【Transact-sql】 execの結果を...
-
ソフトバンクの無料着うたのお...
-
WordpressのContact form 7でzi...
-
php+mysqlで複数選択削除について
-
テーブルが5つの時の結合の仕...
-
Postgreのupdateコマンドでエラー
-
PL/SQLの変数について
-
select文のwhere句に配列を入れ...
-
エクセルの関数について教えて...
-
AUTO_INCREMENTのあるテーブル...
-
sqlで、600行あるテーブルを100...
-
SQLにて特定の文字を除いた検索...
-
#1136 - Column count doesn't ...
-
最小値をUPDATE
-
MYSQLの論理削除について質問で...
-
HAVING count()で重複したデー...
-
selectした大量データをinsert...
-
SQLサーバから、項目の属性(型...
-
このサイト(ttp://127.0.0.1/p...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
エクセルで最後の文字だけ置き...
-
エラー 1068 (42000): 複数の主...
-
エクセルの関数について教えて...
-
VIEWの元のテーブルのindexって...
-
sqlで、600行あるテーブルを100...
-
SQLサーバから、項目の属性(型...
-
SQL Left Join で重複を排除す...
-
Access パラメータクエリをcsv...
-
クエリ表示と、ADOで抽出したレ...
-
ストアドのエラーについて
-
マイクラPC版のコマンドで効率...
-
バインド変数について
-
SQLにて特定の文字を除いた検索...
-
副問合せの書き方について
-
【Transact-sql】 execの結果を...
-
”photo id” とは何ぞや?
-
mysql+phpをつかったカートつく...
-
MySQL5.5 viewの処理速度改善に...
-
select文のwhere句に配列を入れ...
-
テーブル名を省略して「h.id」...
おすすめ情報