なぜSQL句でWHERE 1 = 1 AND <条件>を使用するのですか?


257

誰かWHERE 1=1 AND <conditions>がSQL句で使用する理由(連結された文字列から取得した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

3
「なぜ誰かがこの構造を使用してビューを定義するのでしょうか」おそらく癖がありません。静的クエリでは機能上の利点はありません。
ADTC、2014

回答:


346

条件のリストがコンパイル時に不明であり、代わりに実行時に作成される場合、条件が1つあるのか複数あるのかを気にする必要はありません。あなたはそれらをすべて次のように生成できます:

and <condition>

それらをすべて連結します。で1=1開始時に、初期には、and関連付けるために何かを持っています。

あなたがそれがあまり役に立たないように思われるので、私はこれがどんな種類の注射保護にも使われるのを見たことがありません。私それが実装の便宜として使用されるの見てきました。SQLクエリエンジンは最終的にを無視する1=1ため、パフォーマンスへの影響はありません。


34
時々怠惰ではなく、よりクリーンなコードを持つことです。
Eduardo Molteni、2008年

39
末尾のANDやCOMMAを処理することは汚いことではありません... SQL全体で1 = 1を使用しても、何も問題はありません。

21
DBA?それらは何のため?:)
エドゥアルドモルテニ2008年

38
DBAは、データベースを効果的に使用する方法を知っていると考えているプログラマーの後にクリーンアップするために存在します。
Adrian Pronk、

23
「怠惰」怠惰ではなく、スマートだと思いたい。反復的なコードと不要な条件チェックを回避しています。where 1=1(Oracle)またはwhere true(Postgres)を追加できない場合は、各条件が最初の条件かどうかを確認する必要があります。そのようにする意味はなく、定型コードを追加するだけです。
ADTC、2014

113

グレッグの答えにサンプルコードを追加するだけです:

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

6
少しハッキーですが、有効な使用法のようです。
マイク、

5
これは受け入れられる答えになるはずです。練習は本当にあなたが持っている条件文の数を決定する必要がないようにハックするだけです。
aglassman 2013

38

条件の数が可変になる可能性がある場合に使用されることを確認しました。

「AND」文字列を使用して条件を連結できます。次に、渡す条件の数を数える代わりに、ストックSQLステートメントの最後に「WHERE 1 = 1」を配置して、連結された条件をスローします。

基本的に、条件のテストを行い、その前に「WHERE」文字列を追加する必要がなくなります。


28

あなたのWHERE句がすでに定義されていることを常に知っている怠惰な方法のようであり、それが最初のものかどうかを確認する必要なしに条件を追加し続けることを可能にします。


12
「怠惰」怠惰ではなく、スマートだと思いたい。反復的なコードと不要な条件チェックを回避しています。where 1=1(Oracle)またはwhere true(Postgres)を追加できない場合は、各条件が最初の条件かどうかを確認する必要があります。そのようにする意味はなく、定型コードを追加するだけです。
ADTC、2014

2
@ADTCコードの記述は、多くの場合ではないにせよ、さまざまな条件の処理について行われることがよくあります。これは、処理する必要があるもう1つの条件であり、生成されたSQLを汚染するのは面倒だと個人的に考えています。'Where 1 = 1'を1か所に追加するようにコードを設計すると、少しの労力で、コード内の1か所のゼロと多くの条件の違いを処理できます。しかし、私の推測では、「Where 1 = 1」を支持する人々がコードベース全体に散らばっているため、怠惰が怠惰を生むという結論に至ります。
Jason S

@JasonS怠惰は発明の父です。
ADTC

@ADTC私は何百もの場所でコードを更新したくないので怠惰です。私にとってWHERE 1=1は、同じコードを複数の場所で維持し、生成されたすべてのSQLでそれを読み取るという余分な作業が発生します。私はあなたが思うよりも怠惰です!
Jason S

19

間接的に関連:1 = 2が使用される場合:

CREATE TABLE New_table_name 
as 
select * 
FROM Old_table_name 
WHERE 1 = 2;

これにより、古いテーブルと同じスキーマで新しいテーブルが作成されます。(比較のためにデータをロードしたい場合に非常に便利です)


3
追加するのを忘れた場合、古いテーブルと同じデータで新しいテーブルが作成されますが、新しいテーブルには、古いテーブルの外部キーのような他の制約はありません
milso

16

1 = 1式は、生成されたSQLコードで一般的に使用されます。この式は、sql生成コードを簡略化して、条件ステートメントの数を減らします。


11

実際、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、チェックするクエリを動的に作成する必要があるとします。

  • 名前はボブです。そして
  • 給与は$ 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

1
「怠惰」怠惰ではなく、スマートだと思いたい。反復的なコードと不要な条件チェックを回避しています。where 1=1(Oracle)またはwhere true(Postgres)を追加できない場合は、各条件が最初の条件かどうかを確認する必要があります。そのようにする意味はなく、定型コードを追加するだけです。
ADTC 2014

1
@ADTC、私は悪い意味で怠惰という意味ではありませんでした。実際、レイジーはプログラミングにおいて優れた特性です:-)明確にします。
paxdiablo 2014

怠惰はすべての悪の根源です
Ivanzinho

11

