使用外键约束从 SQL 脚本恢复数据库
我正在尝试使用 SQL 脚本恢复数据库,但是外键约束妨碍了
我获取 MySQL 数据库并将其转移到 PostgreSQL。 由于 MySQL 创建表语法最终非常不同,因此我采用了另一个具有相同架构但数据不同的 PostgreSQL 数据库,并仅从中恢复了架构。 换句话说,我现在有一个包含表、约束、序列和所有这些内容的数据库,但里面没有数据。
所以,是时候恢复数据了。 我使用 phpMyAdmin(仅数据)作为 SQL 脚本备份 MySQL DB(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 多个序列插入语句有点痛苦。所以,我在这里很懒,但是还有更简单的方法来处理序列吗?
或者,你们对一套不同的工具有什么建议,可以让这件事变得更容易吗?
感谢您抽出时间,祝您有美好的一天。
I am trying to restore a DB using an SQL script, but things foreign key constraints get in the way
I am taking a MySQL DB and bringing it over to PostgreSQL.
Since the MySQL create table syntax ended up being quite different, I took another PostgreSQL DB with the same schema, but different data and restored the schema only, from that.
In other words, I now have a database with tables, constraints, sequences and all that shnaz but no data inside.
So, it's is time to restore data.
I take a backup of the MySQL DB with phpMyAdmin (data only) as an SQL script (pgAdmin does not seem to accept zip or gzip files for some reason) and run the SQL script.
Now, this is where the problems start to happen, it's only natural, I am going from MySQL to PostgreSQL, so syntax errors are bound to happen.
But, there are other non syntax related problems to, like this one:
ERROR: insert or update on table "_account" violates foreign key constraint "fk_1_account"
DETAIL: Key (accountid)=(2) is not present in table "_entity".
So, yeah, basically, a foreign constraint exists, the query is trying to insert data into the _account
table, but the corresponding data has not been inserted into the _entity
table yet.
How do I get around that? Is there a way to make pgAdmin3/PostgreSQL disable ALL OF the constraints, insert the data, and then re-enable the constraints?
A syntax related error I encountered, was this one:
INSERT INTO _accounttype_seq (id) VALUES (11);
The PostgreSQL equivalent of that statement (if I am correct) is
ALTER SEQUENCE _accounttype_seq INCREMENT BY 11;
But, it's a bit of a pain to run through the whole script and change all 200+ Sequence insert statements. So, I am being lazy here, but is there an easier way to deal with the sequences as well?
Or, do you guys have any suggestions for a different set of tools to make this easier?
Thanks for your time, have a good day.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不要试图绕过外键约束。这是确保数据不良的方法。
首先查看约束并确保以正确的顺序插入到表中。如果 _entity 是“_account”的父级,那么应该首先填充它。
接下来,您需要让脚本将任何失败的记录移动到异常表中。然后您可以查看它们并了解数据完整性问题是什么,以及是否需要永久丢弃记录或尝试找出丢失的父值应该是什么,如果它是关键数据,例如客户不再存在的订单(可能在任何开始时没有正确的 fks 的系统中)。必须保留记录并且无法确定什么父值应该是,您可以在客户表中创建“未知”记录并将所有不良订单分配给该客户 ID。
手动更改更改序列即使很无聊,也不会花很长时间。在这种类型的转换中,您还需要手动处理很多其他事情。
我会尝试为 PostgreSQL 找到一个数据导入工具 - 我生活在 SQL Server 世界中,我会使用 SSIS,但在 PostgreSQL 世界中你需要相当于 SSIS 的工具。
Do not try to get around the foreign key constraints. That is the way to make sure the data is bad.
First look at the constraints and make sure you are inserting to the tables in the correct order. If _entity is parent of "_account, then it should be populated first.
Next you need to have the script move any failing records to an exception table. Then you can look at them and see what the data integrity issues is and if you need to throw the records away permanently or try to figure out what the missing parent value should be. If it is critical data such as orders where the customer no longer exists (possible in any system that didn't have correct fks to begin with) and you must keep the record and cannot determine what the parent value should have been, you can create an 'Unknown" record in the customer table and assign all bad orders to that customer id.
And manually changing the alter sequences shouldn't take long even if it is boring. There wil be plently of other things you need to handle manually in a conversion of this type.
I would try to find a data import tool for PostgreSQL - I live in SQL server world where I would use SSIS but you need the equivalent of SSIS for the PostgreSQL world.
显然,外键实际上并未在 MySQL 中强制执行(可能是因为使用 MyISAM),或者生成的 SQL 只是以错误的顺序执行。
如果“只是”顺序错误,我看到两种可能的解决方案:
初始延迟.然后将脚本作为单个事务运行,最后仅进行提交。
编辑(因为这太多了,无法作为注释)
仅当使用选项
创建约束时,使用
。SET CONSTRAINTS ALL DEFERRED
才有效>可延期要在一个事务中运行所有内容,您必须确保已关闭自动提交。然后只需运行
INSERT
并在最后发出COMMIT
。仅当您启用了自动提交时,;
才会提交。如果您想独立于自动提交设置,请使用
[BEGIN][1]
启动脚本,并确保最后只有一个 COMMIT。Aparently the foreign keys weren't actually enforced in MySQL (maybe because of using MyISAM) or the generated SQL just does it in the wrong order.
If it's "only" the wrong order, I see two possible solutions:
initially deferred
. Then run the script as one single transaction with only on commit at the very end.Edit (because this is too much to be put as a comment)
Using
SET CONSTRAINTS ALL DEFERRED
will only work if the constraints have been created with the optionDEFERRABLE
.To run everything in one single transaction, you have to make sure you have turned autocommit off. Then simply run the
INSERT
s and at the very end issue aCOMMIT
. A;
will only commit if you have autocommit on.If you want to be independent of the autocommit setting, then start your script with
[BEGIN][1]
and make sure there is only a single COMMIT at the very end.