DELETE 递归 PostgreSQL 尊重特定条件
DELETE recursive PostgreSQL respecting specific conditions
几天前,我问了一个关于从 PostgreSQL 中删除 using WITH RECURSIVE
的问题。有:
效果很好:最初的目的是递归删除父文件夹,只要最后一个子文件夹被删除。下图更好地描述了它:
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 考虑到自我关系。如果SELECT ut3.codigo FROM upload_temp ut3 WHERE ut3.codigo_upload_temp_pai = ut2.codigo LIMIT 1) IS NULL
returns true,那么文件夹是空的。通过使用自引用功能(文件夹和文件相同的数据库 table),我通过检查 codigo_extensao
字段知道它是一个文件夹(只有文件有扩展名)。
好吧,它不起作用,它只删除了我的 5.jpg。有什么提示吗?提前致谢!
您不能随心所欲地递归删除。这里的逻辑是创建一个查询来删除你想要的所有内容,然后 运行 它递归地直到有更多要删除的内容。
这是一个完全满足您需要的函数:
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;
再见!
几天前,我问了一个关于从 PostgreSQL 中删除 using WITH RECURSIVE
的问题。有:
效果很好:最初的目的是递归删除父文件夹,只要最后一个子文件夹被删除。下图更好地描述了它:
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 考虑到自我关系。如果SELECT ut3.codigo FROM upload_temp ut3 WHERE ut3.codigo_upload_temp_pai = ut2.codigo LIMIT 1) IS NULL
returns true,那么文件夹是空的。通过使用自引用功能(文件夹和文件相同的数据库 table),我通过检查 codigo_extensao
字段知道它是一个文件夹(只有文件有扩展名)。
好吧,它不起作用,它只删除了我的 5.jpg。有什么提示吗?提前致谢!
您不能随心所欲地递归删除。这里的逻辑是创建一个查询来删除你想要的所有内容,然后 运行 它递归地直到有更多要删除的内容。
这是一个完全满足您需要的函数:
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;
再见!