我有一个 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
的结果:
嗯,它没有用。它只删除一个文件。我该怎么做才能解决这个问题?谢谢!
答案 0 :(得分:0)
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);
你必须将起始点放在初始选择中(在with中)或者你必须以某种方式制作一个代表“树”顶部的伪列,这对于整个树中的每一行都是相同的。将初始选择中的“top where”放在with中是更容易的解决方案。