誰かがWHERE 1 = 1 AND< conditions>を使用する理由SQL句で?
-
04-07-2019 - |
質問
SQL句で WHERE 1 = 1 AND< conditions>
を使用する理由(連結された文字列から取得したSQL、またはビュー定義)
SQLインジェクションから保護するためにこれが使用されることをどこかで見ましたが、非常に奇妙に見えます。
注入がある場合 WHERE 1 = 1 AND注入OR 1 = 1
は、 injected OR 1 = 1
と同じ結果になります。
後の編集:ビュー定義での使用はどうですか?
ご回答ありがとうございます。
それでも、 なぜ誰かがこの構造を使用してビューを定義したり、ストアドプロシージャ内で使用したりするのか理解できません。
例を挙げましょう:
CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 AND table.Field=Value
解決
条件のリストがコンパイル時に不明であり、代わりに実行時に作成される場合、1つまたは複数の条件があるかどうかを心配する必要はありません。以下のようにすべて生成できます:
and <condition>
それらをすべて連結します。開始時に 1 = 1
を使用すると、最初の and
に関連付けるものがあります。
これがどんな種類の注射保護にも使われるのを見たことはありません。実装の便宜として使用されていることを 見ました。 SQLクエリエンジンは、 1 = 1
を無視するため、パフォーマンスへの影響はありません。
他のヒント
サンプルコードをGregの答えに追加するだけです:
dim sqlstmt as new StringBuilder
sqlstmt.add("SELECT * FROM Products")
sqlstmt.add(" WHERE 1=1")
''// From now on you don't have to worry if you must
''// append AND or WHERE because you know the WHERE is there
If ProductCategoryID <> 0 then
sqlstmt.AppendFormat(" AND ProductCategoryID = {0}", trim(ProductCategoryID))
end if
If MinimunPrice > 0 then
sqlstmt.AppendFormat(" AND Price >= {0}", trim(MinimunPrice))
end if
条件の数が可変である場合に使用されるのを見ました。
&quot;を使用して条件を連結できます。 AND&quot;文字列。次に、渡す条件の数をカウントする代わりに、「WHERE 1 = 1」を配置します。ストックSQLステートメントの最後に、連結された条件をスローします。
基本的に、条件のテストを行ってから「WHERE」を追加する必要がなくなります。それらの前の文字列。
WHERE句が既に定義されていることを常に把握し、最初の条件であるかどうかを確認せずに条件を追加し続けることができる怠laな方法のようです。
間接的に関連:1 = 2が使用される場合:
CREATE TABLE New_table_name
as
select *
FROM Old_table_name
WHERE 1 = 2;
これにより、古いテーブルと同じスキーマを持つ新しいテーブルが作成されます。 (比較のためにいくつかのデータをロードしたい場合に非常に便利です)
1 = 1式は、生成されたSQLコードで一般的に使用されます。この式により、SQL生成コードを簡素化して条件文の数を減らすことができます。
where 1 = 0、これはテーブルが存在するかどうかを確認するために行われます。 1 = 1が使用される理由がわからない。
実際、BIRTレポートでこの種のことを使用しているのを見てきました。 BIRTランタイムに渡されるクエリの形式は次のとおりです。
select a,b,c from t where a = ?
および '?'実行時に、ドロップダウンボックスから選択された実際のパラメーター値に置き換えられます。ドロップダウンの選択肢は次のとおりです。
select distinct a from t
union all
select '*' from sysibm.sysdummy1
すべての可能な値に加えて&quot; *
&quot;を取得します。ユーザーが&quot; *
&quot;を選択した場合ドロップダウンボックスから(aのすべての値を選択する必要があることを意味します)、クエリを実行する前に(Javascriptによって)変更する必要があります。
&quot;?&quot;は位置パラメータであり、他の機能が動作するためにそこに残らなければなりません。Javascriptはクエリを次のように変更します。
select a,b,c from t where ((a = ?) or (1==1))
基本的には、位置パラメータをそのままにして、where句の効果を削除します。
また、SQLクエリを動的に作成する際にレイジーコーダーが使用するANDケースも確認しました。
select * from t
で始まり、チェックするクエリを動的に作成する必要があるとします:
- 名前はボブです。そして
- 給与は&gt; 20,000ドル
一部の人々は、最初にWHEREを追加し、その後にANDを追加します:
select * from t where name = 'Bob' and salary > 20000
レイジープログラマー(およびそれは必ずしも悪い特性ではない)は、追加された条件を区別せず、 select * from t where 1 = 1
で始まります。その後にAND句を追加します。
select * from t where 1=1 and name = 'Bob' and salary > 20000
データベースのテストやダブルチェックを行うときにこのパターンが役立つことがわかったので、他の条件をすばやくコメントできます。
CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1
AND Table.Field=Value
AND Table.IsValid=true
次のようになります:
CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1
--AND Table.Field=Value
--AND Table.IsValid=true
生成されたSQLには1 = 1が有用であることがわかりますが、PHPで使用する手法は、句の配列を作成してから実行することです
implode (" AND ", $clauses);
これにより、先行または後続のANDの問題を回避できます。明らかに、これは、少なくとも1つの句があることを知っている場合にのみ役立ちます!
これは密接に関連する例です。SQL MERGE
ステートメントを使用して、ソーステーブルのすべての値を使用してターゲットテーブルを更新します。
MERGE INTO Circles
USING
(
SELECT pi
FROM Constants
) AS SourceTable
ON 1 = 1
WHEN MATCHED THEN
UPDATE
SET circumference = 2 * SourceTable.pi * radius;
WHERE 1 = 1 AND
を使用する理由&lt; proper conditions&gt;
見たホームスパンフレームワークは、このようなことを行います(赤面)、このように遅延解析手法を WHERE
および AND
Sqlキーワードの両方に適用できます。
たとえば(ここでは例としてC#を使用しています)、SQLクエリ string builder
の次の述語の条件付き解析を検討してください。
var sqlQuery = "SELECT * FROM FOOS WHERE 1 = 1"
if (shouldFilterForBars)
{
sqlQuery = sqlQuery + " AND Bars > 3";
}
if (shouldFilterForBaz)
{
sqlQuery = sqlQuery + " AND Baz < 12";
}
「メリット」 WHERE 1 = 1
は、特別なコードが不要であることを意味します:
- AND の場合-最初の
AND
が必要かどうかを決定する、0、1つ、または両方の述語(バーとバズ)を適用するかどうか。1 = 1
の述語がすでに少なくとも1つあるため、AND
は常に問題ありません。 - 述語がない場合-ゼロの述語がある場合は、
WHERE
を削除する必要があります。しかし、ここでも、少なくとも1つの述語が保証されるため、怠laになる可能性があります。
これは明らかに悪い考えであり、確立されたデータアクセスフレームワークまたはオプションおよび条件付き述語の解析に ORM を使用することをお勧めします。このように。
WHERE 1
を探してここに来た場合、 WHERE 1
と WHERE 1 = 1
は同一であることに注意してください。一部のデータベースシステムでは、 WHERE 1
が実際にはブール値ではないと見なして拒否するため、 WHERE 1
はめったに使用されません。
これは、動的クエリを使用する必要がある場合に役立ちます。 句には、いくつかのフィルタオプションを追加する必要があります。ステータスが非アクティブの場合はオプション0、アクティブの場合は1を含めると同様です。オプションに基づいて、2つの使用可能なオプション(0と1)のみがありますが、すべてのレコードを表示する場合は、close 1 = 1の場所に含めると便利です。 以下のサンプルを参照してください:
Declare @SearchValue varchar(8)
Declare @SQLQuery varchar(max) = '
Select [FirstName]
,[LastName]
,[MiddleName]
,[BirthDate]
,Case
when [Status] = 0 then ''Inactive''
when [Status] = 1 then ''Active''
end as [Status]'
Declare @SearchOption nvarchar(100)
If (@SearchValue = 'Active')
Begin
Set @SearchOption = ' Where a.[Status] = 1'
End
If (@SearchValue = 'Inactive')
Begin
Set @SearchOption = ' Where a.[Status] = 0'
End
If (@SearchValue = 'All')
Begin
Set @SearchOption = ' Where 1=1'
End
Set @SQLQuery = @SQLQuery + @SearchOption
Exec(@SQLQuery);
すべての回答を確認して、次のような実験を行うことにしました
SELECT
*
FROM MyTable
WHERE 1=1
その後、他の番号で確認しました
WHERE 2=2
WHERE 10=10
WHERE 99=99
ect すべてのチェックを行った後、クエリ実行タウンは同じです。 where句がなくても。私は構文のファンではありません
1 = 1
などの述語を使用することは、アクセスプランでインデックススキャンを使用するかどうかを強制するために使用されることがある通常のヒントです。これが使用される理由は、where句に多くの述語を含む複数のネストされた結合クエリを使用している場合です。これは、DBMSがDBMSをだましてより効率的なパスを使用するために使用する多くのヒントの1つにすぎません。ただ投げ込まないでください。クエリが常に機能するとは限らないため、クエリを分析するにはdbaが必要です。
通常、ユーザーが選択できる多くのドロップダウン値を持つレポート用の動的SQLを作成するときにこれを行います。ユーザーは各ドロップダウンから値を選択する場合としない場合があるため、どの条件が最初のwhere句であるかを判断するのに苦労します。そのため、クエリの最後に where 1 = 1
を埋め込み、その後にすべてのwhere句を追加します。
次のようなもの
select column1, column2 from my table where 1=1 {name} {age};
次に、このようなwhere句を作成し、パラメーター値として渡します
string name_whereClause= ddlName.SelectedIndex > 0 ? "AND name ='"+ ddlName.SelectedValue+ "'" : "";
実行時にwhere句の選択が不明なので、これは 'AND'または 'WHERE'を含めるかどうかを見つけるのに非常に役立ちます。
私は最初にADOとクラシックASPでこの問題に出くわしました。答えはパフォーマンスでした。 まっすぐにやる場合
テーブル名から*を選択
そしてそれをSQLコマンド/テキストとして渡すと、顕著なパフォーマンスの向上が得られます
Where 1 = 1
追加すると、目に見える違いがありました。最初の条件が満たされるとすぐにテーブルヘッダーが返されるか、他のいくつかの狂気と関係がありますが、とにかく速度が上がりました。