Perché qualcuno dovrebbe usare DOVE 1 = 1 E < condizioni > in una clausola SQL?

StackOverflow https://stackoverflow.com/questions/242822

  •  04-07-2019
  •  | 
  •  

Domanda

Perché qualcuno dovrebbe usare DOVE 1 = 1 AND < condizioni > 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 è presente l'iniezione DOVE 1 = 1 E iniettato OR 1 = 1 avrebbe lo stesso risultato di iniettato OR 1 = 1 .

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


Grazie per le tue risposte.

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

Prendi questo ad esempio:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 AND table.Field=Value
È stato utile?

Soluzione

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 concatenali tutti insieme. Con 1 = 1 all'inizio, i e iniziali hanno qualcosa a cui associarsi.

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

Altri suggerimenti

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

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

Puoi concatenare le condizioni usando un " E " stringa. Quindi, invece di contare il numero di condizioni che stai passando, inserisci un "DOVE 1 = 1" alla fine della tua istruzione SQL di riserva e lancia le condizioni concatenate.

Fondamentalmente, ti risparmia di dover fare un test per le condizioni e quindi aggiungere un " DOVE " stringa prima di loro.

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.

Indirettamente rilevante: 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)

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

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

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 possibili valori più " * " ;. Se l'utente seleziona " * " dalla casella a discesa (ovvero tutti i valori di a devono essere selezionati), la query deve essere modificata (tramite 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 posizione il parametro posizionale.

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

Supponi di dover creare dinamicamente una query che inizia con seleziona * da t e controlla:

  • 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 con select * da t dove 1 = 1 e aggiungi solo le clausole AND dopo.

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

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

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

si trasforma in:

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

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!

Ecco un esempio strettamente correlato: utilizzare un'istruzione SQL MERGE per aggiornare la destinazione presentata utilizzando tutti i valori della tabella di origine in cui non esiste alcun attributo comune su cui partecipare, 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;
  

Perché qualcuno dovrebbe usare DOVE 1 = 1 E < condizioni adeguate >

Ho visto i framework homespun fanno cose come questa ( arrossire ), in quanto consente di applicare pratiche di analisi pigra sia alle parole chiave WHERE che AND Sql.

Ad esempio (sto usando C # come esempio qui), si consideri 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 DOVE 1 = 1 significa che non è necessario alcun codice speciale:

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

Questa è ovviamente una cattiva idea e raccomanderebbe l'uso di un framework di accesso ai dati consolidato o ORM per l'analisi dei predicati opzionali e condizionali in questo modo.

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

Questo è utile nel caso in cui devi usare una query dinamica in cui clausola devi 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 dove chiudere 1 = 1. Vedi l'esempio seguente:

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);

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

SELECT
*
FROM MyTable

WHERE 1=1

Quindi 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

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 tanti 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.

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 dove 1 = 1 alla fine e aggiungiamo tutte le clausole where in seguito.

Qualcosa di simile

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 trovare se includere un 'AND' o 'WHERE'.

L'ho scoperto per la prima volta con ADO e asp classico, la risposta che ho avuto è stata: prestazioni. se fai una scala

Seleziona * da tablename

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

Dove 1 = 1

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top