Это упрощенная версия запроса, который мы выполняем, где нам нужно найти все строки в основной родительской таблице, где совпадают дочерние строки. Приведенный ниже запрос не возвращает результатов, когда одна из дочерних таблиц пуста.Почему этот запрос возвращает результаты только с непустыми дочерними таблицами?
Основная таблица имеет два дочерних таблиц:
CREATE TABLE main (id INT PRIMARY KEY, name VARCHAR(8));
CREATE TABLE child1(id INT PRIMARY KEY, main_id int, name VARCHAR(8));
ALTER TABLE child1 add constraint fk_child1_main foreign key (main_id) references main (id);
CREATE TABLE child2(id INT PRIMARY KEY, main_id int, name VARCHAR(8));
ALTER TABLE child2 add constraint fk_child2_main foreign key (main_id) references main (id);
INSERT INTO main (id, name) VALUES (1, 'main');
INSERT INTO child1 (id, main_id, name) VALUES (2, 1, 'child1');
Там нет строк в child2 и следующий запрос не возвращает ни одной строки, когда она пуста:
SELECT
main.*
FROM
main
INNER JOIN
child1
ON
main.id = child1.main_id
INNER JOIN
child2
ON
main.id = child2.main_id
WHERE
child1.name = 'child1' OR
child2.name = 'DOES NOT EXIST';
Если строка добавляется child2, даже если он не соответствует предложению WHERE, тогда SELECT возвращает строку в основной таблице.
INSERT INTO child2 (id, main_id, name) VALUES (4, 1, 'child2');
Я тестировал это на Derby и SQLite, поэтому это выглядит как нечто общее с базами данных.
Почему это ведет себя так?
Что я могу сделать, чтобы исправить это?
Я мог бы переключиться на отдельные SELECT-соединения UNION, но это гораздо более многословно, и, кроме того, мы динамически генерируем SQL, и мне бы не пришлось менять код.
Еще одно решение - просто добавить в базу данных тупик, но это грязно.
PS Основная таблица - таблица сеансов в системе управления активами, которая регистрирует активы, которые клиенты ищут. Существуют различные типы поиска, и каждый вид получает отдельную дочернюю таблицу, плюс есть таблица дочерних элементов атрибутов для пар ключ/значение для сеанса, на который можно выполнить поиск.
Тогда почему добавление несогласованной строки в child2 изменяет результат запроса? Согласно этому утверждению, даже после добавления строки несоответствия к child2, запрос все равно не должен возвращать строки. –
Nevermind, я вижу, что это main.id = child2.main_id, который мешал запросу возвращать какие-либо результаты, даже если child2.name не совпало. Я просто игнорировал эту часть запроса. –