MySQL: Где AND / OR / XOR может использоваться как что-либо кроме логических операторов в предложениях WHERE? - PullRequest
2 голосов
/ 16 апреля 2020

Я заметил, что MySQL логические бинарные операторы (AND, OR и XOR) не всегда действуют как таковые. В частности, AND может появляться как часть BETWEEN ... AND ... выражения.

Кроме BETWEEN, есть ли другой случай, когда любой из этих трех токенов (слов) может появляться как часть WHERE предложение, но не действует как логический оператор?

1 Ответ

3 голосов
/ 16 апреля 2020

AND в BETWEEN .. AND - это не то же самое, что оператор AND. Он просто использует одно и то же ключевое слово. Я просматриваю исходный код парсера jOOQ и могу сказать, что по крайней мере (далеко не исчерпывающе):

AND

  • In предложения фрейма оконной функции, такие как ROWS BETWEEN 3 PRECEDING AND 3 FOLLOWING
  • В предложениях MERGE оператора *1014* (пока не поддерживается MySQL 8), таких как WHEN [ NOT ] MATCHED [ AND ... ] THEN
  • В X BETWEEN Y AND Z предикат
  • В синтаксисе временного запроса FOR PORTION OF .. BETWEEN .. AND (пока не поддерживается MySQL 8)

ИЛИ

  • В CREATE OR REPLACE операторы, такие как CREATE OR REPLACE VIEW

NOT

  • NOT NULL предикат
  • NOT LIKE предикат
  • IF NOT EXISTS предложение в DDL и множество других предложений DDL, таких как SET NOT NULL, DROP NOT NULL, et c. et c.

Другие токены

  • Существуют также "мягкие совпадения", которые могут быть полезны, если ваш "парсер" недостаточно умен для фактического анализа SQL язык. Они могут включать в себя такие функции, как BIT_AND()

Заключение для вашего варианта использования

SQL не является тривиальным языком для анализа. Синтаксический анализатор * minimal81 c не может легко преобразовать все виды логических выражений (или других вещей) для создания "эквивалентных" объединений. Это очень тяжело ! Ваш случай может быть неправильным, в зависимости от прогноза. Например, эти два запроса не совпадают:

-- May produce duplicate values for col
SELECT col
FROM t
WHERE (a OR b) AND x AND y

-- Does not produce duplicate values for col
SELECT col
FROM t
WHERE a AND x AND y
UNION
SELECT col
FROM t
WHERE b AND x AND y

UNION ALL не может использоваться здесь, потому что тогда вы получите слишком много дубликатов, которые вы не получили раньше. Вам нужно будет создать этот запрос (сродни тому, что делает Oracle, когда он применяет «преобразование конкатенации», например, с помощью подсказки /*+USE_CONCAT*/):

SELECT col
FROM t
WHERE a AND x AND y
UNION ALL
SELECT col
FROM t
WHERE b AND x AND y AND NOT (a AND x AND y) -- Exclude previous UNION subquery predicate here

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

Но вы действительно что-то получили? Тяжело сказать. Возможно, вы сломали свой запрос? Вероятно, потому что, что произойдет, если у вас уже есть UNION? Или ORDER BY? Или DISTINCT? Или LIMIT?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...