Зачем кому-то использовать WHERE 1 = 1 И <условия> в предложении SQL?

258

Зачем кому-то использовать WHERE 1=1 AND <conditions>в предложении SQL (либо SQL, полученный через объединенные строки, либо посмотреть определение)

Я где-то видел, что это будет использоваться для защиты от SQL-инъекций, но это кажется очень странным.

Если есть инъекция 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
Работа с конечными AND и COMMA не является грязной ... нет ничего лучше, если 1 = 1 по всему SQL.
21
АБД? Для чего они? :)
Эдуардо Молтени
38
Администраторы баз данных предназначены для очистки после программистов, которые думают, что знают, как эффективно использовать базы данных.
Адриан Пронк
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 и добавляете объединенные условия.

По сути, это избавляет вас от необходимости проверять условия и затем добавлять строку «ГДЕ» перед ними.

деревенщина
источник
28

Похоже, ленивый способ всегда знать, что ваше предложение WHERE уже определено и позволяет вам продолжать добавлять условия, не проверяя, является ли оно первым.

Джон Лемп
источник
12
«Ленивый» Мне нравится думать, что это умный, а не ленивый. Вы избегаете повторяющегося кода и ненужных проверок условий. Не имея возможности добавить where 1=1(Oracle) или where true(Postgres), мне придется проверять для каждого условия, является ли оно первым. В этом нет никакого смысла, и это только добавляет больше стандартного кода.
ADTC
2
@ADTC Написание кода часто - если не в основном - связано с обработкой различных условий. Это просто еще одно условие, которое должно быть обработано, и я лично считаю ленивым загрязнять сгенерированный SQL. Если вы спроектировали свой код так, чтобы добавить «Где 1 = 1» в ОДНОМ месте, вы могли бы - без особых дополнительных усилий - обработать разницу между нулем и многими условиями в этом ОДНОМ месте в вашем коде. Однако я предполагаю, что сторонники «Где 1 = 1» распространяют его по всей своей кодовой базе, что приводит меня к выводу, что лень порождает лень.
Джейсон С
@JasonS Лень - отец Изобретения.
ADTC
@ADTC Мне лень, потому что я не люблю обновлять код в сотнях мест, поэтому изобретение - в одном месте. Для меня WHERE 1=1это дополнительная работа по поддержанию одного и того же кода в нескольких местах и ​​чтению его во всех ваших сгенерированных SQL. Я ленивее тебя, я думаю!
Джейсон С
19

Косвенно релевантно: когда используется 1 = 2:

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

это создаст новую таблицу с той же схемой, что и старая таблица. (Очень удобно, если вы хотите загрузить некоторые данные для сравнения)

milso
источник
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проверки:

  • зовут Боб; и
  • зарплата> 20 000 долларов

некоторые люди добавили бы первое с ГДЕ, а последующие с И, таким образом:

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
paxdiablo
источник
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);

таким образом избегая проблемы наличия ведущего или конечного И. Очевидно, это полезно, только если вы знаете, что у вас будет хотя бы одно предложение!

sanbikinoraion
источник
1
Вот где приходит 1 = 1. Это дает вам «хотя бы одно предложение», так что вам не нужно беспокоиться о том, чтобы просто хлопнуть по «И 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;
onedaywhen
источник
5

Зачем кому-то использовать ГДЕ 1 = 1 И <proper conditions>

Я видел, как фреймворки homespun делают такие вещи ( blush ), поскольку это позволяет применять ленивые методы парсинга к ключевым словам 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 для синтаксического анализа необязательных и условных предикатов таким образом.

StuartLC
источник
Или, если вы работаете самостоятельно, конструктор предложения where должен находиться в одном месте вашего кода. Затем вы можете обрабатывать нулевые предикаты или более нуля предикатов в одном месте в вашем коде. Мое подозрение заключается в том, что существование WHERE 1=1является справедливым показателем того, что это НЕ тот случай, что кодовая база завалена битами строк WHERE 1=1, что указывало бы на проблему с архитектурой приложения, и я думаю, не единственная!
Джейсон С
1
На самом деле в этой идее нет ничего «плохого», а тем более «очевидной» ошибки. И ORM не является правильным способом во всех случаях. Люди,
изучающие
4

Если вы пришли сюда в поисках WHERE 1, обратите внимание, что WHERE 1и WHERE 1=1они идентичны. WHERE 1используется редко, потому что некоторые системы баз данных отклоняют его, считая, что он WHERE 1не является логическим.

Йогеш Умеш Ваиты
источник
2

Это полезно в случае, когда вам нужно использовать динамический запрос, в котором в предложении where вы должны добавить некоторые параметры фильтра. Например, если вы включите опции 0 для статуса неактивно, 1 для активного. Исходя из опций, есть только две доступные опции (0 и 1), но если вы хотите отобразить все записи, удобно включить туда, где close 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

т. е. выполнив все проверки, запрос run town остается прежним. даже без оговорки куда. Я не фанат синтаксиса

Jonway
источник
1

Я делаю это обычно, когда создаю динамический SQL для отчета, который имеет много выпадающих значений, которые пользователь может выбрать. Так как пользователь может или не может выбирать значения из каждого раскрывающегося списка, нам в конечном итоге трудно понять, какое условие было первым предложением where. Таким образом, мы дополняем запрос символом « where 1=1в конце» и добавляем все предложения where после этого.

Что-то вроде

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

Затем мы построим предложение where, как это, и передадим его в качестве значения параметра.

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

Поскольку выбор условия where нам неизвестен во время выполнения, это очень помогает нам найти, включать ли 'AND' or 'WHERE'.

Зо имеет
источник
0

Использование подобного предиката 1=1является обычной подсказкой, иногда используемой, чтобы заставить план доступа использовать или не использовать сканирование индекса. Причина, по которой это используется, заключается в том, что вы используете многостраничный объединенный запрос со многими предикатами в предложении where, где иногда даже использование всех индексов заставляет план доступа читать каждую таблицу - полное сканирование таблицы. Это всего лишь один из многих советов, используемых администраторами баз данных, чтобы обманным путем заставить использовать более эффективный путь. Только не бросай одну; вам нужен 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' вместе внутри переменной предложения _where. Итак, я думаю, что использование любого фиктивного условия, которое оценивается как истинное, подойдет в качестве наполнителя.

смс
источник
-1

Впервые я столкнулся с этим с ADO и классическим ASP, ответ я получил: производительность. если вы делаете прямой

Select * from tablename

и передать, что в качестве команды / текста SQL вы получите заметное увеличение производительности с

Where 1=1

добавил, это была видимая разница. что-то связанное с возвращением заголовков таблицы, как только будет выполнено первое условие, или какое-то другое безумие, в любом случае, это ускорило процесс.

jackberry
источник
3
Если это правда, почему СУБД не всегда добавляет это?
Каркамано
5
Можете ли вы представить доказательства?
Питер Г.