Warum sollte jemand WHERE 1 = 1 AND <Bedingungen> in einer SQL-Klausel verwenden?

257

Warum sollte jemand WHERE 1=1 AND <conditions>in einer SQL-Klausel verwenden (entweder SQL, das durch verkettete Zeichenfolgen erhalten wird, oder Ansichtsdefinition)

Ich habe irgendwo gesehen, dass dies zum Schutz vor SQL Injection verwendet wird, aber es scheint sehr seltsam.

Wenn es eine Injektion gibt, WHERE 1 = 1 AND injected OR 1=1hätte dies das gleiche Ergebnis wie injected OR 1=1.

Später bearbeiten: Was ist mit der Verwendung in einer Ansichtsdefinition?


Danke für deine Antworten.

Trotzdem verstehe ich nicht, warum jemand diese Konstruktion zum Definieren einer Ansicht oder in einer gespeicherten Prozedur verwenden sollte.

Nehmen Sie zum Beispiel:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 AND table.Field=Value
Bogdan Maxim
quelle
3
"Warum sollte jemand diese Konstruktion verwenden, um eine Ansicht zu definieren?" Wahrscheinlich aus Gewohnheit. Es bietet keinen funktionalen Vorteil bei statischen Abfragen.
ADTC

Antworten:

346

Wenn die Liste der Bedingungen zur Kompilierungszeit nicht bekannt ist und stattdessen zur Laufzeit erstellt wird, müssen Sie sich keine Gedanken darüber machen, ob Sie eine oder mehrere Bedingungen haben. Sie können sie alle wie folgt generieren:

and <condition>

und verketten sie alle zusammen. Mit dem 1=1am Anfang hat die Initiale andetwas zu assoziieren.

Ich habe noch nie gesehen, dass dies für irgendeine Art von Injektionsschutz verwendet wird, wie Sie sagen, es scheint nicht viel zu helfen. Ich habe gesehen, dass es als Implementierungskomfort verwendet wird. Die SQL-Abfrage-Engine ignoriert diese am Ende, 1=1sodass sie keine Auswirkungen auf die Leistung haben sollte.

Greg Hewgill
quelle
34
Manchmal geht es nicht darum, faul zu sein, sondern einen saubereren Code zu haben.
Eduardo Molteni
39
Der Umgang mit nachgestellten ANDs oder COMMAs ist nicht schmutzig ... nichts ist sauberer, wenn 1 = 1 in Ihrem gesamten SQL vorhanden ist.
21
Datenbankadministratoren? Wofür sind sie? :)
Eduardo Molteni
38
Datenbankadministratoren sind dazu da, nach Programmierern aufzuräumen, die glauben, Datenbanken effektiv nutzen zu können.
Adrian Pronk
23
"Faul" Ich mag es zu denken, dass es klug ist, nicht faul. Sie vermeiden sich wiederholenden Code und unnötige Zustandsüberprüfungen. Ohne where 1=1(Oracle) oder where true(Postgres) hinzufügen zu können , muss ich für jede Bedingung prüfen, ob es die erste ist. Es macht keinen Sinn, dies zu tun, und es wird nur mehr Boilerplate-Code hinzugefügt.
ADTC
113

Fügen Sie einfach einen Beispielcode zu Gregs Antwort hinzu:

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
Eduardo Molteni
quelle
6
etwas hackig, scheint aber eine gültige Verwendung zu sein.
Mike
5
Dies sollte die akzeptierte Antwort sein. Die Praxis besteht eigentlich nur darin, nicht zu bestimmen, wie viele Bedingungen Sie haben.
Aglassman
38

Ich habe gesehen, dass es verwendet wird, wenn die Anzahl der Bedingungen variabel sein kann.

Sie können Bedingungen mit einer "UND" -String verknüpfen. Anstatt die Anzahl der Bedingungen zu zählen, die Sie übergeben, setzen Sie am Ende Ihrer SQL-Standardanweisung ein "WHERE 1 = 1" und werfen die verketteten Bedingungen auf.

