如何“深度复制”行

时间:2019-03-11 08:37:46

标签: sql postgresql

我的问题类似于this one,但涉及更多。假设我有一个ID为A的表idA和另一个具有B和外键idB的表idA。我想复制A的所有条目,包括B中的相应条目。例如,如果我在开始时有以下表格:

A
|---|
|idA|
|---|
| 1 |
| 2 |
| 3 |
|---|

B
|---|---|
|idB|idA|
|---|---|
| 1 | 1 |
| 2 | 1 |
| 3 | 2 |
|---|---|

那么结果应该是:

A
|---|
|idA|
|---|
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
|---|

B
|---|---|
|idB|idA|
|---|---|
| 1 | 1 |
| 2 | 1 |
| 3 | 2 |
| 4 | 4 |
| 5 | 4 |
| 6 | 5 |
|---|---|

1 个答案:

答案 0 :(得分:0)

我有一种方法可以等同于戈登·利诺夫(Gordon Linoff)的建议,如果您能指出任何缺陷,我将不胜感激!

让我们设置表格:

CREATE TABLE A(
    idA SERIAL PRIMARY KEY, 
    txt varchar);

INSERT INTO A(txt)
VALUES ('A1'), ('A2'),('A3');

CREATE TABLE B(
    idB SERIAL PRIMARY KEY, 
    idA int REFERENCES A(idA), 
    txt varchar);

INSERT INTO B(idA, txt)
VALUES (1, 'A1.B1'), (1, 'A1.B2'), (2, 'A2.B1');

因此初始数据如下:

SELECT * FROM (A LEFT JOIN B ON A.idA=B.idA) ORDER BY A.idA, B.idB;


 ida | txt | idb | ida |  txt  
-----+-----+-----+-----+-------
   1 | A1  |   1 |   1 | A1.B1
   1 | A1  |   2 |   1 | A1.B2
   2 | A2  |   3 |   2 | A2.B1
   3 | A3  |     |     | 
(4 rows)

现在,我们可以使用NEXTVAL函数直接生成映射:

CREATE TEMP TABLE tmp_A_new AS (
    SELECT *, NEXTVAL('A_idA_seq') as newidA 
    FROM A ORDER BY idA -- order probably not needed
);
INSERT INTO A(idA, txt) (SELECT newidA, txt FROM tmp_A_new);

CREATE TEMP TABLE tmp_B_new AS (
    SELECT B.idB, newidA, B.txt, NEXTVAL('B_idB_seq') as newidB 
    FROM B, tmp_A_new WHERE B.idA=tmp_A_new.idA ORDER BY idB 
);
INSERT INTO B(idB, idA, txt) (SELECT newidB, newidA, txt FROM tmp_B_new);

结果看起来正确:

SELECT * FROM (A LEFT JOIN B ON A.idA=B.idA) ORDER BY A.idA, B.idB;


 ida | txt | idb | ida |  txt  
-----+-----+-----+-----+-------
   1 | A1  |   1 |   1 | A1.B1
   1 | A1  |   2 |   1 | A1.B2
   2 | A2  |   3 |   2 | A2.B1
   3 | A3  |     |     | 
   4 | A1  |   4 |   4 | A1.B1
   4 | A1  |   5 |   4 | A1.B2
   5 | A2  |   6 |   5 | A2.B1
   6 | A3  |     |     | 
(8 rows)

请注意,此操作可以继续扩展到C,D等。

任何评论我都会很高兴:)