Postgresql удаляет значения из внешнего ключа, который имеет циклическую ссылку, а также ссылки в первичной таблице - PullRequest
0 голосов
/ 12 декабря 2018

Существует 2 таблицы:

, первая из них Таблица отца

create table win_folder_principal(
    id_folder_principal serial primary key not null,
    folder_name varchar(300)not null
);

и таблица с циклической ссылкой

create table win_folder_dependency(
    id_folder_dependency serial primary key not null,
    id_folder_father int not null,
    id_folder_son int not null,
    foreign key(id_folder_father)references win_folder_principal(id_folder_principal),
    foreign key(id_folder_son)references win_folder_principal(id_folder_principal)
);

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

**WIN_FOLDER_PRINCIPAL**
 | Id | Folder_Name|
 | 23 | new2       | 
 | 24 | new3       |
 | 13 | new0       |
 | 22 | new1       |
 | 12 | nFol       |

И это значение хранится в Win_Folder_Dependency

**WIN_FOLDER_DEPENDENCY**
 | Id_Father | Id_Son |
 |     12    |  13    | 
 |     13    |  22    |
 |     22    |  23    |
 |     23    |  24    |

, и это запрос, который я использую, чтобы узнатьзначения в таблице зависимостей и принципалов.

SELECT m2.id_folder_principal AS "Principal",
         m.folder_name  AS "Dependency",
         m2.id_folder_principal AS id_principal,
         m.id_folder_principal  AS id_dependency
  FROM ((win_folder_dependency md
      JOIN win_folder_principal m ON ((m.id_folder_principal = md.id_folder_son)))
      JOIN win_folder_principal m2 ON ((m2.id_folder_principal = md.id_folder_father)))

Если я хочу удалить папку с Id_Principal 13 , мне нужно удалить другие отношения, существующие в Folder_Dependency таблицы, но также удалить значение из Folder_Principal

, есть ли способ добиться этого циклического удаления?

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

В этом блоке анонимного кода будут собраны все принципы, основанные на ID 13, который выполняет поиск по дереву зависимостей в параметре массива с именем l_Principles.Затем он удаляет все записи зависимостей, в которых содержатся отец или сын (или оба) в l_Principles, а затем удаляет все записи принципов, указанные в l_Principles:

DO $$DECLARE
l_principles int[];
BEGIN
with recursive t1(root, child, pinciples) as (
  select id_folder_father
       , id_folder_son
       , array[id_folder_father, id_folder_son]
    from win_folder_dependency
   where id_folder_father = 13
union all
  select root
       , id_folder_son
       , pinciples||id_folder_son
    from win_folder_dependency
    join t1
      on id_folder_father = child
     and not id_folder_son = any(pinciples) -- Avoid cycles
)
select max(pinciples) into l_principles from t1 group by root;

delete from win_folder_dependency
 where id_folder_father = any(l_principles)
    or id_folder_son = any(l_principles);

delete from win_folder_principal
 where id_folder_principal = any(l_principles);
end$$;
/

С предоставленными вами образцами данных конецВ результате в таблице win_folder_principal останется только одна запись, а в таблице win_folder_dependency нет записей.

0 голосов
/ 13 декабря 2018

Если вы хотите удалить запись из win_folder_principal, вы должны сначала удалить ссылки на нее в win_folder_dependency следующим образом:

delete from win_folder_dependency where 13 in (id_folder_father, id_folder_son);

, прежде чем удалить запись из win_folder_principal следующим образом:

delete from win_folder_principal where id_folder_principal = 13;

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

create table win_folder_dependency(
    id_folder_dependency serial primary key not null,
    id_folder_father int not null,
    id_folder_son int not null,
    foreign key(id_folder_father)references win_folder_principal(id_folder_principal) on delete cascade,
    foreign key(id_folder_son)references win_folder_principal(id_folder_principal) on delete cascade
);

Обратите внимание на директивы on delete cascade, тогда вы можете просто удалить из основной таблицы, и ссылки в таблице зависимостей будут удалены какхорошо.

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