Grundsätzlich erspart es Ihnen, einen Test für Bedingungen durchzuführen und dann eine "WHERE" -String vor ihnen hinzuzufügen.

Carl
quelle
28

Es scheint ein fauler Weg zu sein, immer zu wissen, dass Ihre WHERE-Klausel bereits definiert ist, und es Ihnen zu ermöglichen, weiterhin Bedingungen hinzuzufügen, ohne prüfen zu müssen, ob es die erste ist.

John Lemp
quelle
12
"Faul" Ich mag es zu denken, dass es klug ist, nicht faul. Sie vermeiden sich wiederholenden Code und unnötige Zustandsüberprüfungen. Ohne where 1=1(Oracle) oder where true(Postgres) hinzufügen zu können , muss ich für jede Bedingung prüfen, ob es die erste ist. Es macht keinen Sinn, dies zu tun, und es wird nur mehr Boilerplate-Code hinzugefügt.
ADTC
2
@ADTC Beim Schreiben von Code geht es oft - wenn nicht meistens - darum, mit unterschiedlichen Bedingungen umzugehen. Dies ist nur eine weitere Bedingung, die behandelt werden muss. Ich persönlich halte es für faul, generiertes SQL damit zu verschmutzen. Wenn Sie Ihren Code so gestalten, dass an EINER Stelle 'Wobei 1 = 1' hinzugefügt wird, können Sie mit geringem Aufwand den Unterschied zwischen null und vielen Bedingungen an dieser EINEN Stelle in Ihrem Code verarbeiten. Meine Vermutung ist jedoch, dass Befürworter von 'Where 1 = 1' es in ihrer gesamten Codebasis verteilen, was mich zu dem Schluss bringt, dass Faulheit Faulheit erzeugt.
Jason S
@ Jason Laziness ist der Vater der Erfindung.
ADTC
@ADTC Ich bin faul, weil ich Code nicht gerne an Hunderten von Stellen aktualisiere, also wird die Erfindung an einer Stelle platziert. Für mich bedeutet dies WHERE 1=1die zusätzliche Arbeit, denselben Code an mehreren Stellen zu verwalten und in all Ihrem generierten SQL zu lesen. Ich bin fauler als du, denke ich!
Jason S
19

Indirekt relevant: wenn 1 = 2 verwendet wird:

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

Dadurch wird eine neue Tabelle mit demselben Schema wie die alte Tabelle erstellt. (Sehr praktisch, wenn Sie einige Daten für Vergleiche laden möchten)

milso
quelle
3
Ich habe vergessen hinzuzufügen, während es eine neue Tabelle mit den gleichen Daten wie die alte erstellt, aber die neue Tabelle hat keine anderen Einschränkungen wie Fremdschlüssel aus der älteren Tabelle
Milso
16

Der Ausdruck 1 = 1 wird üblicherweise im generierten SQL-Code verwendet. Dieser Ausdruck kann das Generieren von SQL-Code vereinfachen und die Anzahl der bedingten Anweisungen reduzieren.

aku
quelle
11

Eigentlich habe ich so etwas in BIRT-Berichten gesehen. Die an die BIRT-Laufzeit übergebene Abfrage hat folgende Form:

select a,b,c from t where a = ?

und das '?' wird zur Laufzeit durch einen tatsächlichen Parameterwert ersetzt, der aus einem Dropdown-Feld ausgewählt wurde. Die Auswahlmöglichkeiten in der Dropdown-Liste sind wie folgt:

select distinct a from t
union all
select '*' from sysibm.sysdummy1

damit Sie alle möglichen Werte plus " *" erhalten. Wenn der Benutzer " *" aus dem Dropdown-Feld auswählt (dh alle Werte von a sollten ausgewählt werden), muss die Abfrage (von Javascript) geändert werden, bevor sie ausgeführt wird.

