0

Несколько дней назад я задал вопрос об удалении с помощью WITH RECURSIVE из PostgreSQL. Существует:DELETE рекурсивный PostgreSQL с учетом конкретных условий

DELETE recursive PostgreSQL

Это работает отлично: намерение, первоначально было удалить родительские папки рекурсивно до тех пор, как конечный ребенок был удален. Следующее изображение описывает его лучше:

Files tree view

Удалив файл 5.jpg всех родительские папки, в этой ситуации, будут удалены, а также.

Но теперь мне нужно удалить родительские папки , только если они пустуют, т. Е. Теряя единственный ребенок. Я попытался следующий:

WITH RECURSIVE all_uploads (codigo, parent, ext, uploader) AS (
    SELECT ut1.codigo, ut1.codigo_upload_temp_pai AS parent, ut1.codigo_extensao AS ext, ut1.codigo_usuario_inclusao AS uploader 
    FROM upload_temp ut1 
    WHERE ut1.codigo = 576 

    UNION ALL 

    SELECT ut2.codigo, ut2.codigo_upload_temp_pai AS parent, ut2.codigo_extensao AS ext, ut2.codigo_upload_temp_pai AS uploader 
    FROM upload_temp ut2 
    JOIN all_uploads au ON au.parent = ut2.codigo 
    WHERE (SELECT ut3.codigo FROM upload_temp ut3 WHERE ut3.codigo_upload_temp_pai = ut2.codigo LIMIT 1) IS NULL 
    AND ext IS NULL 
    AND uploader = 1535 
) 
DELETE FROM upload_temp WHERE codigo IN (SELECT codigo FROM all_uploads); 

Я думал, что единственный способ проверить, если папка пуста, чтобы выполнить суб-выбор с учетом отношения собственного. Если SELECT ut3.codigo FROM upload_temp ut3 WHERE ut3.codigo_upload_temp_pai = ut2.codigo LIMIT 1) IS NULL возвращает true, папка пуста. И используя функцию самореференции (та же таблица DB для папок и файлов), я знаю, что это папка, проверив поле codigo_extensao (только файлы имеют расширения).

Ну, это не работает, он удаляет только мои 5.jpg. Любой намек? Заранее спасибо!

ответ

0

Вы не можете УДАЛИТЬ рекурсивно, как хотите. Логика здесь заключается в создании запроса, который удаляет все, что вы хотите, и запускать его рекурсивно, пока не удастся удалить что-либо еще.

Вот функция, которая делает именно то, что вам нужно:

CREATE OR REPLACE FUNCTION p_remove_empty_folders(_codigo_usuario_ integer) RETURNS integer AS $$ 
DECLARE 
    AFFECTEDROWS integer; 
BEGIN 

    WITH a AS (
    DELETE FROM upload_temp WHERE codigo IN (SELECT ut1.codigo FROM upload_temp ut1 WHERE ut1.codigo_usuario_inclusao = _codigo_usuario_ AND ut1.codigo_extensao IS NULL AND NOT EXISTS (SELECT * FROM upload_temp ut2 WHERE ut2.codigo_upload_temp_pai = ut1.codigo)) 
    RETURNING 1 
    ) 
    SELECT count(*) INTO AFFECTEDROWS FROM a;  

    WHILE AFFECTEDROWS > 0 LOOP 

     WITH a AS (
     DELETE FROM upload_temp WHERE codigo IN (SELECT ut1.codigo FROM upload_temp ut1 WHERE ut1.codigo_usuario_inclusao = _codigo_usuario_ AND ut1.codigo_extensao IS NULL AND NOT EXISTS (SELECT * FROM upload_temp ut2 WHERE ut2.codigo_upload_temp_pai = ut1.codigo)) 
     RETURNING 1 
     ) 
     SELECT count(*) INTO AFFECTEDROWS FROM a; 

    END LOOP; 

    RETURN 0; 
END; 
$$ LANGUAGE plpgsql; 

Cya!

+0

awesome! благодаря! – Siipe