Perché qualcuno dovrebbe usare WHERE 1 = 1 AND <conditions> in una clausola SQL?


258

Perché qualcuno dovrebbe usare WHERE 1=1 AND <conditions>in una clausola SQL (O SQL ottenuto tramite stringhe concatenate, o visualizzare la definizione)

Ho visto da qualche parte che questo sarebbe usato per proteggere da SQL Injection, ma sembra molto strano.

Se c'è l'iniezione WHERE 1 = 1 AND injected OR 1=1avrebbe lo stesso risultato di injected OR 1=1.

Modifica successiva: che dire dell'utilizzo in una definizione di vista?


Grazie per le tue risposte.

Tuttavia, non capisco perché qualcuno dovrebbe usare questa costruzione per definire una vista o usarla all'interno di una procedura memorizzata.

Prendi questo per esempio:

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

3
"perché qualcuno dovrebbe usare questa costruzione per definire una vista" Probabilmente per abitudine. Non offre alcun vantaggio funzionale nelle query statiche.
ADTC

Risposte:


346

Se l'elenco di condizioni non è noto al momento della compilazione ed è invece creato in fase di esecuzione, non devi preoccuparti se hai una o più condizioni. Puoi generarli tutti come:

and <condition>

e concatenarli tutti insieme. Con l' 1=1all'inizio, l'iniziale andha qualcosa da associare.

Non l'ho mai visto usato per nessun tipo di protezione dalle iniezioni, come dici tu non sembra che sarebbe di grande aiuto. Io ho visto usato come convenienza attuazione. Il motore di query SQL finirà per ignorare, 1=1quindi non dovrebbe avere alcun impatto sulle prestazioni.


34
A volte non si tratta di essere pigri, ma di avere un codice più pulito.
Eduardo Molteni,

39
trattare con AND o COMMA finali non è sporco ... niente è più pulito avendo 1 = 1 in tutto il tuo SQL.

21
DBA? A cosa servono? :)
Eduardo Molteni,

38
I DBA sono lì per ripulire dopo i programmatori che pensano di sapere come utilizzare i database in modo efficace.
Adrian Pronk,

23
"Pigro" Mi piace pensare che sia intelligente, non pigro. Stai evitando codice ripetitivo e inutili controlli delle condizioni. Senza poter aggiungere where 1=1(Oracle) o where true(Postgres), dovrò verificare per ogni condizione se è la prima. Non ha senso farlo, e aggiunge solo più codice boilerplate.
ADTC

113

Basta aggiungere un codice di esempio alla risposta di 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

6
un po 'confuso, ma sembra un uso valido.
Mike,

5
Questa dovrebbe essere la risposta accettata. La pratica consiste davvero nel non dover determinare quanti condizionali hai.
aglassman,

38

L'ho visto usato quando il numero di condizioni può essere variabile.

È possibile concatenare le condizioni utilizzando una stringa "AND". Quindi, invece di contare il numero di condizioni che stai passando, metti un "WHERE 1 = 1" alla fine dell'istruzione SQL di riserva e passi alle condizioni concatenate.

Fondamentalmente, ti risparmia di dover fare un test per le condizioni e quindi aggiungere una stringa "WHERE" prima di esse.


28

Sembra un modo pigro di sapere sempre che la tua clausola WHERE è già definita e ti consente di continuare ad aggiungere condizioni senza dover controllare se è la prima.


12
"Pigro" Mi piace pensare che sia intelligente, non pigro. Stai evitando codice ripetitivo e inutili controlli delle condizioni. Senza poter aggiungere where 1=1(Oracle) o where true(Postgres), dovrò verificare per ogni condizione se è la prima. Non ha senso farlo, e aggiunge solo più codice boilerplate.
ADTC

2
@ADTC La scrittura del codice è spesso - se non principalmente - relativa alla gestione di condizioni diverse. Questa è solo un'altra condizione che deve essere gestita, che personalmente ritengo pigra per inquinare l'SQL generato. Se modifichi il tuo codice per aggiungere "Where 1 = 1" in ONE, potresti - con un piccolo sforzo in più - gestire la differenza tra zero e molte condizioni in quel ONE posto nel tuo codice. La mia ipotesi è che i sostenitori di "Where 1 = 1" lo spargano attraverso la loro base di codice, il che mi porta alla conclusione che la pigrizia genera pigrizia.
Jason S,

@JasonS Laziness è il padre di Invention.
ADTC,

@ADTC Sono pigro perché non mi piace aggiornare il codice in centinaia di posti, quindi l'invenzione lo ha messo in un posto. Per me WHERE 1=1genera il lavoro extra di mantenere lo stesso codice in più punti e leggerlo in tutto il tuo SQL generato. Sono più pigro di te, penso!
Jason S,

