2015-03-27 2 views
4

У меня есть две таблицы, object и object_data, с объектом, ссылающимся на объект_данные по внешнему ключу (отношение равно 1: 1). Для набора объектов, мне нужно обнулить свои object_data ссылки и удалить соответствующие object_data строки, например:PostgreSQL: удаление строк, ссылающихся из другой таблицы

DELETE FROM object_data WHERE id IN 
(SELECT object_data_id FROM object WHERE ...); 

UPDATE object SET object_data_id = NULL WHERE ...; 

Проблема, ограничение внешнего ключа не позволяет удалять object_data строки, которые по-прежнему ссылается от объекта ,

Мое текущее решение считывает результаты SELECT в список, а затем обнуляет внешние ключи, а затем удаляет строки object_data пакетами разумного размера с использованием оператора IN. Есть ли лучшее решение? Добавление столбца, ссылающегося на объект object_data на объект, не является вариантом.

ответ

4

Да использовать КТР (Common Таблицы Expression)

WITH tmp AS (SELECT object_data_id FROM object WHERE ...), 
    upd AS (UPDATE object SET object_data_id = NULL WHERE ...) 
DELETE FROM object_data 
    WHERE id IN (SELECT object_data_id FROM tmp); 

Первый КТР под названием TMP выполняется первым и запоминает данные, которые нужны позже Второй КТР называется обно делает устанавливает величину поля NULL Наконец DELETE использует данные из tmp для выполнения DELETE

5

Sonds, как идеальная работа для модификатора ON UPDATE SET NULL для вашего ограничения FK. Per documentation:

SET NULL

указан столбец (ы) привязка к нулю.

ALTER TABLE object DROP CONSTRAINT <fk_name_here>; 

ALTER TABLE object ADD CONSTRAINT <fk_name_here> 
FOREIGN KEY ON (object_data_id) REFERENCES object_data (object_data_id) 
ON DELETE SET NULL; 

Угадать имя PK является object_data_id, тоже. Тогда все, что вам нужно:

DELETE FROM object_data WHERE id ... 

реверансы в object устанавливаются автоматически NULL.

в сторону, это звучит странно:

У меня есть две таблицы, объект и object_data с объектом ссылки object_data с помощью внешнего ключа (соотношение 1: 1)

Как правило, я ожидал бы, что ссылка будет наоборот от object_dataдоobject в таком сценарии, но это просто гадание из названий таблиц.

0

Вы можете создать временную таблицу:

CREATE TEMP TABLE object_data_ids AS 
SELECT object_data_id FROM object WHERE ...; 

Затем использовать временную таблицу как в вашем обновления и удаления:

UPDATE object SET object_data_id = NULL WHERE object_data_id IN 
(SELECT object_data_id FROM object_data_ids); 


DELETE FROM object_data WHERE id IN 
(SELECT object_data_id FROM object_data_ids); 

 Смежные вопросы

  • Нет связанных вопросов^_^