Postgres 在 SQL Server BCP 文件的最后一个预期列之后复制错误额外数据

Posted

技术标签:

【中文标题】Postgres 在 SQL Server BCP 文件的最后一个预期列之后复制错误额外数据【英文标题】:Postgres copy error extra data after last expected column from SQL Server BCP file 【发布时间】:2019-06-15 06:47:09 【问题描述】:

我正在将数据库从 Windows 上托管的 SQL Server 2016 迁移到 Debian 上托管的 Postgres 11。

我使用 BCP 实用程序从 SQL Server 2016 导出数据,并使用 COPY 命令将其导入 Postgres 11。

对于很多表它都有效,但对于某些表,即使我的文件包含相同数量的列,我也会不断收到“最后一个预期列之后的额外数据”错误。 COPY 命令似乎对包含空字符串的行有问题,在 Notepad++ 中显示为“NUL”。 这是我在 SQL Server 中的表的定义。 (表名和列名已更改)

Create table test (
    TypeId  int not null,
    Name    nvarchar(50) not null,
    License nvarchar(50) not null,
    LastChanged timestamp not null,
    Id1 uniqueidentifier not null,
    Id2 uniqueidentifier not null,
    DescriptionCol  nvarchar(256) not null default '',
    ConditionCol    bit not null default 0,
    ConditionCol2   bit not null default 0,
    ConditionCol3   bit not null default 1,
    DescriptionCol2 nvarchar (2) not null default ''
)

这是 Postgres 中的表定义。

CREATE TABLE test (
    typeid integer NOT NULL,
    name citext COLLATE pg_catalog."default" NOT NULL,
    license citext COLLATE pg_catalog."default" NOT NULL,
    lastchanged bytea NOT NULL,
    id1 uuid NOT NULL,
    id2 uuid NOT NULL DEFAULT uuid_generate_v4(),
    descriptioncol text COLLATE pg_catalog."default" NOT NULL DEFAULT ''::text,
    conditioncol boolean NOT NULL DEFAULT false,
    conditioncol2 boolean NOT NULL DEFAULT false,
    conditioncol3 boolean NOT NULL DEFAULT true,
    descriptioncol2 text COLLATE pg_catalog."default" NOT NULL
)

我是这样提取数据的:

bcp Database.Schema.test out E:\MyFile.dat -S ServerName -U User -P Password -a65535 -c -C 65001

然后我连接到远程 Postgres 服务器并以这种方式导入数据:

\copy Schema.test FROM 'E:\MyFile.dat' (DELIMITER E'\t', FORMAT CSV, NULL '', ENCODING 'UTF8');`

现在如果我打开在 Notepad++ 中生成的文件,我会看到“NUL”字符,这似乎是 COPY 命令无法处理的问题。

如果我尝试将一些数据放在第一行的“NUL”字符中,那么复制命令会在第三行而不是第一行上为我提供“最后一个预期列之后的额外数据”。我无法编辑文件并用其他内容替换“NUL”字符,因为我有数百个表要迁移到一些非常大的表。

我需要为 SQL Server BCP 实用程序或 Postgres COPY 命令指定一个选项才能使其工作。

【问题讨论】:

您可以考虑以这种方式使用 SSIS 吗?我 你可以试试 SQL Server FDW:fluca1978.github.io/2019/01/18/PostgreSQL-TDS-FDW.html 你能从“descriptioncol”中去掉非空约束,然后再试一次,而不对 BCP 输出做任何事情吗?我认为这会奏效。此外,这没关系,但由于您声明了分隔符,CSV 格式可能不会做任何事情。 bcp utility documentation 有以下语句:“在提取数据时,请注意 bcp 实用程序将空字符串表示为空字符串,将空字符串表示为空字符串。” (什么?)。您可能应该从文件中删除所有字节 0。我认为用tr -d '\0' 过滤就足够了。 “tr”程序可在任何 Linux 上使用,并且可能“Git for Windows”包含它。 @Simonare 我还没有使用 SSIS,我今天早上尝试过,它以正确的格式导出了文件。我仍然需要测试,但我想也许我会以这种方式而不是 BCP 来提取数据 【参考方案1】:

正如@Tometzky所说,

bcp 实用程序将空字符串表示为空字符串,将空字符串表示为空字符串。

这解释了不良行为的原因。

作为bcp 的替代方案,您可以考虑使用ssis(Microsoft SQL Server 集成服务)来实现这种方式。它易于使用,并且在 DBMS 系统之间具有广泛的兼容性。

【讨论】:

您是否曾经以编程方式生成 SSIS 以将整个数据库提取到 C# 中的平面文件中?否则我将不得不一张一张地手动生成所有 SSIS 包。我今天尝试了一些东西,但没有任何效果。

以上是关于Postgres 在 SQL Server BCP 文件的最后一个预期列之后复制错误额外数据的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 2005 使用 bcp 写入文件

SQL Server批量数据导出导入BCP使用

安装 BCP 而不在客户端计算机上安装 SQL Server?

sql server的bcp指令

SQL SERVER 命令 bcp

SQL SERVER BCP的用法