2012-01-31 54 views
1

我有2個表:PostgreSQL的 - 更新樹表,通過改變ID從同一個表中的行andparent_id

\d folder

       Table "public.folder" 
Column |   Type   |      Modifiers      
---------+-----------------------+---------------------------------------------------- 
id  | integer    | not null default nextval('folder_id_seq'::regclass) 
name  | character varying(20) | 
parent_id | integer    | 

Indexes: 
    "folder_pkey" PRIMARY KEY, btree (id) 

Foreign-key constraints: 
    "fk_folder_1" FOREIGN KEY (parent_id) REFERENCES folder(id) 

Referenced by: 
    TABLE "files" CONSTRAINT "fk_files_1" FOREIGN KEY (folder_id) REFERENCES folder(id) 
    TABLE "folder" CONSTRAINT "fk_folder_1" FOREIGN KEY (parent_id) REFERENCES folder(id) 

\d files

       Table "public.files" 
Column |   Type   |      Modifiers      
----------+-----------------------+--------------------------------------------------- 
id  | integer    | not null default nextval('files_id_seq'::regclass) 
name  | character varying(20) | 
folder_id | integer    | 

Indexes: 
    "files_pkey" PRIMARY KEY, btree (id) 

Foreign-key constraints: 
    "fk_files_1" FOREIGN KEY (folder_id) REFERENCES folder(id) 


select * from folder; 
id | name | parent_id 
----+---------+----------- 
    1 | home |   
    2 | folder2 |   1 
    3 | folder3 |   1 
    4 | folder4 |   2 
    5 | folder5 |   4 
    6 | folder6 |   5 

(6 rows) 



select * from files; 
id | name | folder_id 
----+-------+----------- 
    1 | file1 |   4 
    2 | file2 |   4 
    3 | file3 |   5 
    4 | file4 |   6 
    5 | file5 |   6 
    6 | file6 |   2 
(6 rows) 

現在我需要一個函數或光標或任何會得到兩個輸入的東西,要複製的文件夾和要複製的目標文件夾,函數應該將文件夾及其子文件夾複製到具有新ID的同一個表中和父母的ID如下,同時當文件夾被複制並插入文件表中的文件也插入,plz幫助我得到下面的結果..

如果我正在應對folder5到folder3我的輸出應該是像這樣的:

select * from folder; 
id | name | parent_id 
----+---------+----------- 
    1 | home |   
    2 | folder2 |   1 
    3 | folder3 |   1 
    4 | folder4 |   2 
    5 | folder5 |   4 
    6 | folder6 |   5 
    7 | folder5 |   3 
    8 | folder6 |   7 
(8 rows) 

和文件表也當文件夾複製並插入這樣被更新:

select * from files; 
id | name | folder_id 
----+-------+----------- 
    1 | file1 |   4 
    2 | file2 |   4 
    3 | file3 |   5 
    4 | file4 |   6 
    5 | file5 |   6 
    6 | file6 |   2 
    7 | file3 |   7 
    8 | file4 |   8 
    9 | file5 |   8 
(9 rows) 

回答

0
CREATE OR REPLACE FUNCTION tree_copy(INTEGER,INTEGER) RETURNS VOID AS $$ 
DECLARE 
    a ALIAS FOR $1; --ROOT FOLDER TO BE COPIED 
    b ALIAS FOR $2; --DESTINATION FOLDER 
    i INTEGER; 
    j INTEGER; 
    g INTEGER; 
BEGIN 
--DROP TABLE IF EXISTS temp1; 

CREATE TEMPORARY TABLE temp1 AS(
WITH RECURSIVE CTE AS(
SELECT *, NEXTVAL('folder_id_seq') new_id FROM folder WHERE id = a 
UNION ALL 
SELECT folder.*,NEXTVAL('folder_id_seq') new_id FROM CTE 
JOIN folder ON CTE.id = folder.parent_id) 
SELECT C1.id, C1.new_id, C1.parent_id, 
C2.new_id new_parent_id FROM CTE C1 LEFT JOIN 
CTE C2 ON C1.parent_id = C2.id); 

FOR i IN (WITH RECURSIVE t AS(SELECT id, parent_id FROM folder WHERE id = a 
UNION SELECT f.id,f.parent_id FROM folder f, t AS t1 WHERE f.parent_id = t1.id) 
SELECT id FROM t) 
LOOP 
    SELECT new_parent_id INTO g FROM temp1 WHERE id = i; 

    INSERT INTO folder(id,name,parent_id)VALUES(
    (SELECT new_id FROM temp1 WHERE id = i), 
    (SELECT name FROM folder WHERE id = i),COALESCE(g,b)); 

    FOR j IN (SELECT id FROM files WHERE folder_id = i) 
    LOOP 
     INSERT INTO files(id,name,folder_id) VALUES (
     NEXTVAL('files_id_seq'),(SELECT name FROM files WHERE id = j), 
     (SELECT new_id FROM temp1 WHERE id = i)); 
    END LOOP; 
END LOOP; 
DROP TABLE temp1; 
END; 
$$ LANGUAGE PLPGSQL; 

這會做,因爲我以爲...

0

爲什麼不使用簡單的更新?

BEGIN; 
UPDATE folder 
SET parent_id = 3 
WHERE id  = 5; 

UPDATE files 
SET folder_id = 3 
WHERE folder_id = 5; 
END; 
+0

我需要一個函數來做到......這裏例如表有更少的數據,當表的增長,這將是不可能這樣做的手動,所以PLZ任何人都可以幫我一些功能PLZ – MAHI 2012-02-01 00:27:33

相關問題