【问题标题】:DELETE recursive PostgreSQL respecting specific conditionsDELETE 递归 PostgreSQL 尊重特定条件
【发布时间】:2017-01-04 17:21:00
【问题描述】:

几天前,我问了一个关于使用 PostgreSQL 中的 WITH RECURSIVE 删除的问题。有:

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,则文件夹为空。通过使用自引用功能(文件夹和文件的相同数据库表),我通过检查codigo_extensao 字段(只有文件有扩展名)知道它是一个文件夹。

好吧,它不起作用,它只删除了我的 5.jpg。有什么提示吗?提前致谢!

【问题讨论】:

    标签: postgresql recursion sql-delete recursive-query multiple-conditions


    【解决方案1】:

    你不能像你想要的那样递归地删除。这里的逻辑是创建一个删除你想要的所有内容的查询,并递归运行它,直到有更多内容要删除。

    这是一个完全满足您需要的函数:

    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;
    

    哇!

    【讨论】:

      猜你喜欢
      • 2019-07-12
      • 2016-03-31
      • 2017-03-29
      • 2011-03-19
      • 2014-07-10
      • 2015-11-26
      • 2018-11-13
      • 2022-01-02
      • 1970-01-01
      相关资源
      最近更新 更多