1

我有很多最初来自 MySQL 的记录。我对数据进行了按摩,以便使用 ActiveRecord 将其成功插入 PostgreSQL。这我可以很容易地在行的基础上进行插入,即一次一行。这很慢我想做批量插入,但如果任何行包含无效数据,这将失败。无论如何我可以实现批量插入并且只有无效行失败而不是整个批量?

4

2 回答 2

1

复制

当使用 SQLCOPY进行批量插入(或\copy在 psql 客户端中的等效项)时,不能选择失败COPY不能跳过非法行。您必须将输入格式与您导入的表相匹配。

如果数据本身(不是装饰器)违反了您的表定义,但有一些方法可以让这种情况变得更加宽容。例如:创建一个包含所有类型列的临时登台表text。复制到它,然后在转换为实际数据类型并插入实际目标表之前使用 SQL 命令修复违规行。

考虑这个相关的答案:
How to bulk insert only new rows in PostreSQL

或者这种更高级的情况:
使用 PostgreSQL COPY 时的“错误:最后一个预期列之后的额外数据”

如果NULL有问题,请暂时从目标表中删除 NOT NULL 约束。在 COPY 之后修复行,然后恢复约束。或者,如果您暂时无法软化您的规则,请选择使用临时表的路线。
示例代码:

ALTER TABLE tbl ALTER COLUMN col DROP NOT NULL;
COPY ...
-- repair, like ..
-- UPDATE tbl SET col = 0 WHERE col IS NULL;
ALTER TABLE tbl ALTER COLUMN col SET NOT NULL;

或者你只是修复源表。COPY 告诉您违规行的编号。使用您喜欢的编辑器并修复它,然后重试。我喜欢用vim它。

INSERT

对于INSERT(如评论)值的检查NULL是微不足道的:

要跳过具有NULL值的行:

INSERT INTO (col1, ...
SELECT col1, ...
WHERE col1 IS NOT NULL

插入某事。else 而不是一个NULL值(在我的示例中为空字符串):

INSERT INTO (col1, ...
SELECT COALESCE(col1, ''),  ...
于 2013-06-07T17:15:16.847 回答
0

一个常见的解决方法是将数据导入到一个TEMPORARYUNLOGGED没有约束的表中,并且输入中的数据是足够虚假的text类型列。

然后,您可以INSERT INTO ... SELECT对数据进行查询,以使用在导入期间清理数据的大查询来填充真实表。您可以为此使用很多CASE语句。这个想法是一次性转换数据。

当您读入数据时,您可能可以在 Ruby 中进行许多修复,然后使用COPY ... FROM STDIN. 这可以通过 Ruby 的Pggem 实现,参见例如https://bitbucket.org/ged/ruby-pg/src/tip/sample/copyfrom.rb

对于更复杂的情况,请查看 Pentaho Kettle 或 Talend Studio ETL 工具。

于 2013-06-08T02:54:25.510 回答