使用外键约束从SQL脚本还原DB

时间:2011-11-01 17:03:52

标签: mysql sql postgresql pgadmin

我正在尝试使用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多个Sequence插入语句会有点痛苦。所以,我在这里很懒,但是有更简单的方法来处理序列吗?

或者,你们有什么建议可以使用不同的工具来使这更容易吗?

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

2 个答案:

答案 0 :(得分:2)

很明显,外键实际上并没有在MySQL中实施(可能是因为使用了MyISAM),或者生成的SQL只是以错误的顺序执行。

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

  1. 编辑生成的脚本,并将所有FK定义移动到脚本的末尾
  2. 编辑每个FK约束的定义,并将它们全部设置为initially deferred。然后将脚本作为单个事务运行,仅在最后一次提交时运行。
  3. 修改(因为这太过于无法作为评论)了

    使用SET CONSTRAINTS ALL DEFERRED仅在使用选项DEFERRABLE创建约束时才有效。

    要在一次交易中运行所有内容,您必须确保已关闭自动提交。然后只需运行INSERT,最后发出一个COMMIT。只有在您自动提交时,;才会提交。

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

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

答案 1 :(得分:2)

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

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

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

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

我会尝试为PostgreSQL找到一个数据导入工具 - 我住在SQL服务器世界里,我会使用SSIS,但你需要相当于PostgreSQL世界的SSIS。