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)
);
Другие вопросы по тегам