19

Rilevante indirettamente: quando si utilizza 1 = 2:

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

questo creerà una nuova tabella con lo stesso schema della vecchia tabella. (Molto utile se si desidera caricare alcuni dati per i confronti)


3
Hai dimenticato di aggiungere, mentre creerà una nuova tabella con gli stessi dati di quelli precedenti, la nuova tabella non avrà altri vincoli come la chiave esterna dalla tabella precedente
milso

16

L'espressione 1 = 1 è comunemente usata nel codice sql generato. Questa espressione può semplificare il codice di generazione sql riducendo il numero di istruzioni condizionali.


11

In realtà, ho visto questo genere di cose usate nei rapporti BIRT. La query passata al runtime BIRT è nel formato:

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

e il '?' viene sostituito in fase di esecuzione da un valore di parametro effettivo selezionato da una casella a discesa. Le scelte nel menu a discesa sono fornite da:

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

in modo da ottenere tutti i valori possibili più " *". Se l'utente seleziona " *" dalla casella a discesa (ovvero tutti i valori di a devono essere selezionati), la query deve essere modificata (da Javascript) prima di essere eseguita.

Dal momento che il "?" è un parametro posizionale e DEVE rimanere lì affinché altre cose funzionino, Javascript modifica la query in modo che sia:

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

Ciò sostanzialmente rimuove l'effetto della clausola where, lasciando comunque in atto il parametro posizionale.

Ho anche visto il caso AND utilizzato dai programmatori pigri durante la creazione dinamica di una query SQL.

Supponi di dover creare dinamicamente una query che inizia con select * from te verifica:

  • il nome è Bob; e
  • lo stipendio è> $ 20.000

alcune persone aggiungerebbero la prima con un WHERE e le successive con un AND quindi:

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

I programmatori pigri (e questo non è necessariamente un tratto negativo ) non distinguerebbero tra le condizioni aggiunte, inizierebbero select * from t where 1=1e aggiungerebbero solo clausole AND.

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

1
"Pigro" Mi piace pensare che sia intelligente, non pigro. Stai evitando codice ripetitivo e inutili controlli delle condizioni. Senza poter aggiungere where 1=1(Oracle) o where true(Postgres), dovrò verificare per ogni condizione se è la prima. Non ha senso farlo, e aggiunge solo più codice boilerplate.
ADTC

1
@ADTC, non volevo dire pigro in modo negativo. In effetti, pigro è una buona caratteristica della programmazione :-) Chiarirò.
paxdiablo,

La pigrizia è la radice di tutti i mali
Ivanzinho,

11

Ho trovato utile questo schema quando sto testando o ricontrollando cose sul database, così posso commentare molto rapidamente altre condizioni:

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

diventa:

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

10

dove 1 = 0, questo viene fatto per verificare se la tabella esiste. Non so perché viene utilizzato 1 = 1.


1
Visto questo usato per restituire un set di risultati vuoto dal database da utilizzare come supporto per i nuovi record.
Gary Kindel,

6

Mentre vedo che 1 = 1 sarebbe utile per l'SQL generato, una tecnica che uso in PHP è quella di creare un array di clausole e quindi fare

implode (" AND ", $clauses);

evitando così il problema di avere un AND iniziale o finale. Ovviamente questo è utile solo se sai che avrai almeno una clausola!


1
Ecco dove entra in gioco 1 = 1. Ti dà quella "almeno una clausola", quindi non devi preoccuparti di schiaffeggiare un "AND abc"
Carl

Mi piace questa idea! Vedi qui per più completo esempio stackoverflow.com/questions/35326160/...
drooh

5

Ecco un esempio strettamente correlato: usare MERGEun'istruzione SQL per aggiornare la destinazione presentata usando tutti i valori della tabella di origine in cui non esiste alcun attributo comune su cui unirsi, ad es.

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

5

Perché qualcuno dovrebbe usare WHERE 1 = 1 AND <proper conditions>

Ho visto quadri Homespun fanno cose come questa ( rossore ), in quanto ciò consente pratiche di analisi pigri da applicare sia alle WHEREe ANDparole chiave SQL.

Ad esempio (sto usando C # come esempio qui), prendere in considerazione l'analisi condizionale dei seguenti predicati in una query 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";
}

