SQL "УДАЛИТЬ КАСКАД"
У меня есть таблица B, которая имеет внешний ключ к таблице A, и теперь я хочу сделать что-то вроде "DELETE CASCADE" на A, но PostgreSQL не примет следующее:
DELETE FROM ATable WHERE aid IN
(
DELETE FROM BTable WHERE aid IN
(
... [expression that depends on the entries in BTAble] ...
)
RETURNING aid
);
Кажется, что только SELECT может быть внутри IN ()
пункт. Я полагаю, что есть какой-то простой (и стандартный SQL, а не специфичный для PostgreSQL?) Способ сделать это?
Редактировать: безопасно ли говорить, что что-то плохо структурировано, когда вы сталкиваетесь с такой проблемой? В нашем случае у меня есть ощущение, что хиты в ..[expr]..
должен быть в новом CTAble, а не в качестве подмножества в ATable, но я не могу указать на какую-либо парадигму дизайна, поддерживающую это.
4 ответа
Функции БД находятся за пределами моей зоны комфорта (я знаю, я знаю), и я не хотел даже вносить временные изменения в рассматриваемые столбцы, поэтому я просто сделал
CREATE TABLE CTable AS ... [expression that depends on BTAble] ...;
и использовал это для последовательного удаления данных в B и A.
Это будет возможно с PostgreSQL 9.1, но я не думаю, что есть способ сделать это без определения каскадных ограничений.
http://developer.postgresql.org/pgdocs/postgres/queries-with.html
Вы можете ждать 9.1
или создайте функцию, возвращающую множество:
CREATE OR REPLACE FUNCTION fn_delete_btable(params)
RETURNS SETOF btable.aid%TYPE
AS
$$
DELETE
FROM btable
WHERE expression_over_params(params)
RETURNING
aid
$$
LANGUAGE 'sql';
DELETE
FROM atable
WHERE aid IN
(
SELECT aid
FROM fn_delete_btable(params)
)
PS На всякий случай, если вы не знаете о стандарте SQL
способ сделать это.
Если вы создаете таблицы следующим образом:
CREATE TABLE btable (aid INT NOT NULL UNIQUE, …)
CREATE TABLE atable (aid INT NOT NULL FOREIGN KEY REFERENCES (aid) ON DELETE CASCADE, …)
затем удалить из btable
инициирует удаление из atable
также.
Чтобы это работало, btable.aid
должно быть UNIQUE
или PRIMARY KEY
и это менее эффективно для массовых обновлений, чем решение на основе множеств.
Вы должны быть в состоянии сделать это: вот пример, который я нашел внизу этой страницы.
CREATE TABLE order_items (
product_no integer REFERENCES products ON DELETE RESTRICT,
order_id integer REFERENCES orders ON DELETE CASCADE,
quantity integer,
PRIMARY KEY (product_no, order_id)
);