I would like to use the single SQL-statement
insert into T (...) select ... from T where ...
to copy a lot of datasets. My problem is that there are N:M-relationships from table T
to other tables and these have to be copied too. How can I do this, if I do not know which original dataset belongs to which copied dataset? Let me demonstrate by example.
Content of the database before:
Table T
:
ID | COL1 | COL2
-----------------
1 | A | B
2 | C | D
N:M-table references table U from table T (table U is not shown):
T | U
---------
1 | 100
1 | 101
2 | 100
2 | 102
My copy operation where [???] is the part I do not know:
insert into T (COL1, COL2) select COL1, COL2 from T
insert into NM (T, U) select [???]
Content of the database after:
Table T
:
ID | COL1 | COL2
-----------------
1 | A | B
2 | C | D
3 | A | B
4 | C | D
N:M-table:
T | U
---------
1 | 100
1 | 101
2 | 100
2 | 102
3 | 100
3 | 101
4 | 100
4 | 102
Notice:
- I have thousands of datasets (not just two)
- I want to use 'insert ... select' to get a better performance
Step 1. Lock (both) tables or make sure that only this script is running. Disable FK checks.
Step 2. Use these two
INSERT
statements, in this order:Step 3. Re-enable FKs.
If you are lucky enough to run the current PostgreSQL 9.1, there is an elegant and fast solution with a single command using the new data-modifying CTEs.
No such luck with MySQL which does not support Common Table Expressions (CTE), not to mention data-modifying CTE.
Assuming
(col1, col2)
is initially unique:Query 1
t.id
will be wasted.If
(col1, col2)
is not unique, I see two other ways:Query 2
row_number()
to make non-unique rows unique.INSERT
rows without holes in thet.id
space just like in the query above.Query 3
t.id
, sequence numbers will be burnt for the new rows accordingly.t
that draw the default forid
from the sequence. I integrated this as final step into the command. Fastest & safest this way.Details about setval() in the manual.
Test setup
For a quick test.
There was a somewhat similar question recently, where I provided a somewhat similar answer. Plus alternatives for version 8.3 without CTEs and window functions.