Dlaczego ktoś miałby używać GDZIE 1 = 1 ORAZ <warunki> w klauzuli SQL?

257

Dlaczego ktoś miałby używać WHERE 1=1 AND <conditions>klauzuli SQL (albo SQL uzyskany przez połączone łańcuchy, albo zobacz definicję)

Widziałem gdzieś, że byłoby to użyte do ochrony przed SQL Injection, ale wydaje się to bardzo dziwne.

Gdyby zastrzyk WHERE 1 = 1 AND injected OR 1=1miał taki sam wynik jak injected OR 1=1.

Późniejsza edycja: co z użyciem w definicji widoku?


Dziękuję Ci za Twoje odpowiedzi.

Nadal nie rozumiem, dlaczego ktoś miałby użyć tej konstrukcji do zdefiniowania widoku lub użyć jej w procedurze przechowywanej.

Weźmy na przykład:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 AND table.Field=Value
Bogdan Maxim
źródło
3
„dlaczego ktoś miałby używać tej konstrukcji do definiowania widoku” Prawdopodobnie z przyzwyczajenia. Nie oferuje żadnych korzyści funkcjonalnych w zapytaniach statycznych.
ADTC

Odpowiedzi:

346

Jeśli lista warunków nie jest znana w czasie kompilacji i zamiast tego jest budowana w czasie wykonywania, nie musisz się martwić, czy masz jeden, czy więcej niż jeden warunek. Możesz wygenerować je wszystkie w następujący sposób:

and <condition>

i połączyć je wszystkie razem. Z 1=1na początku, początkowa andma coś do obcowania z.

Nigdy nie widziałem tego używanego do jakiejkolwiek ochrony przed wstrzyknięciem, ponieważ mówisz, że nie wydaje się, aby to bardzo pomogło. Ja nie widziałem go stosować jako wygody realizacji. Mechanizm zapytań SQL zostanie zignorowany, 1=1więc nie powinien mieć wpływu na wydajność.

Greg Hewgill
źródło
34
Czasami nie chodzi o lenistwo, ale o czystszy kod.
Eduardo Molteni
39
radzenie sobie z końcowymi AND i COMMA nie jest brudne ... nic nie jest czystsze, mając 1 = 1 w całym SQL.
21
DBA? Po co one są? :)
Eduardo Molteni,
38
DBA są po to, aby posprzątać programistów, którzy myślą, że wiedzą, jak skutecznie korzystać z baz danych.
Adrian Pronk
23
„Leniwy” Lubię myśleć, że jest mądry, a nie leniwy. Unikasz powtarzającego się kodu i niepotrzebnych kontroli stanu. Bez możliwości dodania where 1=1(Oracle) lub where true(Postgres) będę musiał sprawdzić dla każdego warunku, czy jest to pierwszy. Nie ma sensu, aby to robić, a to tylko dodaje więcej kodu na tablicy.
ADTC
113

Wystarczy dodać przykładowy kod do odpowiedzi Grega:

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
źródło
6
nieco hacky, ale wydaje się, że jest to prawidłowe użycie.
Mike
5
To powinna być zaakceptowana odpowiedź. Praktyka polega tylko na tym, aby nie musieć ustalać, ile masz warunków warunkowych.
aglassman
38

Widziałem to używane, gdy liczba warunków może być zmienna.

Możesz konkatenować warunki, używając ciągu „AND”. Następnie zamiast zliczać liczbę warunków, które przechodzisz, umieszczasz „WHERE 1 = 1” na końcu swojej podstawowej instrukcji SQL i rzucasz konkatenowane warunki.

Zasadniczo oszczędza to konieczności przeprowadzania testu warunków, a następnie dodawania przed nimi łańcucha „GDZIE”.

Carl
źródło
28

Wydaje się to leniwym sposobem, aby zawsze wiedzieć, że twoja klauzula WHERE jest już zdefiniowana i pozwala ci dodawać warunki bez konieczności sprawdzania, czy jest to pierwsza.

