Чому хтось використовує WHERE 1 = 1 AND <conditions> у пункті SQL?


257

Навіщо комусь користуватися WHERE 1=1 AND <conditions>в SQL-пункті (або SQL, отриманий за допомогою об'єднаних рядків, або визначення перегляду)

Я десь бачив, що це буде використовуватися для захисту від SQL Injection, але це здається дуже дивним.

Якщо ін'єкція 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

Відповіді:


346

Якщо перелік умов не відомий під час компіляції і натомість побудований під час виконання, вам не доведеться турбуватися про те, чи є у вас одна чи більше ніж одна умова. Ви можете їх генерувати, як:

and <condition>

і об'єднати їх усіх разом. З початком 1=1на початку початковий andмає щось асоціювати.

Я ніколи не бачив, щоб це використовувалося для будь-якого захисту від ін'єкцій, як ви кажете, це не здається, що це дуже допоможе. Я вже бачив , як це використовується в якості зручності реалізації. Двигун SQL запитів в кінцевому підсумку ігнорує, 1=1тому він не повинен впливати на продуктивність.


34
Іноді справа не в тому, щоб лінуватися, а мати більш чистий код.
Едуардо Мольтені

39
робота з підключенням ANDs або COMMA не є брудною ... нічого більш чистого, якщо 1 = 1 у вашому SQL.

21
DBA? Для чого вони? :)
Едуардо Мольтені

38
DBA є прибирати після програмістів, які думають, що вони знають, як ефективно використовувати бази даних.
Адріан Пронк

23
"Ледачий" мені подобається вважати, що це розумно, а не лінь. Ви уникаєте повторюваного коду та зайвих перевірок стану. Не маючи змоги додати where 1=1(Oracle) або where true(Postgres), мені доведеться перевірити для кожної умови, чи є першою. В цьому немає сенсу, і це лише додає більше кодового коду.
ADTC

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

38

Я бачив, як він використовується, коли кількість умов може бути змінною.

Ви можете об'єднати умови, використовуючи рядок "І". Потім, замість того, щоб рахувати кількість умов, які ви проходите, ви поміщаєте "WHERE 1 = 1" в кінці вашої операції SQL запасу і кидаєте на об'єднані умови.

В основному, це дозволяє економити вам тест на умови, а потім до них додавати рядок "WHERE".


28

Здається, ледачий спосіб завжди знати, що ваш пункт WHERE вже визначений і дозволяє вам продовжувати додавати умови, не перевіряючи, чи це перший.


12
"Ледачий" мені подобається вважати, що це розумно, а не лінь. Ви уникаєте повторюваного коду та зайвих перевірок стану. Не маючи змоги додати where 1=1(Oracle) або where true(Postgres), мені доведеться перевірити для кожної умови, чи є першою. В цьому немає сенсу, і це лише додає більше кодового коду.
ADTC

2
@ADTC Письмовий код часто - якщо не в основному - стосується обробки різних умов. Це лише ще одна умова, з якою потрібно впоратися, і я особисто вважаю, що лінь забруднювати створений SQL. Якщо ви архітектуєте свій код, щоб додати "Де 1 = 1" в одному місці, ви могли б - з невеликими додатковими зусиллями - впоратися з різницею між нулем і багатьма умовами в цьому ОДНОМУ місці вашого коду. Я думаю, що прихильники «Де 1 = 1» розповсюджують його по всій своїй кодовій базі, що підводить мене до висновку, що лінь породжує лінь.
Jason S

@JasonS Лінь - батько Винахідництва.
ADTC

@ADTC Я лінивий, бо мені не подобається оновлювати код у сотнях місць, тому винахід ставиться в одне місце. Для мене WHERE 1=1потрібна додаткова робота з підтримання одного і того ж коду в декількох місцях і читання його у всіх створених SQL. Я лінивий, ніж ти думаєш!
Джейсон 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, залишаючи при цьому позиційний параметр.

Я також бачив випадок AND, який використовуються ледачими кодерами, динамічно створюючи SQL-запит.

Скажіть, що вам потрібно динамічно створити запит, який починається select * from tі перевіряється:

  • ім'я Боб; і
  • зарплата становить> 20000 доларів

деякі люди додають перший з 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

1
@ADTC, я не мав на увазі лінивий погано. Насправді ледачий - хороша риса в програмуванні :-) Я уточню.
paxdiablo

Лінь - корінь усього зла
Іванзіньо

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
Це вбачається для повернення порожнього набору результатів з бази даних, який буде використовуватися як власник для нових записів.
Гері Кіндель

6

Хоча я можу бачити, що 1 = 1 буде корисним для створеного SQL, я використовую техніку в PHP, щоб створити масив пропозицій, а потім зробити

implode (" AND ", $clauses);

таким чином, уникнути проблеми наявності провідного або кінцевого І. Очевидно, це корисно лише в тому випадку, якщо ви знаєте, що у вас буде хоча б одне застереження!


1
Ось де входить 1 = 1. Це дає вам "принаймні один пункт", тож вам не доведеться турбуватися про те, щоб просто ляпнути по "AND abc"
Карл

