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

Зачем кому-то использовать 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
"зачем кому-то использовать эту конструкцию для определения представления" Наверное по привычке. Он не дает никаких функциональных преимуществ в статических запросах.
ADTC 30.07.2014 09:47
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
270
2
219 075
20
Перейти к ответу Данный вопрос помечен как решенный

Ответы 20

Ответ принят как подходящий

Если список условий неизвестен во время компиляции и вместо этого создается во время выполнения, вам не нужно беспокоиться о том, есть ли у вас одно или несколько условий. Вы можете сгенерировать их все, например:

and <condition>

и соедините их все вместе. С 1=1 вначале, у первоначального and есть что связать.

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

В прошлом были случаи, когда SQL Server создавал плохие планы при использовании этого метода. По этой причине я больше не использую его, если только запрос не нацелен на получение определения схемы.

Mitch Wheat 28.10.2008 13:42

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

Ady 28.10.2008 13:45

Иногда речь идет не о лени, а о более чистом коде.

Eduardo Molteni 28.10.2008 13:55

работа с конечными операторами AND или COMMA не является грязной ... нет ничего более чистого, если 1 = 1 во всем вашем SQL.

Mark Brady 29.10.2008 01:01

Да, если бы наши администраторы баз данных увидели этот запрос в их коллекциях статистики RUNSTATS, они бы выследили вас, как утку (и прежде, чем кто-нибудь спросит, это на самом деле юмористическая строчка из фильмов «Назад в будущее»).

paxdiablo 29.10.2008 05:03

DBA? Для чего они? :)

Eduardo Molteni 29.10.2008 20:22

Администраторы баз данных должны помочь программистам, которые думают, что знают, как эффективно использовать базы данных.

Adrian Pronk 11.12.2009 13:46

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

N West 02.11.2012 18:30
"Ленивый" Мне нравится думать, что это умно, а не лениво. Вы избегаете повторяющегося кода и ненужных проверок условий. Не имея возможности добавить where 1=1 (Oracle) или where true (Postgres), мне придется проверять каждое условие, является ли оно первым. В этом нет смысла, и это только добавляет больше шаблонного кода.
ADTC 30.07.2014 09:58

Я сторонник любого пути, и если кто-то сможет улучшить производительность, тем лучше. Я просто хотел указать, что создание массива условий (хранящихся в виде строк) с последующим объединением их с помощью «и» может быть такой же ленивой альтернативой подходу 1 = 1.

Biagio Arobba 27.08.2015 19:41

Может ли шаблон WHERE 1 AND <conditions> каким-либо образом вводить гигантские дыры в безопасности через внедрение sql по сравнению с WHERE <condition 1> AND <conditions 2+>? Мой начальник говорит мне, что он вводит sql-инъекцию, это ужасно, и этого не следует делать. Они тоже не могут мне привести никаких примеров. Они сумасшедшие и принимают это за инъекцию OR 1=1?

radtek 30.09.2016 17:20

@radtek: Нет, SQL-инъекция не имеет ничего общего с фактически используемыми операторами SQL. Все дело в как, в котором вызываются операторы SQL.

Greg Hewgill 30.09.2016 23:27

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

radtek 01.10.2016 20:21

и не должен ли план выполнения быть таким же, с условием или без него? Так что я не вижу вреда в использовании этого; он позволяет сделать код более чистым, и выполнение остается таким же.

jtate 12.12.2016 18:25

Как насчет того, чтобы поставить 1 = 1 в конце и использовать <condition> AND? Разве это не решило бы проблему плохого плана запроса? Не удивлюсь, если первые условия окажут большее влияние, чем последующие ...

Fabian Pijcke 11.05.2017 11:32

В SQL Server это не приводит к снижению производительности благодаря функции Constant Folding and Expression Evaluation (docs.microsoft.com/en-us/sql/relational-databases/…).

Néstor Waldyd 06.04.2019 00:00
Лень - корень всего зла
Ivanzinho 15.10.2019 23:45

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

"Ленивый" Мне нравится думать, что это умно, а не лениво. Вы избегаете повторяющегося кода и ненужных проверок условий. Не имея возможности добавить where 1=1 (Oracle) или where true (Postgres), мне придется проверять каждое условие, является ли оно первым. В этом нет смысла, и это только добавляет больше шаблонного кода.
ADTC 30.07.2014 09:56

@ADTC Написание кода часто - если не в основном - связано с обработкой различных условий. Это просто еще одно условие, которое необходимо обработать, и я лично считаю, что лень загрязнять сгенерированный SQL. Если вы спроектируете свой код так, чтобы добавить «Где 1 = 1» в ОДНОМ месте, вы могли бы - с небольшими дополнительными усилиями - обработать разницу между нулем и многими условиями в этом ОДНОМ месте кода. Я предполагаю, однако, что сторонники «Где 1 = 1» разбрасывают его по всей своей кодовой базе, что подводит меня к выводу, что лень порождает лень.

Jason S 22.02.2016 09:51

@JasonS Лень - отец изобретений.

ADTC 22.02.2016 12:05

@ADTC Я ленив, потому что не люблю обновлять код в сотнях мест, поэтому изобретение помещает его в одно место. Для меня WHERE 1=1 порождает дополнительную работу по поддержанию одного и того же кода в нескольких местах и ​​чтению его во всех сгенерированных вами SQL. Я думаю, что я ленивее тебя!

