Удалить строки из левого соединения - PullRequest
0 голосов
/ 04 января 2019

Я хочу объединить две таблицы и удалить из них.

table1:

|ID| DATA|

table2:

|ID | ID_TAB1|

Запрос выглядит так:

delete from table2 
using table2 as t2 left join table1 as t1 
on t2.ID_TAB1=t1.ID 
where t1.DATA='xxx';

Проблема в том, что существует третья таблица:

Таблица3:

|ID|ID_TAB2|

Когда я запускаю свое утверждение, оно не говорит:

Обновление или удаление в таблице table2 нарушает ограничение внешнего ключа для таблицы table3

Я уверен, что в таблице 3 нет данных, связанных со строками с t1.DATA='xxx', так почему же возникает эта ошибка? Разве мой запрос не верный?

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Этот запрос:

delete from table2 
using table2 as t2 left join table1 as t1 
on t2.ID_TAB1=t1.ID 
where t1.DATA='xxx';

Фактически удаляет все строки из table2 (или ни одной, если в where нет совпадений. У вас нет связи между t2 и table2, так что по сути это перекрестное соединение.

Как объяснено (в глубине души) в документации :

Не повторяйте целевую таблицу в using_list, если только вы не хотите настроить самостоятельное соединение.

Предположительно, удаление всех строк вызывает проблему с третьей таблицей. Обратите внимание, что строки, которые вы действительно хотите удалить, также могут быть причиной проблемы. В этом случае вам нужно обрабатывать ошибки, используя некую каскадную логику.

Вы можете выразить это, используя предложение using и удалив join:

delete from table2 t2
    using table1 t1 
    where t2.ID_TAB1 = t1.ID  and
          t1.DATA = 'xxx';

Или просто используйте exists в предложении where:

delete from table2 t2
    where exists (select 1
                  from table1 t1
                  where t1.id = t2.id_tab1 and t1.data = 'xxx'
                 );
0 голосов
/ 04 января 2019

Возможно, вы имели в виду:

delete from table2 
 using table1
where  table2.ID_TAB1=table1.ID 
  and  table1.DATA='xxx';

Чем он отличается от вашего запроса:

  • он не вводит второй, независимый экземпляр table2.В противном случае запрос удалил бы все строки из table2.

  • квалификация left для соединения используется неправильно.Смысл левого соединения состоит в том, чтобы включить строки из table2, для которых нет соответствующих table1.id, а для отсутствующих столбцов table1 установлено значение NULL.Но условие t1.DATA='xxx' противоречит этому.

...