【问题标题】:Restore DB from SQL script with Foreign Key Constraints使用外键约束从 SQL 脚本恢复数据库
【发布时间】:2011-11-01 17:03:51
【问题描述】:

我正在尝试使用 SQL 脚本恢复数据库,但外键约束妨碍了

我正在使用 MySQL 数据库并将其带到 PostgreSQL。 由于 MySQL 创建表的语法最终完全不同,因此我采用了另一个具有相同架构但数据不同的 PostgreSQL 数据库,并仅从中恢复了架构。 换句话说,我现在有一个包含表、约束、序列和所有这些 shnaz 的数据库,但里面没有数据。

所以,是时候恢复数据了。 我使用 phpMyAdmin(仅数据)备份 MySQL 数据库作为 SQL 脚本(由于某种原因,pgAdmin 似乎不接受 zip 或 gzip 文件)并运行 SQL 脚本。 现在,这就是问题开始发生的地方,这是很自然的,我从 MySQL 转到 PostgreSQL,所以肯定会发生语法错误。

但是,还有其他与语法无关的问题,比如这个:

ERROR: insert or update on table "_account" violates foreign key constraint "fk_1_account"
DETAIL:  Key (accountid)=(2) is not present in table "_entity".

所以,是的,基本上,外部约束存在,查询正在尝试将数据插入_account 表,但相应的数据尚未插入_entity 表。 我该如何解决?有没有办法让 pgAdmin3/PostgreSQL 禁用所有约束,插入数据,然后重新启用约束?

我遇到的一个与语法相关的错误,是这个:

 INSERT INTO _accounttype_seq (id) VALUES (11);

该语句的 PostgreSQL 等效项(如果我正确的话)是

 ALTER SEQUENCE _accounttype_seq INCREMENT BY 11; 

但是,运行整个脚本并更改所有 200 多个序列插入语句有点痛苦。所以,我在这里偷懒了,但是有没有更简单的方法来处理序列?

或者,你们对一组不同的工具有什么建议可以让这更容易吗?

感谢您的宝贵时间,祝您有美好的一天。

【问题讨论】:

标签: mysql sql postgresql pgadmin


【解决方案1】:

不要试图绕过外键约束。这是确保数据错误的方法。

首先查看约束并确保您以正确的顺序插入到表中。如果 _entity 是“_account”的父级,则应首先填充它。

接下来,您需要让脚本将所有失败的记录移至异常表。然后您可以查看它们并查看数据完整性问题是什么,以及是否需要永久丢弃记录或尝试找出丢失的父值应该是什么。如果它是关键数据,例如客户不再存在的订单(可能在任何没有正确 fks 开始的系统中)并且您必须保留记录并且无法确定父值应该是什么,您可以创建客户表中的“未知”记录,并将所有不良订单分配给该客户 ID。

即使很无聊,手动更改更改序列也不应该花很长时间。在这种类型的转换中,您还需要手动处理许多其他事情。

我会尝试为 PostgreSQL 找到一个数据导入工具 - 我生活在 SQL 服务器世界中,我会使用 SSIS,但对于 PostgreSQL 世界,您需要与 SSIS 等效的工具。

【讨论】:

  • 哈哈,谢谢,最后是的,我只是移动了桌子,让它们按顺序排列。
【解决方案2】:

显然,MySQL 中实际上并未强制执行外键(可能是因为使用了 MyISAM),或者生成的 SQL 只是以错误的顺序执行。

如果是“仅”错误的顺序,我看到了两种可能的解决方案:

  1. 编辑生成的脚本并将所有 FK 定义移到脚本末尾
  2. 编辑每个 FK 约束的定义并将它们全部设置为 initially deferred。然后将脚本作为单个事务运行,最后只在提交时运行。

编辑(因为这太多了,不能作为评论)

只有在使用DEFERRABLE 选项创建了约束时,才能使用SET CONSTRAINTS ALL DEFERRED

要在一个事务中运行所有内容,您必须确保已关闭自动提交。然后只需运行INSERTs 并在最后发出COMMIT; 仅在您启用自动提交时才会提交。

如果您想独立于自动提交设置,请使用 [BEGIN][1] 开始您的脚本,并确保最后只有一个 COMMIT。

BEGIN DEFERRABLE
   INSERT INTO table_one ... ;
   INSERT INTO table_two ... ; 
   .....
COMMIT;

【讨论】:

  • 约束定义不是我正在运行的查询的一部分。表和约束已经创建。根据 Abhay 的建议,我尝试在开头添加以下行来运行查询:SET CONSTRAINTS ALL DEFERRED; 但它不起作用,我认为这是因为有很多提交。假设每次您以; 结束查询时,我是否正确,然后查询已提交?如果是,我怎么能只在最后提交?感谢您的回复。
  • 非常感谢您的帮助,但不幸的是,我不认为使用 deferable 选项创建了约束,所以我只是继续并改变了插入顺序。
猜你喜欢
  • 1970-01-01
  • 2012-08-15
  • 2013-12-17
  • 1970-01-01
  • 2016-08-09
  • 1970-01-01
  • 2018-01-23
  • 1970-01-01
  • 2013-01-30
相关资源
最近更新 更多