У меня есть стол upload_temp как следует:
CREATE TABLE upload_temp (
codigo serial PRIMARY KEY NOT NULL,
codigo_upload_temp_pai INTEGER,
nome TEXT NOT NULL,
codigo_extensao INTEGER,
data_inclusao TIMESTAMP NOT NULL DEFAULT NOW(),
codigo_usuario_inclusao INTEGER NOT NULL,
CONSTRAINT fk_upload_upload_pai FOREIGN KEY (codigo_upload_temp_pai) REFERENCES upload_temp (codigo) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT fk_extensao_upload FOREIGN KEY (codigo_extensao) REFERENCES extensao (codigo) MATCH SIMPLE ON UPDATE CASCADE ON DELETE NO ACTION,
CONSTRAINT fk_usuario_upload FOREIGN KEY (codigo_usuario_inclusao) REFERENCES usuario (chave) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT uq_upload UNIQUE('nome', COALESCE('codigo_extensao', -1), COALESCE('codigo_upload_temp_pai', -1), 'codigo_usuario_inclusao', DATE(data_inclusao))
);
В этой таблице хранятся все временные загрузки моей системы, и эти загрузки могут быть папки а также файлы. Функция самостоятельной ссылки в таблице обрабатывает это. Но дело в том, что когда какой-либо файл регистрируется в системе, он становится официальным цифровым файлом, и upload_temp удален Когда он удаляется, его родительская папка должна удаляться, только если она становится пустой папкой. Таким образом, мне нужно удалить все папки из этого дерева, если они опустеют, потеряв своего единственного ребенка. Следующая картинка содержит больше деталей:
Файл 5.jpg принадлежит папка 5, который принадлежит папка 4, и так далее. Если я выберу файл 5.jpg чтобы быть зарегистрированным в системе, он будет удален из upload_temp, который опустеет папка 5. Итак папка 5, будучи пустым, должен быть также удален, и то же самое произойдет со всеми родительскими папками в этом случае.
Хотя я использую PHP, мне нужно решение в PostgreSQL, направленное на повышение производительности. Я пытаюсь понять как WITH RECURSIVE
работает, но у меня трудности. Я написал следующий код, который должен рекурсивно удалять всех родителей, начиная с файла 5.jpg, игнорируя пустую функцию:
WITH RECURSIVE all_uploads (codigo, parent, ext, main) AS (
SELECT ut1.codigo, ut1.codigo_upload_temp_pai AS parent, ut1.codigo_extensao AS ext, ut1.codigo AS main
FROM upload_temp ut1
UNION ALL
SELECT ut2.codigo, ut2.codigo_upload_temp_pai AS parent, ut2.codigo_extensao AS ext, au.main
FROM upload_temp ut2
JOIN all_uploads au ON au.parent = ut2.codigo
)
DELETE FROM upload_temp WHERE codigo IN (SELECT codigo FROM all_uploads WHERE codigo = 486);
На следующем рисунке показан результат для SELECT * FROM upload_temp ORDER BY codigo
:
Ну, это не работает. Это только удаление одного файла. Что я могу сделать, чтобы решить это? Спасибо!
WITH RECURSIVE all_uploads (codigo, parent, ext, main) AS (
SELECT ut1.codigo, ut1.codigo_upload_temp_pai AS parent,
ut1.codigo_extensao AS ext, ut1.codigo AS main
FROM upload_temp ut1
WHERE ut1.codigo = 486
UNION ALL
SELECT ut2.codigo, ut2.codigo_upload_temp_pai AS parent,
ut2.codigo_extensao AS ext, au.main
FROM upload_temp ut2
JOIN all_uploads au ON au.parent = ut2.codigo
)
DELETE FROM upload_temp WHERE codigo IN (SELECT codigo FROM all_uploads);
Вы должны поместить начальную точку в начальный выбор (внутри с), ИЛИ вы должны каким-то образом создать псевдостолбец, который представляет вершину «дерева», это то же самое для каждой строки во всем этом дереве. Поместить «верх, где» в начальный выбор внутри с является более простым решением.
Других решений пока нет …