Mysql 使用n:m关系复制数据集

Mysql 使用n:m关系复制数据集,mysql,sql,postgresql,insert,many-to-many,Mysql,Sql,Postgresql,Insert,Many To Many,我想使用单个SQL语句 insert into T (...) select ... from T where ... 复制大量数据集。我的问题是,从表T到其他表存在N:M关系,这些关系也必须复制。如果我不知道哪个原始数据集属于哪个复制的数据集,我该怎么做?让我举例说明 之前数据库的内容: 表T: ID | COL1 | COL2 ----------------- 1 | A | B 2 | C | D ID | COL1 | COL2 ----------

我想使用单个SQL语句

insert into T (...) select ... from T where ...
复制大量数据集。我的问题是,从表
T
到其他表存在N:M关系,这些关系也必须复制。如果我不知道哪个原始数据集属于哪个复制的数据集,我该怎么做?让我举例说明

之前数据库的内容: 表
T

ID  | COL1 | COL2    
-----------------
1   | A    | B
2   | C    | D
ID  | COL1 | COL2
-----------------
1   | A    | B
2   | C    | D
3   | A    | B
4   | C    | D
N:M-表参考了表T中的表U(未显示表U):

我的复制操作,其中[???]是我不知道的部分:

insert into T (COL1, COL2) select COL1, COL2 from T
insert into NM (T, U) select [???]
数据库的内容在以下时间之后: 表
T

ID  | COL1 | COL2    
-----------------
1   | A    | B
2   | C    | D
ID  | COL1 | COL2
-----------------
1   | A    | B
2   | C    | D
3   | A    | B
4   | C    | D
N:M-表:

T   | U
---------
1   | 100
1   | 101
2   | 100
2   | 102
3   | 100
3   | 101
4   | 100
4   | 102
注意:

  • 我有数千个数据集(不仅仅是两个)
  • 我想使用“插入…”。。。选择“以获得更好的性能”
第1步。锁定(两个)表或确保只有此脚本正在运行。禁用FK检查

第二步。按以下顺序使用这两条
INSERT
语句:

INSERT INTO NM 
    (T, U) 
  SELECT 
      T + maxID, U
  FROM 
      NM
    CROSS JOIN
      ( SELECT MAX(ID) AS maxID 
        FROM T
      ) AS m

INSERT INTO T 
    (ID, COL1, COL2) 
  SELECT 
      ID+maxID, COL1, COL2 
  FROM 
      T
    CROSS JOIN
      ( SELECT MAX(ID) AS maxID 
        FROM T
      ) AS m

第三步。重新启用FKs。

如果您有幸运行当前的PostgreSQL 9.1,则有一个优雅而快速的解决方案,只需使用新的

MySQL不支持,更不用说数据修改CTE了

假设
(col1,col2)
最初是唯一的:

问题1
  • 在这种情况下,您可以轻松地从表中拾取任意切片
  • t.id
    的序列号不会被浪费

如果
(col1,col2)
非唯一的,我会看到另外两种方法:

问题2
  • 使用使非唯一行唯一
  • INSERT
    t.id
    空间中插入不带孔的行,就像上面的查询一样

问题3
  • 这与@ypercu已经提供的想法相同,但都是在一个查询中提供的
  • 如果当前
    t.id
    的数字空间中存在漏洞,则相应地,新行的序列号将被烧掉
  • 不要忘记重置序列超过新的最大值,否则
    t
    中的新插入会出现重复的键错误,从而从序列中提取
    id
    的默认值。我将此作为最后一步集成到命令中。这样最快最安全

有关详细信息,请参阅手册

测试设置 进行快速测试

CREATE TEMP TABLE t (id serial primary key, col1 text, col2 text);
INSERT INTO t (col1, col2) VALUES 
 ('A', 'B')
,('C', 'D');

CREATE TEMP TABLE tu (t int, u int);
INSERT INTO tu VALUES
 (1, 100)
,(1, 101)
,(2, 100)
,(2, 102);

SELECT * FROM t;
SELECT * FROM tu;

有一个有点,我提供了一个有点类似的答案。加上没有CTE和窗口功能的版本8.3

我不理解这个问题,尤其是最后一句话。只要做任何你想要的
select
——根据需要连接多个表,这将生成一个结果表,并将其插入。就这样@托马斯,对不起,我不明白这个问题:(@Tomas:我想从一个表复制到同一个表中。这不应该是一个问题-我有一个相当大的问题,也不应该是一个问题。所以像通常那样准备
选择
子查询,然后试着把它放在insert语句下,不要担心。我已经添加了一个小例子,在你的“非常类似的问题”中,你编了一个新的日期。我想进行插入,但不知道插入的ID。并且不要忘记在之后重置序列列的顺序。
WITH s AS (
    SELECT max(id) AS max_id
    FROM   t
    )
    ,i AS (
    INSERT INTO t (id, col1, col2)
    SELECT id + s.max_id, col1, col2
    FROM   t, s
    )
    ,j AS (
    INSERT INTO tu (t, u)
    SELECT tu.t + s.max_id, tu.u
    FROM   tu, s
    )
SELECT setval('t_id_seq', s.max_id + s.max_id)
FROM   s;
CREATE TEMP TABLE t (id serial primary key, col1 text, col2 text);
INSERT INTO t (col1, col2) VALUES 
 ('A', 'B')
,('C', 'D');

CREATE TEMP TABLE tu (t int, u int);
INSERT INTO tu VALUES
 (1, 100)
,(1, 101)
,(2, 100)
,(2, 102);

SELECT * FROM t;
SELECT * FROM tu;