Seit der "?" ist ein Positionsparameter und MUSS dort bleiben, damit andere Dinge funktionieren. Das Javascript ändert die Abfrage wie folgt:

select a,b,c from t where ((a = ?) or (1==1))

Dadurch wird der Effekt der where-Klausel im Wesentlichen beseitigt, während der Positionsparameter weiterhin beibehalten wird.

Ich habe auch den AND-Fall gesehen, der von faulen Codierern beim dynamischen Erstellen einer SQL-Abfrage verwendet wird.

Angenommen, Sie müssen dynamisch eine Abfrage erstellen, die mit Folgendes beginnt select * from tund Folgendes überprüft:

  • der Name ist Bob; und
  • Das Gehalt beträgt> 20.000 US-Dollar

Einige Leute würden das erste mit einem WO und die nachfolgenden mit einem UND hinzufügen, also:

select * from t where name = 'Bob' and salary > 20000

Faule Programmierer (und das ist nicht unbedingt eine schlechte Eigenschaft) würden nicht zwischen den hinzugefügten Bedingungen unterscheiden, sie würden damit beginnen select * from t where 1=1und danach einfach AND-Klauseln hinzufügen.

select * from t where 1=1 and name = 'Bob' and salary > 20000
paxdiablo
quelle
1
"Faul" Ich mag es zu denken, dass es klug ist, nicht faul. Sie vermeiden sich wiederholenden Code und unnötige Zustandsüberprüfungen. Ohne where 1=1(Oracle) oder where true(Postgres) hinzufügen zu können , muss ich für jede Bedingung prüfen, ob es die erste ist. Es macht keinen Sinn, dies zu tun, und es wird nur mehr Boilerplate-Code hinzugefügt.
ADTC
1
@ADTC, ich meinte nicht schlecht faul. In der Tat ist Faulheit eine gute Eigenschaft in der Programmierung :-) Ich werde klarstellen.
Paxdiablo
Faulheit ist die Wurzel allen Übels
Ivanzinho
11

Ich fand dieses Muster nützlich, wenn ich Dinge in der Datenbank teste oder doppelt überprüfe, damit ich andere Bedingungen sehr schnell kommentieren kann:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 
AND Table.Field=Value
AND Table.IsValid=true

verwandelt sich in:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 
--AND Table.Field=Value
--AND Table.IsValid=true
Carlos Toledo
quelle
10

Dabei ist 1 = 0, um zu überprüfen, ob die Tabelle vorhanden ist. Ich weiß nicht, warum 1 = 1 verwendet wird.


quelle
1
Dies wurde verwendet, um eine leere Ergebnismenge aus der Datenbank zurückzugeben, die als Halter für neue Datensätze verwendet werden soll.
Gary Kindel
6

Während ich sehe, dass 1 = 1 für generiertes SQL nützlich wäre, besteht eine Technik, die ich in PHP verwende, darin, ein Array von Klauseln zu erstellen und dies dann zu tun

implode (" AND ", $clauses);

Dadurch wird das Problem eines führenden oder nachfolgenden UND vermieden. Dies ist natürlich nur dann nützlich, wenn Sie wissen, dass Sie mindestens eine Klausel haben werden!

Sanbikinoraion
quelle
1
Hier kommt die 1 = 1 ins Spiel. Sie gibt Ihnen diese "mindestens eine Klausel", sodass Sie sich keine Sorgen machen müssen, nur auf ein "AND abc" zu klatschen
Carl
Ich mag diese Idee! Siehe hier für ein vollständigeres Beispiel stackoverflow.com/questions/35326160/…
drooh
5

Hier ist ein eng verwandtes Beispiel: Verwenden einer SQL- MERGEAnweisung zum Aktualisieren des vorgelegten Ziels unter Verwendung aller Werte aus der Quelltabelle, für die es kein gemeinsames Attribut gibt, an dem Sie teilnehmen können, z

