复制关系表数据

Posted

技术标签:

【中文标题】复制关系表数据【英文标题】:Copying Relational Table Data 【发布时间】:2011-03-16 00:36:27 【问题描述】:

我希望我在这个问题上不会太啰嗦,我只是想确保我所问的内容完全清楚(我认为这很令人困惑:)。

我有一个包含一堆表的数据库,其中设置了我所有的外键约束。关系有时是几个表的深度,也有一个子表与多个父表相关的情况。我想插入我的“***”表行之一的副本,以及与之相关的所有子表数据(保持关系完整性)。也就是说我的新顶层行获得了自己的新主键(通过auto_increment),所有新的子行都获得了自己的主键(再次通过auto_increment),表的所有外键信息都与我复制的数据(现在才使用新创建的主键)。所以现在我将拥有一份与原始数据独立可变的关系数据的副本。

为了使我的示例更加具体,我煞费苦心地设置了一个类似但更简单的示例。让我们定义以下表格:

alt text http://www.freeimagehosting.net/uploads/ef22070a89.png

所有绿色的 id 字段都是 auto_update 主键,而黄色的是带有外键约束的索引列。假设数据库最初包含以下数据:

job_types
+----+----------+
| id | jobcode  |
+----+----------+
|  1 | DEADBEEF |
|  3 | FEEDFACE |
+----+----------+

managers
+----+---------------+-------------+
| id | name          | job_type_id |
+----+---------------+-------------+
|  1 | John          |           1 |
|  3 | Michael Scott |           3 |
+----+---------------+-------------+

departments
+----+------+------------+
| id | name | manager_id |
+----+------+------------+
|  1 | H32  |          1 |
|  2 | X11  |          3 |
+----+------+------------+

employees
+----+-------------+---------------+------------+-------------+
| id | name        | department_id | manager_id | job_type_id |
+----+-------------+---------------+------------+-------------+
|  1 | Billy Bob   |             1 |          1 |           1 |
|  2 | Sandra Lee  |             1 |          1 |           3 |
|  3 | Buddy Holly |             2 |          3 |           1 |
+----+-------------+---------------+------------+-------------+

现在说我想做的是制作部门 H32 (id=1) 的关系副本。

我应该得到如下结果(显然主键的实际值并不重要,参照完整性才是)。

job_types
+----+----------+
| id | jobcode  |
+----+----------+
|  1 | DEADBEEF |
|  3 | FEEDFACE |
|  4 | DEADBEEF |
|  5 | FEEDFACE |
+----+----------+

managers
+----+---------------+-------------+
| id | name          | job_type_id |
+----+---------------+-------------+
|  1 | John          |           1 |
|  3 | Michael Scott |           3 |
|  4 | John          |           4 |
+----+---------------+-------------+

departments
+----+------+------------+
| id | name | manager_id |
+----+------+------------+
|  1 | H32  |          1 |
|  2 | X11  |          3 |
|  3 | H32  |          4 |
+----+------+------------+

employees
+----+-------------+---------------+------------+-------------+
| id | name        | department_id | manager_id | job_type_id |
+----+-------------+---------------+------------+-------------+
|  1 | Billy Bob   |             1 |          1 |           1 |
|  2 | Sandra Lee  |             1 |          1 |           3 |
|  3 | Buddy Holly |             2 |          3 |           1 |
|  4 | Billy Bob   |             3 |          4 |           4 |
|  5 | Sandra Lee  |             3 |          4 |           5 |
+----+-------------+---------------+------------+-------------+

实现此类复制操作的最有效执行方式是什么?值得我在 Grails 的上下文中使用 InnoDB 表引擎使用 mysql。我期待听到一些关于您如何以“正确方式”执行此类操作的好主意。

-- 问候,维克

我已经在 PasteBin 上发布了 a MySQLDump of the example 初始化。

编辑 对于它的价值,我发布了一个更简单/更广泛的问题here,我得到了普遍积极的回应,这表明我不是“只是做错了”......

【问题讨论】:

如果我可以问,您复制整个表格图表的动机是什么?你的问题是让数据异常警报在我脑海中响起。 @proflux,假设您有一个具有关系模型的系统。如果部门是关系结构的根,我想创建一个新部门,它绝对是部门的一个单独实例,但在我的示例中具有与部门 H32 相同的初始结构,在我看来,深层副本是方法来做到这一点。它仍然正常化,但我现在可以在不影响原件的情况下随意更改副本......为什么这对你来说似乎很奇怪?如果我的想法是错误的,我应该如何以不同的方式思考它? @Mark,我认为一组表要么被规范化,要么没有被规范化......在结构存在后你不能做一些事情来“非规范化”数据库...... @vic - 我不知道 grails 在执行克隆/深拷贝方面为您提供的任何灵丹妙药。您基本上被困在自己用 Groovy 或 SQL 编写深拷贝逻辑;根据您的应用,一个可能比另一个更好。 @prolux,你说得对,我的例子很糟糕;您的wiki示例更适合我的要求。我的问题的核心是,鉴于您需要对数据库进行深度复制,您如何有效地执行此操作以获得最佳性能?我人为的例子只是在可理解的上下文中回答的素材。我的真实案例太复杂了,无法描述,仅此而已...... 【参考方案1】:

我使用INSERT INTO ... SELECT 语法做了类似的事情。 (C api 也有一个 MYSQL_OPTION_MULTI_STATEMENTS_ON ,您可以使用它来运行多个语句。或者您可以使用一个过程)。

这是最有效的,因为您不必在客户端和服务器之间移动数据。复制的值是创建新实体的模板。我不明白你为什么用这个特殊的数据模型来做这个。

【讨论】:

以上是关于复制关系表数据的主要内容,如果未能解决你的问题,请参考以下文章

如果我使用双引号在 SQL 数据库表中插入字符串,这有啥关系? [复制]

数据库之表关系

MySQL的学习之旅

查询或合并一对多关系而不复制结果条目

关系型数据库关联系统MySQL!

BigQuery 表的扁平数据并将扁平数据复制到新的 BigQuery 表