Jason S 23.02.2016 03:42

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

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

Вы можете объединить условия, используя строку «И». Затем вместо подсчета количества условий, которые вы передаете, вы помещаете «WHERE 1 = 1» в конец стандартного оператора SQL и добавляете конкатенированные условия.

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

Просто добавив пример кода к ответу Грега:

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

немного хакерский, но похоже на допустимое использование.

Mike 11.12.2009 13:04

Это должен быть принятый ответ. На самом деле практика сводится только к тому, чтобы не определять, сколько у вас условных операторов.

aglassman 09.04.2013 23:05

На самом деле, я видел такие вещи, используемые в отчетах 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
"Ленивый" Мне нравится думать, что это умно, а не лениво. Вы избегаете повторяющегося кода и ненужных проверок условий. Не имея возможности добавить where 1=1 (Oracle) или where true (Postgres), мне придется проверять каждое условие, является ли оно первым. В этом нет смысла, и это только добавляет больше шаблонного кода.
ADTC 30.07.2014 09:54

@ADTC, я не имел в виду ленивый в плохом смысле. Фактически, ленивость - это черта хорошо в программировании :-) Я поясню.

paxdiablo 30.07.2014 10:28
Лень - корень всего зла
Ivanzinho 15.10.2019 23:44

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

Select * from tablename

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

Where 1=1

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

Если это правда, почему СУБД не всегда это добавляет?

Carcamano 16.05.2012 15:39

Я тоже это видел, но извините, я не могу указать движок / версию. Это было в какой-то момент за мои 20 с лишним лет программирования на sql. Я думаю, что произошло то, что без какого-либо предложения Where план выполнения завершился сканированием таблицы; добавление где 1 = 1 привело к лучшему плану. Но множественное число от анекдота <> данные; Я не могу поклясться, что основная проблема была не в переходной сети или другой проблеме с ресурсами :-p

spioter 19.12.2020 17:31

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

Видно, что это используется для возврата пустого набора результатов из базы данных, который будет использоваться в качестве держателя для новых записей.

Gary Kindel 28.01.2011 23:34

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

implode (" AND ", $clauses);

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

Вот где приходит 1 = 1. Это дает вам "по крайней мере одно предложение", поэтому вам не нужно беспокоиться о том, чтобы просто нажать на "AND abc"

Carl 21.01.2014 09:14

Мне нравится эта идея! См. Здесь более полный пример stackoverflow.com/questions/35326160/…

drooh 11.02.2016 00:23

Вот близкий пример: использование оператора 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;

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

Есть ли у вас какие-либо ссылки, подтверждающие такое поведение некоторых баз данных?

Joe 13.12.2013 20:16

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

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

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

Забыл добавить, хотя он создаст новую таблицу с теми же данными, что и старая, новая таблица не будет иметь других ограничений, таких как внешний ключ из старой таблицы

milso 08.05.2013 19:52

Обычно я делаю это, когда создаю динамический 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'..

Why would someone use WHERE 1=1 AND <proper conditions>

У меня домашние фреймворки видимый делают такие вещи (краснеть), поскольку это позволяет применять методы ленивого синтаксического анализа как к ключевым словам WHERE, так и к AND Sql.

Например (здесь я использую 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 означает, что никакого специального кода не требуется:

  • Для И - должен ли применяться ноль, один или оба предиката (Bars и Baz), которые будут определять, требуется ли первый AND. Поскольку у нас уже есть хотя бы один предикат с 1 = 1, это означает, что AND всегда в порядке.
  • Без предикатов вообще - в случае, когда есть предикаты НУЛЯ, то WHERE должен быть отброшен. Но опять же, мы можем полениться, потому что мы снова гарантируем хотя бы один предикат.

Это, очевидно, плохая идея, и мы бы рекомендовали использовать установленную структуру доступа к данным или ORM для такого анализа необязательных и условных предикатов.

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

Jason S 22.02.2016 10:02

На самом деле в этой идее нет ничего «плохого», не говоря уже о «очевидном» недостатке. И ORM не является правильным способом во всех случаях. Изучите людей SQL и реляционной алгебры ...

Hejazzman 10.10.2018 11:11

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

Я нашел полезный этот шаблон, когда я тестирую или дважды проверяю что-то в базе данных, поэтому я могу очень быстро прокомментировать другие условия:

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

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

Изучив все ответы, я решил провести эксперимент, например

SELECT
*
FROM MyTable

WHERE 1=1

Затем я проверил другие числа

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

т. д. После выполнения всех проверок город выполнения запроса останется прежним. даже без предложения where. Я не фанат синтаксиса

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

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

Причина в том, что я не смог реализовать ключевое слово 'where' вместе внутри переменной предложения _where. Итак, я думаю, что в качестве наполнителя можно использовать любое фиктивное условие, которое оценивается как истинное.

Сделав "where 1 = 1" стандартом для всех ваших запросов, также тривиально упростить проверку sql, заменив его на where 1 = 0, что удобно, когда у вас есть пакеты команд / файлов.

Также упрощает поиск конца раздела from / join любого запроса. Даже запросы с подзапросами при правильном отступе.

Другие вопросы по теме