Oracleのバインド変数を介して列名を参照することは可能ですか?
-
03-07-2019 - |
質問
列名を参照して、Oracleデータベースと通信するアプリケーションでクエリを注文しようとしています。バインド変数を使用して、クエリの順序を動的に変更できるようにします。
私が抱えている問題は、データベースが列ごとの順序を無視しているように見えることです。
バインド変数を介してデータベース列を参照する特定の方法があるかどうか、またはそれが可能かどうか、誰もが知っていますか?
e.g私のクエリは
SELECT * FROM PERSON ORDER BY :1
(:1
は PERSON.NAME
にバインドされます)
クエリは結果をアルファベット順に返していません。データベースがこれを次のように解釈しているのではないかと心配です:-
SELECT * FROM PERSON ORDER BY 'PERSON.NAME'
これは明らかに動作しません。
どんな提案でも大歓迎です。
解決
いいえ。テーブル名または列名にバインド変数を使用することはできません。
この情報は、実行計画を作成するために必要です。注文するものがわからない場合、たとえば、どのインデックスを使用するかを判断することは不可能です。
バインド変数の代わりに、プログラムで列名を作成するときに、SQLステートメントに列名を直接挿入する必要があります。 SQLインジェクションに対して予防策を講じていると仮定すると、それに対するマイナス面はありません。
更新:フープをジャンプしたい場合は、おそらく次のようなことができます
order by decode(?, 'colA', colA, 'colB', colB)
しかし、それは馬鹿げています。そして遅い。しないでください。
他のヒント
JDBCを使用している場合。コードをバインド変数なしで何かに書き換えることができます。このようにして、順序を動的に変更することもできます。例:
String query = "SELECT * FROM PERS ";
if (condition1){
query = query+ " order by name ";
// insert more if/else or case statements
} else {
query = query+ " order by other_column ";
}
Statement select = conn.createStatement();
ResultSet result = select.executeQuery(query);
または
String columnName = getColumnName(input);
Statement select = conn.createStatement();
ResultSet result = select.executeQuery("SELECT * FROM PERS ORDER BY "+columnName);
ResultSet result = select.executeQuery(" SELECT * FROM PERS ORDER BY" + columnName);
は常にデータベースに対する新しいステートメントになります。つまり、既に説明したティロのように、「再注文」することは不可能です。すでにバインド、計算、準備、解析されたステートメント。この結果セットをアプリケーションで繰り返し使用し、時間の経過とともに変化する唯一のものがプレゼンテーションの順序である場合は、クライアントコードでセットを順序付けてみてください。それ以外の場合、動的SQLは問題ありませんが、フットプリントが大きくなります。