В качестве ответа - но также и в качестве дополнительного пояснения к тому, что @AndreaColleoni уже упомянул:
управлять многими условиями ИЛИ в динамических запросах (например, WHERE 1=0 OR <condition>
)
Предназначен для включения / выключения
Я использую это как оператор включения / выключения для частей моего запроса.
Если бы я использовал
WHERE 1=1
AND (0=? OR first_name = ?)
AND (0=? OR last_name = ?)
Затем я могу использовать первую переменную связывания (?
), чтобы включить или выключить критерий поиска first_name
. и третья переменная связывания (?
) для включения или выключения критерия last_name
.
Я также добавил литерал 1=1
только для эстетики, чтобы текст запроса хорошо выровнялся.
Только для этих двух критериев это не кажется полезным, так как, возможно, проще сделать то же самое, динамически создавая условие WHERE, указав только first_name
или last_name
, или оба, или никто. Таким образом, ваш код должен будет динамически создавать 4 версии одного и того же запроса. Представьте себе, что произойдет, если у вас будет 10 различных критериев, а затем сколько комбинаций одного и того же запроса вам придется обрабатывать?
Оптимизация времени компиляции
Я также мог бы добавить, что добавление в 0 =? так как переменная связывания не будет работать очень хорошо, если все ваши критерии проиндексированы. Оптимизатор времени выполнения, который выберет соответствующие индексы и планы выполнения, может просто не увидеть экономическую выгоду от использования индекса в этих немного более сложных предикатах. Поэтому я обычно советую явно вставлять 0/1 в ваш запрос (объединить строку в вашем sql или выполнить поиск / замену). Это даст компилятору возможность оптимизировать избыточные операторы и даст исполнителю времени выполнения гораздо более простой запрос для рассмотрения.
(0=1 OR cond = ?) --> (cond = ?)
(0=0 OR cond = ?) --> Always True (ignore predicate)
Во втором приведенном выше утверждении компилятор знает, что ему никогда не придется даже учитывать вторую часть условия (cond = ?
), и он просто удалит весь предикат. Если бы это была переменная связывания, компилятор никогда бы этого не достиг.
Поскольку вы просто и принудительно вводите 0/1, вероятность внедрения SQL-кода равна нулю.
В моем SQL, в качестве одного из подходов, я обычно помещаю свои точки внедрения sql как $ {literal_name}, а затем просто выполняю поиск / замену с помощью регулярного выражения любого вхождения $ {...} с соответствующим литералом, прежде чем я даже пусть у компилятора есть на это удар. Это в основном приводит к тому, что запрос хранится следующим образом:
WHERE 1=1
AND (0=${cond1_enabled} OR cond1 = ?)
AND (0=${cond2_enabled} OR cond2 = ?)
Выглядит хорошо, легко понимается, компилятор хорошо с этим справляется, а Оптимизатор на основе затрат времени выполнения понимает его лучше и будет иметь более высокую вероятность выбора правильного индекса.
Я особенно внимательно отношусь к тому, что я делаю. Первичным способом передачи переменных является и остается связывание переменных по всем очевидным причинам.