なぜ誰かがSQL句でWHERE 1=1 AND <conditions>
を使用するのか(連結された文字列、またはビュー定義から取得されたいずれかのSQL)
SQLインジェクションから保護するためにこれが使用されることをどこかで見ましたが、非常に奇妙に見えます。
注入がある場合、WHERE 1 = 1 AND injected 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
に関連付けるものがあります。
あなたがそれが多くの助けになるとは思われないと言うので、私はこれがどんな種類の注射保護にも使われるのを見たことがありません。 I have実装の便宜として使用されているのを見た。 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
条件の数が可変の場合に使用されるのを見てきました。
「AND」文字列を使用して条件を連結できます。次に、渡す条件の数をカウントする代わりに、ストックSQLステートメントの最後に「WHERE 1 = 1」を配置し、連結された条件にスローします。
基本的に、条件のテストを行ってから、「WHERE」文字列を条件の前に追加する必要がなくなります。
WHERE句が既に定義されていることを常に把握し、最初の条件であるかどうかを確認せずに条件を追加し続けることができる怠laな方法のようです。
間接的関連:1 = 2が使用される場合:
CREATE TABLE New_table_name
as
select *
FROM Old_table_name
WHERE 1 = 2;
これにより、古いテーブルと同じスキーマを持つ新しいテーブルが作成されます。 (比較のためにいくつかのデータをロードしたい場合に非常に便利です)
1 = 1式は、生成されたSQLコードで一般的に使用されます。この式により、SQL生成コードが単純化され、条件ステートメントの数が削減されます。
ここで、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
すべての可能な値に加えて「*
」を取得します。ユーザーがドロップダウンボックスから「*
」を選択した場合(aのすべての値を選択する必要があることを意味します)、クエリを実行する前に(Javascriptによって)変更する必要があります。
「?」は位置パラメータであり、他の機能が動作するためにそこに残らなければなりません。Javascriptはクエリを次のように変更します。
select a,b,c from t where ((a = ?) or (1==1))
基本的には、位置パラメータをそのまま残したままwhere句の効果を削除します。
また、SQLクエリを動的に作成する際に、遅延コーダーが使用するANDケースも確認しました。
select * from t
で始まり、チェックするクエリを動的に作成する必要があるとします。
一部の人々は、最初にWHEREを追加し、その後にANDを追加します:
select * from t where name = 'Bob' and salary > 20000
怠zyなプログラマー(そして、それは必ずしもbad特性ではない)は、追加された条件を区別せず、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つの節があることを知っている場合にのみ役立ちます!
密接に関連する例は次のとおりです。SQLMERGE
ステートメントを使用して、ソーステーブルからのすべての値を使用してターゲットテーブルを更新します。
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
<proper conditions>
を使用する理由
seen homespunフレームワークはこのようなことを行います(blush)。これにより、遅延解析構文をWHERE
name__と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
name__が必要かどうかを決定します。 1 = 1
には少なくとも1つの述語がすでにあるため、AND
name__は常にOKです。WHERE
name__を削除する必要があります。しかし、ここでも、少なくとも1つの述語が保証されるため、怠zyになる可能性があります。これは明らかに悪い考えであり、確立されたデータアクセスフレームワークまたは ORM を使用して、この方法でオプションおよび条件付き述語を解析することをお勧めします。
WHERE 1
を探してここに来た場合は、WHERE 1
とWHERE 1=1
が同じであることに注意してください。 WHERE 1
は、WHERE 1
が実際にはブール値ではないと見なして拒否するデータベースシステムがあるため、めったに使用されません。
すべての答えを確認してから、次のような実験を行うことにしました
SELECT
*
FROM MyTable
WHERE 1=1
次に、他の番号で確認しました
WHERE 2=2
WHERE 10=10
WHERE 99=99
ectすべてのチェックを行った後、クエリ実行タウンは同じです。 where句がなくても。私は構文のファンではありません
これは、where句にフィルターオプションを追加する必要がある動的クエリを使用する必要がある場合に役立ちます。ステータスが非アクティブの場合はオプション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);
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' or 'WHERE'.
を含めるかどうかを見つけるのに非常に役立ちます