
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で質問しましょう!
似たような質問が見つかりました
- Oracle sqlで質問です。 aテーブルとbテーブルがあり、下記のsqlで取得したidとnameに一致しないレ 1 2022/04/20 20:34
- MySQL 書籍の内容はまともでしょうか? 1 2023/01/22 03:07
- MySQL 共通点はあります。何が違うのでしょうか? 1 2023/01/27 05:22
- Access(アクセス) アクセス where句を使用して複数条件抽出をするには 2 2022/08/29 13:24
- Access(アクセス) アクセス 有効なフィールド名、または式として認識できませんのエラー 3 2022/08/19 11:53
- Access(アクセス) 実行時エラー3131 FROM 句の構文エラーです について 7 2022/06/13 15:45
- PHP php my adminより取り出したデータ表示 2 2022/06/15 11:56
- MySQL 下記の問合せを行うクエリを、PhpMyAdminで作成して実行せよ。 「名前(first name) 1 2023/06/24 13:03
- Oracle SQL update方法 2 2022/06/22 14:07
- PHP 重複を防ぐ記述について教えて下さい。 3 2023/04/03 14:35
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
複数テーブルのGROUP BY の使い...
-
フリーマーケット!
-
ローカルルーターモードとは
-
bashスクリプトで特定の文字に...
-
mysqlについて
-
尾形光琳の作品が見たい!
-
製品の最安店舗を取りたい。
-
レコードセットに新規追加する
-
EXISTSでの列名指定
-
データベース内の値をweb内でテ...
-
Dell Latitude C600に合うメモ...
-
JOIN後同一名カラムから値がと...
-
ストアド内でカラム名一覧を取得
-
SQLServerでのデータディクショ...
-
INSERT時の大小比較を含む重複...
-
このSQL文の意味を教えてくださ...
-
verilogに適したvimの設定を探...
-
正規表現を使って前方一致置換...
-
最小値をUPDATE
-
MySQLでvarcharに先頭ゼロをセ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
エクセルで最後の文字だけ置き...
-
エクセルの関数について教えて...
-
sqlで、600行あるテーブルを100...
-
select文のwhere句に配列を入れ...
-
SQLにて特定の文字を除いた検索...
-
WordpressのContact form 7でzi...
-
SQLサーバから、項目の属性(型...
-
VIEWの元のテーブルのindexって...
-
クエリ表示と、ADOで抽出したレ...
-
マイクラPC版のコマンドで効率...
-
【Transact-sql】 execの結果を...
-
SQL Left Join で重複を排除す...
-
エラー 1068 (42000): 複数の主...
-
[MySQL] UNIQUE制約の値を更新...
-
inner joinをすると数がおかし...
-
1テーブル&複数レコードの更新...
-
Access パラメータクエリをcsv...
-
期間の重複を調べるSQL文につい...
-
Unionした最後にGROUP BYを追加...
-
Updateの複数テーブル条件時のL...
おすすめ情報