Зачем кому-то использовать 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


Если список условий неизвестен во время компиляции и вместо этого создается во время выполнения, вам не нужно беспокоиться о том, есть ли у вас одно или несколько условий. Вы можете сгенерировать их все, например:
and <condition>
и соедините их все вместе. С 1=1 вначале, у первоначального and есть что связать.
Я никогда не видел, чтобы это использовалось для какой-либо защиты от инъекций, как вы говорите, похоже, что это не сильно поможет. Я видел, что имеют используется для удобства реализации. Механизм запросов SQL в конечном итоге проигнорирует 1=1, поэтому это не должно повлиять на производительность.
В прошлом были случаи, когда SQL Server создавал плохие планы при использовании этого метода. По этой причине я больше не использую его, если только запрос не нацелен на получение определения схемы.
Согласовано. Проголосуйте за ответ на вопрос, но я бы рекомендовал для начала правильно написать запрос, а не лениться.
Иногда речь идет не о лени, а о более чистом коде.
работа с конечными операторами AND или COMMA не является грязной ... нет ничего более чистого, если 1 = 1 во всем вашем SQL.
Да, если бы наши администраторы баз данных увидели этот запрос в их коллекциях статистики RUNSTATS, они бы выследили вас, как утку (и прежде, чем кто-нибудь спросит, это на самом деле юмористическая строчка из фильмов «Назад в будущее»).
DBA? Для чего они? :)
Администраторы баз данных должны помочь программистам, которые думают, что знают, как эффективно использовать базы данных.
Одно место, где этот метод очень полезен, - это инструменты бизнес-аналитики, которые позволяют размещать «условные подсказки» в SQL, такие как Microstrategy.
where 1=1 (Oracle) или where true (Postgres), мне придется проверять каждое условие, является ли оно первым. В этом нет смысла, и это только добавляет больше шаблонного кода.
Я сторонник любого пути, и если кто-то сможет улучшить производительность, тем лучше. Я просто хотел указать, что создание массива условий (хранящихся в виде строк) с последующим объединением их с помощью «и» может быть такой же ленивой альтернативой подходу 1 = 1.
Может ли шаблон WHERE 1 AND <conditions> каким-либо образом вводить гигантские дыры в безопасности через внедрение sql по сравнению с WHERE <condition 1> AND <conditions 2+>? Мой начальник говорит мне, что он вводит sql-инъекцию, это ужасно, и этого не следует делать. Они тоже не могут мне привести никаких примеров. Они сумасшедшие и принимают это за инъекцию OR 1=1?
@radtek: Нет, SQL-инъекция не имеет ничего общего с фактически используемыми операторами SQL. Все дело в как, в котором вызываются операторы SQL.
Я так и подумал, я не вижу в этом никаких дыр в безопасности. В обоих случаях, если функция, генерирующая SQL, не допускает никаких условий, мы выбираем все в этой таблице.
и не должен ли план выполнения быть таким же, с условием или без него? Так что я не вижу вреда в использовании этого; он позволяет сделать код более чистым, и выполнение остается таким же.
Как насчет того, чтобы поставить 1 = 1 в конце и использовать <condition> AND? Разве это не решило бы проблему плохого плана запроса? Не удивлюсь, если первые условия окажут большее влияние, чем последующие ...
В SQL Server это не приводит к снижению производительности благодаря функции Constant Folding and Expression Evaluation (docs.microsoft.com/en-us/sql/relational-databases/…).
Похоже на ленивый способ всегда знать, что ваше предложение WHERE уже определено и позволяет вам продолжать добавлять условия, не проверяя, является ли оно первым.
where 1=1 (Oracle) или where true (Postgres), мне придется проверять каждое условие, является ли оно первым. В этом нет смысла, и это только добавляет больше шаблонного кода.
@ADTC Написание кода часто - если не в основном - связано с обработкой различных условий. Это просто еще одно условие, которое необходимо обработать, и я лично считаю, что лень загрязнять сгенерированный SQL. Если вы спроектируете свой код так, чтобы добавить «Где 1 = 1» в ОДНОМ месте, вы могли бы - с небольшими дополнительными усилиями - обработать разницу между нулем и многими условиями в этом ОДНОМ месте кода. Я предполагаю, однако, что сторонники «Где 1 = 1» разбрасывают его по всей своей кодовой базе, что подводит меня к выводу, что лень порождает лень.
@JasonS Лень - отец изобретений.
@ADTC Я ленив, потому что не люблю обновлять код в сотнях мест, поэтому изобретение помещает его в одно место. Для меня WHERE 1=1 порождает дополнительную работу по поддержанию одного и того же кода в нескольких местах и чтению его во всех сгенерированных вами SQL. Я думаю, что я ленивее тебя!
Выражение 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
немного хакерский, но похоже на допустимое использование.
Это должен быть принятый ответ. На самом деле практика сводится только к тому, чтобы не определять, сколько у вас условных операторов.
На самом деле, я видел такие вещи, используемые в отчетах 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 и проверяет:
некоторые люди добавляли бы первые с помощью 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, я не имел в виду ленивый в плохом смысле. Фактически, ленивость - это черта хорошо в программировании :-) Я поясню.
Впервые я столкнулся с этим с ADO и классическим asp, и получил ответ: представление. если ты сделаешь прямой
Select * from tablename
и передайте это как команду / текст sql, вы получите заметное увеличение производительности с
Where 1=1
добавил, это была видимая разница. что-то, связанное с возвращением заголовков таблиц при выполнении первого условия, или какое-то другое безумие, во всяком случае, это ускорило процесс.
Если это правда, почему СУБД не всегда это добавляет?
Я тоже это видел, но извините, я не могу указать движок / версию. Это было в какой-то момент за мои 20 с лишним лет программирования на sql. Я думаю, что произошло то, что без какого-либо предложения Where план выполнения завершился сканированием таблицы; добавление где 1 = 1 привело к лучшему плану. Но множественное число от анекдота <> данные; Я не могу поклясться, что основная проблема была не в переходной сети или другой проблеме с ресурсами :-p
где 1 = 0, это делается для проверки, существует ли таблица. Не знаю, почему используется 1 = 1.
Видно, что это используется для возврата пустого набора результатов из базы данных, который будет использоваться в качестве держателя для новых записей.
Хотя я вижу, что 1 = 1 было бы полезно для сгенерированного SQL, метод, который я использую в PHP, заключается в создании массива предложений, а затем
implode (" AND ", $clauses);
таким образом избегая проблемы наличия начального или конечного AND. Очевидно, это полезно только в том случае, если вы знаете, что у вас будет хотя бы одно предложение!
Вот где приходит 1 = 1. Это дает вам "по крайней мере одно предложение", поэтому вам не нужно беспокоиться о том, чтобы просто нажать на "AND abc"
Мне нравится эта идея! См. Здесь более полный пример stackoverflow.com/questions/35326160/…
Вот близкий пример: использование оператора 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, где иногда даже использование всех индексов заставляет план доступа читать каждую таблицу - полное сканирование таблицы. Это лишь один из многих советов, используемых администраторами баз данных, чтобы обмануть базу данных и заставить ее использовать более эффективный путь. Только не бросайте ни одного; вам нужна база данных для анализа запроса, поскольку она не всегда работает.
Есть ли у вас какие-либо ссылки, подтверждающие такое поведение некоторых баз данных?
Косвенно релевантно: когда используется 1 = 2:
CREATE TABLE New_table_name
as
select *
FROM Old_table_name
WHERE 1 = 2;
это создаст новую таблицу с той же схемой, что и старая таблица. (Очень удобно, если вы хотите загрузить данные для сравнения)
Забыл добавить, хотя он создаст новую таблицу с теми же данными, что и старая, новая таблица не будет иметь других ограничений, таких как внешний ключ из старой таблицы
Обычно я делаю это, когда создаю динамический 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 означает, что никакого специального кода не требуется:
AND. Поскольку у нас уже есть хотя бы один предикат с 1 = 1, это означает, что AND всегда в порядке.WHERE должен быть отброшен. Но опять же, мы можем полениться, потому что мы снова гарантируем хотя бы один предикат.Это, очевидно, плохая идея, и мы бы рекомендовали использовать установленную структуру доступа к данным или ORM для такого анализа необязательных и условных предикатов.
Или, если вы используете свой собственный, конструктор предложений where должен быть в одном месте вашего кода. Затем вы можете обрабатывать нулевые или более чем нулевые предикаты в одном месте вашего кода. Я подозреваю, что существование WHERE 1=1 является верным индикатором того, что это НЕ так, что кодовая база усеяна битами строк WHERE 1=1, что указывало бы мне на проблему архитектуры приложения, и я думаю, не единственную!
На самом деле в этой идее нет ничего «плохого», не говоря уже о «очевидном» недостатке. И ORM не является правильным способом во всех случаях. Изучите людей SQL и реляционной алгебры ...
Если вы пришли сюда в поисках 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 любого запроса. Даже запросы с подзапросами при правильном отступе.