アプリケーションのログファイルでクエリが実行されているのを見ました。次のようなクエリが含まれていました。
SELECT ID FROM CUST_ATTR49 WHERE 1=0
何も返さないようにバインドされているそのようなクエリの使用は何ですか?
このようなクエリを使用して、データベースにpingを送信できます。条項:
WHERE 1=0
非データが送り返されるようにし、CPUチャージ、ネットワークトラフィック、その他のリソース消費を防ぎます。
そのようなクエリは以下をテストできます:
WHERE 1=0 OR <condition>
)考えられるユースケース:検索結果を取得したくないフィルターフォームがあります。フィルタを指定すると、それらはwhere句に追加されます。
または、SQLクエリを手動で作成する必要がある場合に通常使用されます。例えば。 where句が空であるかどうかを確認する必要はありません。次のようなものを追加するだけです。
where := "WHERE 0=1"
if X then where := where + " OR ... "
if Y then where := where + " OR ... "
(ORで句を接続する場合、0 = 1が必要で、かつANDが1 = 1の場合))
これは、テーブル内のデータを抽出せずにテーブルからテーブルスキーマを抽出するためにも使用できます。アンドレア・コレオーニが言ったように、これらはこれを使用する他の利点になるでしょう。
一部のシステムはスクリプトを使用し、選択されたレコードを完全なリストから非表示に動的に設定できます。したがって、偽の条件をSQLに渡す必要があります。たとえば、500の内の3つのレコードは、医学的な理由でプライバシーとしてマークされている可能性があり、全員に表示されるべきではありません。動的なクエリは、HRの500のレコードが管理者に表示され、497のレコードが管理者に表示されることを制御します。条件付きで設定されるSQL句に値が渡されます。つまり、システムにログインしているユーザーに応じて、「WHERE 1 = 1」または「WHERE 1 = 0」になります。
これはメタデータの取得に非常に優れており、一般的なものになります。多くのDBにはオプティマイザーがあるため、実際には実行されませんが、依然として有効なSQLステートメントであり、すべてのDBで実行する必要があります。これは結果をフェッチしませんが、列名が有効であること、データ型などを知っています。実行されない場合、DBに問題があることがわかります(not upなど)。 。
答えとして-しかし、@ AndreaColleoniがすでに言及したことに対するさらなる明確化として:
多くのOR動的クエリの条件を管理します(例:
WHERE 1=0 OR <condition>
)
これをクエリの一部のスイッチ(オン/オフ)ステートメントとして使用しています。
私が使用する場合
WHERE 1=1
AND (0=? OR first_name = ?)
AND (0=? OR last_name = ?)
次に、最初のバインド変数(?
)を使用して、first_name
検索基準をオンまたはオフにできます。 、および?
criteriumをオンまたはオフにする3番目のバインド変数(last_name
)。
また、審美的な目的でリテラル1=1
を追加したため、クエリのテキストがうまく揃います。
これらの2つの基準については、first_name
またはlast_name
のいずれか、または両方を配置してWHERE条件を動的に構築することで同じことを行う方が簡単な場合があるため、あまり役に立たないようです。またはなし。したがって、コードは同じクエリの4つのバージョンを動的に構築する必要があります。考慮すべき10の異なる基準がある場合、何が起こるかを想像してください。その後、同じクエリの組み合わせをいくつ管理する必要がありますか?
0 =?に追加することもできます。すべての条件にインデックスが付けられている場合、バインド変数スイッチはあまりうまく機能しません。適切なインデックスと実行プランを選択するランタイムオプティマイザーは、これらのわずかに複雑な述語でインデックスを使用することのコスト上のメリットをまったく見ないかもしれません。したがって、クエリに明示的に0/1を挿入する(SQLで文字列を連結するか、検索/置換を行う)ことをお勧めします。そうすることで、コンパイラーは冗長なステートメントを最適化する機会を与え、ランタイム実行プログラムに、はるかに単純な照会を提供します。
(0=1 OR cond = ?) --> (cond = ?)
(0=0 OR cond = ?) --> Always True (ignore predicate)
上記の2番目のステートメントでは、コンパイラーは条件の2番目の部分(cond = ?
)を考慮する必要さえないことを認識し、単純に述部全体を削除します。バインド変数である場合、コンパイラはこれを達成できませんでした。
単純かつ強制的に0/1を注入するため、SQLインジェクションの可能性はゼロです。
私のSQLでは、1つのアプローチとして、通常、SQLインジェクションポイントを$ {literal_name}として配置し、コンパイラーに許可する前に、適切なリテラルで正規表現any $ {...}を使用して検索/置換します。刺します。これは基本的に、次のように保存されたクエリにつながります。
WHERE 1=1
AND (0=${cond1_enabled} OR cond1 = ?)
AND (0=${cond2_enabled} OR cond2 = ?)
見栄えがよく、理解しやすく、コンパイラはそれを適切に処理し、ランタイムコストベースオプティマイザーはそれをよりよく理解し、適切なインデックスを選択する可能性が高くなります。
私は注入するものに特別な注意を払います。変数を渡すための主要な方法は、明白なすべての理由のためにバインド変数であり、そのままです。
グレッグから引用
コンパイル時に条件のリストがわからず、代わりに実行時に作成される場合、1つまたは複数の条件があるかどうかを心配する必要はありません。これらはすべて次のように生成できます。
そして
それらをすべて連結します。開始時に1 = 1を使用すると、イニシャルが関連付けられます。
これがどんな種類の注射保護にも使われるのを見たことがありません。実装の便宜として使用されるのを見てきました。 SQLクエリエンジンは1 = 1を無視するため、パフォーマンスへの影響はありません。
アプリケーションでテーブルメタデータのみが必要な場合に役立ちます。たとえば、JDBCアプリケーションを作成していて、テーブル内の列の列表示サイズを取得する場合。
ここにコードスニペットを貼り付ける
String query = "SELECT * from <Table_name> where 1=0";
PreparedStatement stmt = connection.prepareStatement(query);
ResultSet rs = stmt.executeQuery();
ResultSetMetaData rsMD = rs.getMetaData();
int columnCount = rsMD.getColumnCount();
for(int i=0;i<columnCount;i++) {
System.out.println("Column display size is: " + rsMD.getColumnDisplaySize(i+1));
}
ここで「select * from table」のようなクエリを使用すると、テーブルからすべてのレコードを取得しようとするため、巨大なデータを扱う場合にパフォーマンスの問題が発生する可能性があります。代わりに、「select * from table where 1 =」のようなクエリを提供すると、レコードではなくテーブルメタデータのみがフェッチされるため、効率的です。
別のスレッドのユーザーmilso ごと、「WHERE 1 = 0」の別の目的:
CREATE TABLE New_table_name as select * FROM Old_table_name WHERE 1 = 2;
これにより、古いテーブルと同じスキーマを持つ新しいテーブルが作成されます。 (比較のためにいくつかのデータをロードしたい場合に非常に便利です)
ユーザーがレコードのみを追加する場合、最速の方法は既存のレコードを返さずにレコードセットを開くことです。