Il "vantaggio" di WHERE 1 = 1significa che non è necessario alcun codice speciale:

  • Per AND - se zero, uno o entrambi i predicati (Bars e Baz's) dovrebbero essere applicati, il che determinerebbe se ANDè richiesto il primo . Dal momento che abbiamo già almeno un predicato con il 1 = 1, significa che ANDè sempre OK.
  • Per nessun predicato - Nel caso in cui siano presenti predicati ZERO, è WHEREnecessario eliminare il predicato . Ma ancora una volta, possiamo essere pigri, perché siamo di nuovo garantiti da almeno un predicato.

Questa è ovviamente una cattiva idea e raccomanderebbe di utilizzare un framework di accesso ai dati o ORM per analizzare i predicati facoltativi e condizionali in questo modo.


O se esegui il rotolamento, il builder clausola where dovrebbe trovarsi in un punto del codice. Quindi è possibile gestire zero predicati o più di zero predicati in un'unica posizione nel codice. Il mio sospetto è che l'esistenza di WHERE 1=1sia un giusto indicatore del fatto che NON è il caso, che la base di codice sia disseminata di bit di stringhe WHERE 1=1, il che indicherebbe a me un problema di architettura dell'applicazione, e immagino che non sia l'unico!
Jason S,

1
In realtà non c'è nulla di "cattivo" nell'idea, tanto meno un difetto "ovvio". Né un ORM è il modo corretto in tutti i casi. Impara le persone SQL e Algebra relazionale ...
Hejazzman,

4

Se sei venuto qui a cercare WHERE 1, nota che WHERE 1e WHERE 1=1sono identici. WHERE 1viene usato raramente perché alcuni sistemi di database lo rifiutano considerando che WHERE 1non è realmente booleano.


2

Ciò è utile nel caso in cui sia necessario utilizzare una query dinamica in cui nella clausola where è necessario aggiungere alcune opzioni di filtro. Come se includi le opzioni 0 per lo stato è inattivo, 1 per attivo. Sulla base delle opzioni, ci sono solo due opzioni disponibili (0 e 1) ma se si desidera visualizzare tutti i record, è utile includere in dove close 1 = 1. Vedi sotto esempio:

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

Dopo aver esaminato tutte le risposte, ho deciso di eseguire alcuni esperimenti come

SELECT
*
FROM MyTable

WHERE 1=1

Poi ho controllato con altri numeri

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

ect Dopo aver eseguito tutti i controlli, la query run town è la stessa. anche senza la clausola where. Non sono un fan della sintassi


1

Lo faccio di solito quando creo SQL dinamico per un report che ha molti valori a discesa che un utente può selezionare. Poiché l'utente può o meno selezionare i valori da ciascun menu a discesa, finiamo per avere difficoltà a capire quale condizione è stata la prima clausola where. Quindi riempiamo la query con un where 1=1alla fine e aggiungiamo tutte le clausole where in seguito.

Qualcosa di simile a

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

Quindi costruiremmo la clausola where in questo modo e la passeremmo come valore di parametro

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

Poiché la selezione della clausola where ci è sconosciuta in fase di esecuzione, questo ci aiuta molto a scoprire se includere un 'AND' or 'WHERE'.


0

L'uso di un predicato come 1=1è un suggerimento normale talvolta utilizzato per forzare il piano di accesso a utilizzare o non utilizzare una scansione dell'indice. Il motivo per cui questo viene utilizzato è quando si utilizza una query unita multi-nidificata con molti predicati nella clausola where in cui a volte anche l'utilizzo di tutti gli indici fa sì che il piano di accesso legga ogni tabella: una scansione completa della tabella. Questo è solo uno dei molti suggerimenti usati dai DBA per ingannare un dbms nell'usare un percorso più efficiente. Basta non buttarne uno dentro; è necessario un dba per analizzare la query poiché non sempre funziona.


4
Hai delle citazioni che documentano questo comportamento per alcuni database?
Joe,

0

Ecco un caso d'uso ... tuttavia non mi preoccupo troppo dei tecnicismi del perché dovrei o meno usare 1 = 1. Sto scrivendo una funzione, usando pyodbc per recuperare alcuni dati da SQL Server. Stavo cercando un modo per forzare un filler dopo la whereparola chiave nel mio codice. Questo è stato davvero un grande suggerimento:

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

Il motivo è perché non sono riuscito a implementare la parola chiave "dove" insieme all'interno della variabile della clausola _where. Quindi, penso che usare qualsiasi condizione fittizia che valuti come vera farebbe da riempitivo.


-1

Mi sono imbattuto per la prima volta in ADO e ASP classico, la risposta che ho avuto è stata: prestazioni. se fai una scala

Select * from tablename

e passalo come comando / testo sql otterrai un notevole aumento delle prestazioni con

Where 1=1

aggiunto, era una differenza visibile. qualcosa a che fare con la restituzione delle intestazioni del tavolo non appena viene soddisfatta la prima condizione, o qualche altra follia, comunque, ha accelerato le cose.


3
Se questo è vero, perché il DBMS non lo aggiunge sempre?
Carcamano,

5
Puoi produrre prove?
Peter G.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.