web-dev-qa-db-ja.com

引用符なしのPreparedStatement.setString()メソッド

次のようなコードでPreparedStatementを使用しようとしています。

SELECT * FROM ? WHERE name = ?

明らかに、setString()を使用してテーブルと名前のフィールドを設定するとどうなりますか?

SELECT * FROM 'my_table' WHERE name = 'whatever'

クエリは機能しません。行が次のようになるように、引用符なしで文字列を設定する方法はありますか?

SELECT * FROM my_table WHERE name = 'whatever'

または、それをあきらめて、代わりに通常のステートメントを使用する必要があります(引数はシステムの別の部分から来ており、どちらもユーザーが入力していません)?

12
Slavko

パラメータを使用して、テーブルをパラメータ化したり、データベースオブジェクトをパラメータ化したりすることはできません。これらは主に、WHERE/HAVING句のパラメータ化に使用されます。

必要なことを行うには、自分で置換を行い、必要に応じて通常のステートメントを作成する必要があります。

プリペアドステートメントを使用する場合、これは、ステートメントに対して事前処理を行うためのデータベースへのヒントです。文字列を解析し、場合によっては実行プランを決定します。クエリで使用されるオブジェクトが動的に変更される可能性がある場合、データベースは事前の準備をあまり行うことができません。

17
mdma

残念ながら、プリペアドステートメントのテーブル名をパラメータ化することはできません。必要に応じて、文字列を作成し、動的SQLとして実行できます。

3
Zugwalt

あなたのSQLがそのように本当に無限に柔軟であるとは思えません。テーブルの数は有限であるため、必要なSQLを表現するための静的な最終文字列の数も有限です。

引き続きPreparedStatementを使用し、変数をバインドします。これは完全に価値があり、SQLインジェクションの問題を回避するときに特に役立ちます。

3
duffymo

あなたがした間違いはあなたがパラメータとしてテーブル名を渡すことができないであるということです。値はSQLステートメントにのみ渡す必要があります。

例:必要な場合:

Select * from LoggedUsers where username='whatever' and privilege='whatever';

次に、PreparedStatementを次のようにビルドする必要があります。

Select * from LoggedUsers where username=? and privilege=?

setString(1, usernameObject);
setString(2, privilegeObject);

PreparedStatementの目的は、データベース接続コードの難易度と読みやすさを軽減することです。開発者がStatementのインスタンスで非常に多くの列値を使用する必要がある場合、セミコロン、コンマ、プラス(連結演算子)を配置するのは非常に困難です。 )。

設計されていない、誤って利用したいと思っていると思います。

1
Venkat