Мені подобається ця ідея! Дивіться тут для більш повного прикладу 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

Чому хтось використовує, де 1 = 1 І <proper conditions>

Я бачив, як домоткані рамки роблять подібні речі ( рум'яна ), оскільки це дозволяє застосовувати практику ледачого розбору як до ключових слів, так WHEREі до ANDSql.

Наприклад (тут я використовую 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 - нульовий, слід застосувати один або обидва предикати (Bars і Baz's), які б визначали, чи потрібно перший AND. Оскільки у нас вже є принаймні один присудок із значком 1 = 1, це означає, що ANDце завжди добре.
  • Для предикатів взагалі немає - У випадку, коли є предикати ZERO, тоді WHEREнеобхідно скасувати. Але знову ж таки, ми можемо лінуватися, тому що ми знову гарантуємо хоча б один присудок.

Це, очевидно, погана ідея і рекомендує використовувати встановлений фреймворк доступу до даних або ORM для розбору необов'язкових та умовних предикатів таким чином.


Або якщо прокат ваш, конструктор пропозицій де повинен бути в одному місці у вашому коді. Тоді ви можете обробити нульові предикати або більше нульових предикатів в одному місці вашого коду. Я підозрюю, що існування WHERE 1=1є справедливим показником того, що це НЕ так, що база коду всіяна шматочками рядків WHERE 1=1, що вказувало б на проблему архітектури додатків, і я б здогадався не єдиний!
Jason S

1
Насправді в ідеї немає нічого поганого, тим більше "очевидної" помилки. Також ОРМ не є правильним способом у всіх випадках. Дізнайтеся людей з SQL та реляційної алгебри ...
Hejazzman

4

Якщо ви прийшли сюди в пошуках WHERE 1, відзначимо , що WHERE 1і WHERE 1=1ідентичні. WHERE 1використовується рідко, оскільки деякі системи баз даних відкидають його, вважаючи, що він WHERE 1насправді не є булевим.


2

Це корисно у випадку, коли вам доведеться використовувати динамічний запит, у якому в пункті, де ви повинні додати деякі параметри фільтра. Наприклад, якщо ви включили опції 0 для статусу неактивний, 1 для активного. Виходячи з параметрів, є лише два варіанти (0 і 1), але якщо ви хочете відобразити Усі записи, зручно включити туди, де близько 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 Зробивши всі перевірки, місто, яке працює за запитом, те саме. навіть без пункту де. Я не шанувальник синтаксису


1

Я роблю це, як правило, коли будую динамічний SQL для звіту, який має багато значень, що випадає, який може вибрати користувач. Оскільки користувач може або не може вибирати значення у кожному спадному меню, ми в кінцевому підсумку отримуємо важкий час з’ясувати, яка умова була першим де пунктом. Тож ми запитуємо запит за допомогою awhere 1=1 в кінці і додаємо всі пункти після цього.

Щось на зразок

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

Тоді ми б побудували пункт, як це, і передамо його як значення параметра

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

Оскільки вибір пункту пункту невідомий нам під час виконання, то це дуже допомагає нам знайти, чи потрібно включати 'AND' or 'WHERE'.


0

Використання предиката на зразок 1=1- це звичайна підказка, яка іноді використовується для примушування плану доступу до використання або не використання сканування індексів. Причина, чому це використовується, полягає в тому, що ви використовуєте багато вкладений об'єднаний запит з багатьма предикатами в пункті, де іноді навіть використання всіх індексів викликає план доступу для зчитування кожної таблиці - повне сканування таблиці. Це лише 1 із багатьох підказок, які використовуються DBA для обману dbms у використанні більш ефективного шляху. Просто не кидайте жодного; вам потрібен dba для аналізу запиту, оскільки він не завжди працює.


4
Чи є у вас цитати, які підтверджують цю поведінку для деяких баз даних?
Джо

0

Ось випадок використання ... однак я не надто переймаюся технічними можливостями, чому я повинен чи не використовувати 1 = 1. Я пишу функцію, використовуючи pyodbc для отримання деяких даних із SQL Server. Я шукав спосіб змусити наповнювач за whereключовим словом у своєму коді. Це справді було чудовою пропозицією:

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

Причина полягає в тому, що я не зміг реалізувати ключове слово «де» разом всередині змінної пункту _where. Отже, я думаю, що використання будь-якої манекенової умови, яка оцінюється як істинна, було б виконано як наповнювач.


-1

Я вперше натрапив на цю спину з ADO та класичним аспіром, я отримав відповідь: продуктивність. якщо ви робите пряму

Select * from tablename

і передайте, що як команда / текст sql, ви отримаєте помітне підвищення продуктивності за допомогою

Where 1=1

додав, це була видима різниця. щось стосується повернення заголовків таблиць, як тільки виконується перша умова, або якась інша божевільність, все одно, це прискорило роботу.


3
Якщо це правда, чому СУБД не завжди додає цього?
Carcamano

5
Чи можете ви представити докази?
Пітер Г.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.