2010-07-19 1 views
5

Я хочу удалить строки из двух таблиц, которые имеют зависимость друг от друга через набор отложенных ограничений. Чтобы упростить этот пост, я издевался над простой схемой БД.PostgreSQL 'Deferrable Delete' по-прежнему удаляет ограничение на Delete

Я надеюсь удалить записи из таблицы «delete_from_me» внутри транзакции SQL/DB Patch. Уловка, я хочу удалить на основе выбора из второй таблицы constraints_table, прежде чем я потеряю ссылку.

Вот описание двух таблиц:

tab-quarantine=> \d delete_from_me 
     Table "public.delete_from_me" 
    Column |  Type  | Modifiers 
-----------+-------------------+----------- 
id  | character varying | not null 
extension | character varying | not null 
Indexes: 
    "delete_from_me_pkey" PRIMARY KEY, btree (id) 

tab-quarantine=> \d constraining_table 
    Table "public.constraining_table" 
Column |  Type  | Modifiers 
--------+-------------------+----------- 
image | character varying | not null 
type | character varying | not null 
Foreign-key constraints: 
    "constraining_table_image_fkey" FOREIGN KEY (image) REFERENCES delete_from_me(id) 
     ON UPDATE CASCADE 
     ON DELETE RESTRICT DEFERRABLE 

Вот некоторые примеры данных я просто blatted там:

tab-quarantine=> SELECT * FROM delete_from_me; 
    id  | extension 
------------+----------- 
12345abcde | png 
(1 row) 

tab-quarantine=> SELECT * FROM constraining_table; 
    image | type 
------------+---------- 
12345abcde | select_me 
(1 row) 

И здесь идет моя сделка:

BEGIN; 
\set ON_ERROR_STOP 1 
SET CONSTRAINTS ALL DEFERRED; 
DELETE FROM delete_from_me WHERE id IN (
    SELECT image FROM constraining_table WHERE type = 'select_me' 
); 
DELETE FROM constraining_table WHERE type = 'select_me'; 
COMMIT; 

Этот транзакция не удалась. Когда я пошагово и сделать это вручную, я представил со следующим сообщением об ошибке:

ERROR: update or delete on table "delete_from_me" violates foreign key constraint "constraining_table_image_fkey" on table "constraining_table" 
DETAIL: Key (id)=(12345abcde) is still referenced from table "constraining_table". 

Это кажется хорошим кандидатом для временной таблицы, однако я хотел бы знать, почему это то, что Я не могу удалить в этом порядке, учитывая, что ограничения не должны быть эффективными до конца транзакции?

ответ

6

Использовать ON DELETE NO ACTION DEFERRABLE вместо ON DELETE RESTRICT DEFERRABLE. Использование RESTRICT вместо NO ACTION заставляет ограничение не отступать, независимо от того, применяете ли вы модификатор DEFERRABLE.

Это мелким шрифтом в manual page for CREATE TABLE:

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

Очевидно, что упомянутое выше предостережение содержит RESTRICT.

После вскоре после того, как это предложения является определение NO ACTION и RESTRICT:

NO ACTION

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

RESTRICT

Производит ошибку, указывающую, что удаление или обновление создаст ключ нарушение ограничения внешнего. Это то же самое, что и NO ACTION, за исключением того, что проверка не откладывается.

Как вы можете видеть, NO ACTION будет вести себя идентично RESTRICT, за исключением NO ACTION является откладываемые. Вот почему я рекомендовал его - я думаю, это именно то, о чем вы просите.