John Lemp
źródło
12
„Leniwy” Lubię myśleć, że jest mądry, a nie leniwy. Unikasz powtarzającego się kodu i niepotrzebnych kontroli stanu. Bez możliwości dodania where 1=1(Oracle) lub where true(Postgres) będę musiał sprawdzić dla każdego warunku, czy jest to pierwszy. Nie ma sensu, aby to robić, a to tylko dodaje więcej kodu na tablicy.
ADTC
2
@ ADTC Pisanie kodu często - jeśli nie głównie - dotyczy różnych warunków. To tylko kolejny warunek, który należy sobie poradzić, który osobiście uważam za leniwy, aby zanieczyszczać wygenerowany SQL. Jeśli zbudujesz swój kod, aby dodać „Where 1 = 1” w JEDNYM miejscu, możesz - przy niewielkim dodatkowym wysiłku - obsłużyć różnicę między zerem a wieloma warunkami w tym JEDNYM miejscu w kodzie. Sądzę jednak, że zwolennicy „Where 1 = 1” posypują go w całej swojej bazie kodu, co prowadzi mnie do wniosku, że lenistwo rodzi lenistwo.
Jason S
@JasonS Laziness jest ojcem wynalazku.
ADTC
@ ADTC Jestem leniwy, ponieważ nie lubię aktualizować kodu w setkach miejsc, więc wynalazek został umieszczony w jednym miejscu. Dla mnie WHERE 1=1rodzi się dodatkowa praca polegająca na utrzymywaniu tego samego kodu w wielu miejscach i odczytywaniu go we wszystkich wygenerowanych kodach SQL. Myślę, że jestem leniwy!
Jason S
19

Pośrednio istotne: gdy stosuje się 1 = 2:

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

spowoduje to utworzenie nowej tabeli o takim samym schemacie jak stara tabela. (Bardzo przydatne, jeśli chcesz załadować dane do porównań)

milso
źródło
3
Zapomniałem dodać, podczas gdy utworzy nową tabelę z tymi samymi danymi, co stara, nowa tabela nie będzie miała innych ograniczeń, takich jak klucz obcy ze starszej tabeli
milso
16

Wyrażenie 1 = 1 jest powszechnie używane w generowanym kodzie SQL. To wyrażenie może uprościć generowanie kodu SQL, zmniejszając liczbę instrukcji warunkowych.

aku
źródło
11

W rzeczywistości widziałem tego rodzaju rzeczy używane w raportach BIRT. Zapytanie przekazane do środowiska wykonawczego BIRT ma postać:

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

i „?” w czasie wykonywania jest zastępowany rzeczywistą wartością parametru wybraną z rozwijanego pola. Opcje w menu rozwijanym są podane przez:

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

aby uzyskać wszystkie możliwe wartości plus „ *”. Jeśli użytkownik wybierze „ *” z listy rozwijanej (co oznacza, że ​​należy wybrać wszystkie wartości a), zapytanie musi zostać zmodyfikowane (przez Javascript) przed uruchomieniem.

Od „?” jest parametrem pozycyjnym i MUSI pozostać tam, aby działały inne rzeczy, JavaScript modyfikuje zapytanie tak, aby było:

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

To w zasadzie usuwa efekt klauzuli where, jednocześnie pozostawiając parametr pozycyjny na miejscu.

Widziałem także przypadek AND używany przez leniwych programistów podczas dynamicznego tworzenia zapytania SQL.

Załóżmy, że musisz dynamicznie utworzyć zapytanie, które zaczyna się select * from ti sprawdza:

  • nazywa się Bob; i
  • wynagrodzenie wynosi> 20 000 $

niektórzy dodaliby pierwszą z GDZIE, a kolejną z AND:

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

Leniwi programiści (i to niekoniecznie zła cecha) nie rozróżnią dodanych warunków, zaczną od select * from t where 1=1i po prostu dodadzą klauzule AND.

select * from t where 1=1 and name = 'Bob' and salary > 20000
paxdiablo
źródło
1
„Leniwy” Lubię myśleć, że jest mądry, a nie leniwy. Unikasz powtarzającego się kodu i niepotrzebnych kontroli stanu. Bez możliwości dodania where 1=1(Oracle) lub where true(Postgres) będę musiał sprawdzić dla każdego warunku, czy jest to pierwszy. Nie ma sensu, aby to robić, a to tylko dodaje więcej kodu na tablicy.
ADTC
1
@ ADTC, nie miałem na myśli lenistwa w zły sposób. W rzeczywistości leniwy jest dobrą cechą w programowaniu :-) Wyjaśnię.
paxdiablo
Lenistwo jest źródłem wszelkiego zła
Ivanzinho
11

