SQL «УДАЛИТЬ КАСКАД» - PullRequest
       30

SQL «УДАЛИТЬ КАСКАД»

2 голосов
/ 15 апреля 2011

У меня есть таблица 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 ]

2 голосов
/ 15 апреля 2011

Вы можете подождать 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, и это менее эффективно для массовых обновлений, чем решение на основе набора.

2 голосов
/ 15 апреля 2011

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

http://developer.postgresql.org/pgdocs/postgres/queries-with.html#QUERIES-WITH-MODIFYING

1 голос
/ 15 апреля 2011

Вы должны сделать это: вот пример, который я нашел внизу этой страницы.

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)
);
0 голосов
/ 15 апреля 2011

Функции БД находятся за пределами моей зоны комфорта (я знаю, я знаю), и я не хотел даже вносить временные изменения в рассматриваемые столбцы, поэтому я просто сделал

CREATE TABLE CTable AS ... [expression that depends on BTAble] ...;

и использовал это для последовательного удаления данных в B и A.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...