MERGE INTO Circles
   USING 
      (
        SELECT pi
         FROM Constants
      ) AS SourceTable
   ON 1 = 1
WHEN MATCHED THEN 
  UPDATE
     SET circumference = 2 * SourceTable.pi * radius;
eines Tages, wenn
quelle
5

Warum sollte jemand WHERE 1 = 1 AND verwenden? <proper conditions>

Ich habe gesehen homespun Frameworks Dinge zu tun wie diese ( Röte ), da diese faulen Parsing Praktiken ermöglicht die auf beide angewendet werden WHEREund ANDSQL - Schlüsselwörter.

Betrachten Sie beispielsweise (ich verwende hier C # als Beispiel) das bedingte Parsen der folgenden Prädikate in einer SQL-Abfrage string builder:

var sqlQuery = "SELECT * FROM FOOS WHERE 1 = 1"
if (shouldFilterForBars)
{
    sqlQuery = sqlQuery + " AND Bars > 3";
}
if (shouldFilterForBaz)
{
    sqlQuery = sqlQuery + " AND Baz < 12";
}

Der "Vorteil" von WHERE 1 = 1bedeutet, dass kein spezieller Code benötigt wird:

  • Für UND - ob Null, ein oder beide Prädikate (Balken und Baz) angewendet werden sollen, die bestimmen würden, ob das erste ANDerforderlich ist. Da wir bereits mindestens ein Prädikat mit dem haben 1 = 1, bedeutet dies, dass ANDes immer in Ordnung ist.
  • Für überhaupt keine Prädikate - Wenn es NULL Prädikate gibt, WHEREmuss das gelöscht werden. Aber auch hier können wir faul sein, weil wir wieder mindestens ein Prädikat garantieren.

Dies ist offensichtlich eine schlechte Idee und würde empfehlen, ein etabliertes Datenzugriffsframework oder ORM zu verwenden, um optionale und bedingte Prädikate auf diese Weise zu analysieren.

StuartLC
quelle
Wenn Sie Ihre eigenen rollen, sollte sich der Builder für die where-Klausel an einer Stelle in Ihrem Code befinden. Dann können Sie null Prädikate oder mehr als null Prädikate an einer einzelnen Stelle in Ihrem Code verarbeiten. Mein Verdacht ist, dass die Existenz von WHERE 1=1ein fairer Indikator dafür ist, dass dies NICHT der Fall ist, dass die Codebasis mit Zeichenfolgen übersät ist WHERE 1=1, was auf ein Problem mit der Anwendungsarchitektur hinweisen würde, und ich würde nicht das einzige vermuten!
Jason S
1
Eigentlich ist nichts "Schlechtes" an der Idee, geschweige denn ein "offensichtlicher" Fehler. Ein ORM ist auch nicht in allen Fällen der richtige Weg. Lernen Sie SQL und relationale Algebra Menschen ...
Hejazzman
4

Wenn Sie hierher gekommen sind, suchen WHERE 1Sie danach WHERE 1und WHERE 1=1sind identisch. WHERE 1wird selten verwendet, da einige Datenbanksysteme dies ablehnen, da sie WHERE 1nicht wirklich boolesch sind.

Yogesh Umesh Vaity
quelle
2

Dies ist nützlich, wenn Sie eine dynamische Abfrage verwenden müssen, in der Sie in der where-Klausel einige Filteroptionen anhängen müssen. Zum Beispiel, wenn Sie die Optionen 0 für Status inaktiv und 1 für aktiv einschließen. Basierend auf den Optionen stehen nur zwei Optionen zur Verfügung (0 und 1). Wenn Sie jedoch Alle Datensätze anzeigen möchten, ist es praktisch, in den Bereich 1 = 1 aufzunehmen. Siehe Beispiel unten:

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);
Eliseo Jr.
quelle
2

Nachdem ich alle Antworten überprüft hatte, beschloss ich, ein Experiment wie durchzuführen

SELECT
*
FROM MyTable