Przydał mi się ten wzór podczas testowania lub podwójnego sprawdzania rzeczy w bazie danych, dzięki czemu mogę bardzo szybko skomentować inne warunki:

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

zamienia się w:

CREATE VIEW vTest AS
SELECT FROM Table WHERE 1=1 
--AND Table.Field=Value
--AND Table.IsValid=true
Carlos Toledo
źródło
10

gdzie 1 = 0, Odbywa się to w celu sprawdzenia, czy tabela istnieje. Nie wiem, dlaczego użyto 1 = 1.


źródło
1
Widzisz to używane do zwracania pustego zestawu wyników z bazy danych, który ma być używany jako uchwyt dla nowych rekordów.
Gary Kindel
6

Chociaż widzę, że 1 = 1 przydałby się w wygenerowanym SQL, techniką, której używam w PHP jest utworzenie tablicy klauzul, a następnie wykonanie

implode (" AND ", $clauses);

w ten sposób unikając problemu posiadania wiodącego lub końcowego AND. Oczywiście jest to przydatne tylko wtedy, gdy wiesz, że będziesz mieć co najmniej jedną klauzulę!

sanbikinoraion
źródło
1
Właśnie wtedy pojawia się 1 = 1. Daje ci to „co najmniej jedną klauzulę”, więc nie musisz się martwić, że uderzysz „AND abc”
Carl
Podoba mi się ten pomysł! Zobacz tutaj pełniejszy przykład stackoverflow.com/questions/35326160/…
drooh
5

Oto ściśle powiązany przykład: użycie MERGEinstrukcji SQL do zaktualizowania tabeli docelowej przy użyciu wszystkich wartości z tabeli źródłowej, w której nie ma wspólnego atrybutu, na którym można by dołączyć, np.

MERGE INTO Circles
   USING 
      (
        SELECT pi
         FROM Constants
      ) AS SourceTable
   ON 1 = 1
WHEN MATCHED THEN 
  UPDATE
     SET circumference = 2 * SourceTable.pi * radius;
oneedaywhen
źródło
5

Dlaczego ktoś miałby używać GDZIE 1 = 1 ORAZ <proper conditions>

Ja widziałem ramy fałszem robić rzeczy tak ( rumieniec ), gdyż pozwala to na leniwe praktyki parsowanie być stosowane zarówno do WHEREi ANDsłów kluczowych SQL.

Na przykład (używam C # jako przykładu tutaj), rozważ warunkowe analizowanie następujących predykatów w zapytaniu 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";
}

„Korzyść” WHERE 1 = 1oznacza, że ​​nie jest potrzebny żaden specjalny kod:

  • Dla AND - czy zero, należy zastosować jeden lub oba predykaty (słupki i Baz), które określą, czy pierwszy ANDjest wymagany. Ponieważ mamy już co najmniej jeden predykat z 1 = 1, oznacza to, że ANDzawsze jest OK.
  • W przypadku braku predykatów - w przypadku, gdy istnieją predykaty ZERO, WHEREnależy je usunąć. Ale znowu możemy być leniwi, ponieważ znów jesteśmy gwarancją co najmniej jednego orzeczenia.

Jest to oczywiście zły pomysł i zaleciłby użycie ustalonej struktury dostępu do danych lub ORM do analizowania opcjonalnych i warunkowych predykatów w ten sposób.

StuartLC
źródło
Lub jeśli tworzysz własne, kreator klauzuli where powinien znajdować się w jednym miejscu w kodzie. Następnie możesz obsłużyć predykaty zerowe lub więcej niż zero predykatów w jednym miejscu w kodzie. Podejrzewam, że istnienie WHERE 1=1jest uczciwym wskaźnikiem, który WHERE 1=1wcale tak nie jest, że baza kodu jest zaśmiecona kawałkami ciągów , co wskazywałoby mi na problem architektury aplikacji, i nie sądzę, że jedyny!
Jason S
1
W rzeczywistości pomysł nie ma „złego”, a tym bardziej „oczywistego” błędu. We wszystkich przypadkach ORM nie jest właściwy. Naucz się ludzi SQL i algebry relacyjnej ...
Hejazzman,
4

