Я писал SQL, который возвращал описание продукта на основе заданного кода. Я подготовил свой запрос с предположением, что коды с разной капитализацией могут сосуществовать. Однако, фильтруя результаты моей основной таблицы, я бы хотел, чтобы мой результат учитывал регистр. То есть поиск некоторого строчного кода вернул бы только строчные коды, а не прописные эквиваленты.
Однако я пришел к выводу, что в зависимости от использования условия предложения WHERE в заглавной букве результат может измениться.
Я посмотрел на каждую таблицу, и у каждого есть свое сопоставление. Вместо этого я протестировал RIGHT JOIN, и он правильно соединил таблицы в обоих случаях. Кроме того, никогда не было необходимости проверять различные случаи: все коды должны быть прописными в соответствии со стандартами и валидациями нашей системы. Таким образом, хотя исправить это было так же просто, как убедиться, что мое предложение WHERE было в верхнем регистре, я все еще оставался в удивлении почему запрос дал другие результаты. Меня учили, что во время обработки запроса SQL предложение JOIN будет запускаться до предложения WHERE, гарантируя, что последнее будет просматривать результат присоединенный .
Для воспроизведения этой ошибки, во-первых, я создал базу данных с DEFAULT CHARACTER SET UTF8 COLLATION UNICODE_CI_AI
.
Затем я создал каждую таблицу как таковую:
CREATE TABLE MAIN_TABLE (
val VARCHAR(40) NOT NULL PRIMARY KEY,
code VARCHAR(40) NOT NULL COLLATE UNICODE_CI
);
CREATE TABLE PRODUCTS (
name VARCHAR(40) NOT NULL PRIMARY KEY,
code VARCHAR(40) NOT NULL COLLATE UNICODE
);
Затем я вставил следующие тестовые записи:
INSERT INTO MAIN_TABLE (val, code) VALUES ('This value is returned', 'ABC');
INSERT INTO PRODUCTS (name, code) VALUES ('My product', 'ABC');
И, наконец, я выполнил следующий запрос:
SELECT * FROM MAIN_TABLE
LEFT JOIN PRODUCTS
ON MAIN_TABLE.code = PRODUCTS.code
WHERE MAIN_TABLE.code LIKE '%abc%'
Что привело к:
MAIN_TABLE.code | MAIN_TABLE.val | PRODUCTS.code | PRODUCTS.name
----------------+------------------------+---------------+---------------
ABC | This value is returned | null | null
Обратите внимание, что, хотя мой запрос нашел результат в MAIN_TABLE, результат LEFT JOIN был равен нулю.
Однако точно такой же запрос, измените предложение WHERE, возвращает другой результат. Итак, запрос:
SELECT * FROM MAIN_TABLE
LEFT JOIN PRODUCTS
ON MAIN_TABLE.code = PRODUCTS.code
WHERE MAIN_TABLE.code LIKE '%ABC%'
Закончилось возвращением:
MAIN_TABLE.code | MAIN_TABLE.val | PRODUCTS.code | PRODUCTS.name
----------------+------------------------+---------------+---------------
ABC | This value is returned | ABC | My product
Я задавался вопросом - было ли мое понимание порядка операций неправильным? Читает ли сервер базы данных запрос, идентифицирует ли он, что столбец предложения WHERE (MAIN_TABLE.code
) такой же, как в JOIN, и , а затем изменяет внутреннюю обработку JOIN (для оптимизации или иным образом)? Или это просто ошибка в том, как Firebird интерпретирует запросы? Я ожидал некоторого странного поведения, учитывая различные параметры сортировки, но я не был уверен, что это какая-то особенность.
Почему мое предложение WHERE повлияло на мое левое соединение?
Я не ищу способов исправить это , поскольку я нашел много - изменение параметров сортировки, прописные буквы моего запроса, предварительная проверка кода и т. Д.
Моя база данных работает на Firebird 3.0. Я проверил опции для отображения всех сообщений, проверил журналы и проверил варианты запросов, которые работали. Я не видел там ничего, что могло бы дать мне представление о том, почему это произошло.