WHERE 1=1

Dann habe ich mit anderen Nummern nachgesehen

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

ect Nachdem alle Überprüfungen durchgeführt wurden, ist die Abfragestadt dieselbe. auch ohne die where-Klausel. Ich bin kein Fan der Syntax

JonWay
quelle
1

Ich mache dies normalerweise, wenn ich dynamisches SQL für einen Bericht erstelle, der viele Dropdown-Werte enthält, die ein Benutzer auswählen kann. Da der Benutzer die Werte aus jedem Dropdown-Menü auswählen kann oder nicht, fällt es uns schwer, herauszufinden, welche Bedingung die erste where-Klausel war. Also füllen wir die Abfrage where 1=1am Ende mit einem auf und fügen danach alle where-Klauseln hinzu.

Etwas wie

select column1, column2 from my table where 1=1 {name} {age};

Dann würden wir die where-Klausel wie folgt erstellen und sie als Parameterwert übergeben

string name_whereClause= ddlName.SelectedIndex > 0 ? "AND name ='"+ ddlName.SelectedValue+ "'" : "";

Da uns die Auswahl der where-Klausel zur Laufzeit unbekannt ist, hilft uns dies sehr bei der Suche, ob wir eine aufnehmen sollen 'AND' or 'WHERE'.

Zo hat
quelle
0

Die Verwendung eines Prädikats wie 1=1ist ein normaler Hinweis, der manchmal verwendet wird, um den Zugriffsplan zu zwingen, einen Index-Scan zu verwenden oder nicht. Der Grund, warum dies verwendet wird, liegt darin, dass Sie eine mehrfach verschachtelte verknüpfte Abfrage mit vielen Prädikaten in der where-Klausel verwenden, bei der manchmal sogar die Verwendung aller Indizes dazu führt, dass der Zugriffsplan jede Tabelle liest - ein vollständiger Tabellenscan. Dies ist nur einer von vielen Hinweisen, die von Datenbankadministratoren verwendet werden, um einen Datenbankbetreiber dazu zu verleiten, einen effizienteren Pfad zu verwenden. Wirf einfach keinen rein. Sie benötigen eine Datenbank, um die Abfrage zu analysieren, da sie nicht immer funktioniert.

Big Al
quelle
4
Haben Sie Zitate, die dieses Verhalten für einige Datenbanken dokumentieren?
Joe
0

Hier ist ein Anwendungsfall ... Ich bin jedoch nicht allzu besorgt darüber, warum ich 1 = 1 verwenden sollte oder nicht. Ich schreibe eine Funktion und verwende pyodbc, um einige Daten von SQL Server abzurufen. Ich suchte nach einer Möglichkeit, einen Füllstoff nach dem whereSchlüsselwort in meinem Code zu erzwingen . Dies war in der Tat ein großartiger Vorschlag:

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

Der Grund dafür ist, dass ich das Schlüsselwort 'where' nicht zusammen in der Klauselvariablen _where implementieren konnte. Ich denke also, dass die Verwendung einer Dummy-Bedingung, die als wahr ausgewertet wird, als Füllstoff dienen würde.

SMS
quelle
-1

Ich bin zum ersten Mal mit ADO und klassischem Asp auf dieses Problem gestoßen. Die Antwort war: Leistung. wenn du eine Straße machst

Select * from tablename

und geben Sie das als SQL-Befehl / Text ein. Sie erhalten eine spürbare Leistungssteigerung mit dem

Where 1=1

hinzugefügt, es war ein sichtbarer Unterschied. Etwas, das damit zu tun hat, dass Tabellenüberschriften zurückgegeben werden, sobald die erste Bedingung erfüllt ist, oder mit einer anderen Verrücktheit, die die Dinge beschleunigt hat.

Jackberry
quelle
3
Wenn das stimmt, warum fügt das DBMS das nicht immer hinzu?
Carcamano
5
Können Sie Beweise vorlegen?
Peter G.