Jeśli przyszedłeś tu szukać WHERE 1, zauważ to WHERE 1i WHERE 1=1są identyczne. WHERE 1jest używany rzadko, ponieważ niektóre systemy baz danych odrzucają go, ponieważ WHERE 1nie są tak naprawdę boolowskie.

Yogesh Umesh Vaity
źródło
2

Jest to przydatne w przypadku, gdy trzeba użyć zapytania dynamicznego, w którym w klauzuli należy dołączyć niektóre opcje filtrowania. Tak jak w przypadku włączenia opcji 0 dla statusu jest nieaktywny, 1 dla aktywnego. Oparte na opcjach, są tylko dwie dostępne opcje (0 i 1), ale jeśli chcesz wyświetlić Wszystkie rekordy, dobrze jest umieścić w miejscu, gdzie close 1 = 1. Zobacz próbkę poniżej:

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
źródło
2

Po przejrzeniu wszystkich odpowiedzi postanowiłem przeprowadzić eksperyment

SELECT
*
FROM MyTable

WHERE 1=1

Potem sprawdziłem z innymi numerami

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

ect Po wykonaniu wszystkich kontroli miasto uruchomione w zapytaniu jest takie samo. nawet bez klauzuli where. Nie jestem fanem składni

JonWay
źródło
1

Robię to zwykle, gdy buduję dynamiczny SQL dla raportu, który ma wiele wartości rozwijanych, które użytkownik może wybrać. Ponieważ użytkownik może lub nie może wybrać wartości z każdego menu rozwijanego, w rezultacie trudno nam ustalić, który warunek był pierwszą klauzulą ​​where. Wypełniamy więc zapytanie where 1=1na końcu znakiem i dodajemy wszystkie klauzule where po tym.

Coś jak

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

Następnie zbudujemy taką klauzulę where i przekażemy ją jako wartość parametru

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

Ponieważ wybór klauzuli where nie jest nam znany w czasie wykonywania, pomaga nam to w ustaleniu, czy dołączyć 'AND' or 'WHERE'.

Zo Has
źródło
0

Użycie predykatu podobnego 1=1jest normalną wskazówką, która czasami jest używana do wymuszenia, aby plan dostępu używał lub nie korzystał ze skanowania indeksu. Powodem tego jest użycie wielo-zagnieżdżonego zapytania połączonego z wieloma predykatami w klauzuli where, w którym czasami nawet użycie wszystkich indeksów powoduje, że plan dostępu odczytuje każdą tabelę - pełne skanowanie tabeli. Jest to tylko jedna z wielu wskazówek używanych przez DBA, aby oszukać dbms w celu użycia bardziej wydajnej ścieżki. Po prostu nie wrzucaj jednego; potrzebujesz dba do analizy zapytania, ponieważ nie zawsze działa.

Big Al
źródło
4
Czy masz jakieś cytaty, które dokumentują takie zachowanie niektórych baz danych?
Joe
0

Oto przypadek użycia ... jednak nie martwię się zbytnio o szczegóły techniczne, dlaczego powinienem używać 1 = 1. Piszę funkcję, używając pyodbc do pobierania niektórych danych z SQL Server. Szukałem sposobu wymuszenia wypełniacza po wheresłowie kluczowym w moim kodzie. To była naprawdę świetna sugestia:

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

Powodem jest to, że nie mogłem zaimplementować słowa kluczowego „where” razem w zmiennej klauzula _where. Tak więc myślę, że użycie dowolnego warunku fikcyjnego, który ma wartość true, może być wypełniaczem.

SMS
źródło
-1

Po raz pierwszy natknąłem się na to z ADO i klasycznym boleniem, odpowiedź dostałem: wydajność. jeśli zrobisz strita

Select * from tablename

i przekaż to jako polecenie / tekst sql, otrzymasz zauważalny wzrost wydajności dzięki

Where 1=1

dodano, to była widoczna różnica. coś wspólnego z zwracaniem nagłówków tabel, gdy tylko pierwszy warunek zostanie spełniony, lub jakimś innym szaleństwem, co przyspieszyło sprawę.

jeżyna
źródło
3
Jeśli to prawda, dlaczego DBMS nie zawsze tego dodaje?
Carcamano
5
Czy potrafisz przedstawić dowody?
Peter G.