データベースでテストまたはダブルチェックをしているときに、このパターンが有用であることがわかりました。そのため、他の条件を非常にすばやくコメントできます。

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

10

ここで1 = 0、これはテーブルが存在するかどうかを確認するために行われます。1 = 1が使用されている理由がわかりません。


1
これは、データベースから空の結果セットを返し、新しいレコードのホルダーとして使用するために使用されていました。
ゲイリーキンデル2011年

6

1 = 1は生成されたSQLに役立つことがわかりますが、PHPで使用する手法は、節の配列を作成してから

implode (" AND ", $clauses);

したがって、先頭または末尾のANDの問題を回避できます。明らかにこれは、少なくとも1つの句を使用することがわかっている場合にのみ役立ちます。


1
これは、「少なくとも1つの句は、」あなたは「とABC」にちょうど叩きを心配する必要はありませんので、あなたを与える1 = 1がでてくるのこと。
カール・

私はこのアイデアが好きです!より完全な例についてはこちらをご覧くださいstackoverflow.com/questions/35326160/...
drooh

5

密接に関連する例を次に示します。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;

5

なぜ誰かがWHERE 1 = 1 ANDを使用するのか <proper conditions>

ホームスパンフレームワークがこのようなことをするのを見たことがあります(blush)。これにより、遅延解析手法をWHEREANDSqlキーワードの両方に適用できるようになります。

たとえば(ここでは例として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が必要です。には少なくとも1つの述語が既にあるので1 = 1AND常にOK であることを意味します。
  • 述語がまったくない場合-述語がゼロの場合、をWHERE削除する必要があります。しかし、繰り返しになりますが、少なくとも1つの述語が再び保証されるため、怠惰になる可能性があります。

これは明らかに悪い考えであり、この方法でオプションの条件付き述語を解析するために、確立されたデータアクセスフレームワークまたはORMを使用することをお勧めします。


または、独自にロールする場合は、where句ビルダーをコード内の1つの場所に配置する必要があります。その後、コード内の1つの場所でゼロ述語またはゼロを超える述語を処理できます。私の疑いは、の存在がそうでWHERE 1=1はない公正な指標であり、コードベースに文字列のビットが散らばっているWHERE 1=1ということです。
Jason S

1
実際、このアイデアには「悪い」ものは何もありません。「明白な」欠点ははるかに少ないものです。ORMがすべての場合に適切な方法でもありません。SQLとリレーショナル代数の人々を学ぶ...
Hejazzman '10 / 10/18

4

ここでを検索した場合はWHERE 1WHERE 1WHERE 1=1が同じであることを確認してください。WHERE 1一部のデータベースシステムWHERE 1は実際にはブール値ではないと見なして拒否するため、めったに使用されません。


2

これは、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);

2

すべての回答を確認した後、次のような実験を行うことにしました

SELECT
*
FROM MyTable

WHERE 1=1

次に、他の番号で確認しました

WHERE 2=2
WHERE 10=10
WHERE 99=99

ectすべてのチェックを行った後、クエリ実行タウンは同じです。where句がなくても。私は構文のファンではありません


1

これは通常、ユーザーが選択できる多くのドロップダウン値を持つレポートの動的SQLを構築しているときに行います。ユーザーが各ドロップダウンから値を選択する場合としない場合があるため、最初のwhere句がどの条件であったかを判断するのに苦労します。したがって、クエリをwhere 1=1最後にa で埋め、その後にすべての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'.


0

like述語を1=1使用することは、アクセスプランがインデックススキャンを使用するかどうかを強制するために時々使用される通常のヒントです。これが使用される理由は、where句に多数の述語を持つ複数のネストされた結合クエリを使用しているときに、すべてのインデックスを使用してもアクセスプランが各テーブルを読み取る場合があるためです(全テーブルスキャン)。これは、DBAがより効率的なパスを使用するようにdbmsをだますために使用する多くのヒントの1つにすぎません。投入しないでください。クエリは常に機能するとは限らないため、クエリを分析するにはdbaが必要です。


4
一部のデータベースでこの動作を文書化した引用はありますか?
Joe

0

ここにユースケースがあります...しかし、1 = 1を使用する必要があるかどうかの専門性にはあまり関心がありません。pyodbcを使用してSQL Serverからデータを取得する関数を作成しています。whereコードのキーワードの後にフィラーを強制する方法を探していました。これは確かに素晴らしい提案でした:

if _where == '': _where = '1=1'
...
...
...
cur.execute(f'select {predicate} from {table_name} where {_where}')

その理由は、_where句変数内にキーワード「where」を一緒に実装できなかったためです。したがって、trueと評価されるダミー条件を使用すると、フィラーとして機能すると思います。


-1

私は最初にこれにADOとクラシックASPを見つけました。答えは「パフォーマンス」でした。 あなたがストレートを行う場合

Select * from tablename

そしてそれをsqlコマンド/テキストとして渡すと、あなたは顕著なパフォーマンスの向上を得るでしょう

Where 1=1

さらに、それは目に見える違いでした。最初の条件が満たされるとすぐに返されるテーブルヘッダー、または他のいくつかの狂気と関係がありますが、とにかく高速になりました。


3
それが本当なら、DBMSはなぜそれを常に追加しないのですか?
カルカマノ

5
証拠を提示できますか?
Peter G.
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.