如何在将数据导出到CSV平面文件时修复嵌入的文本限定符问题?

62 sql-server ssis sql-server-2000 sql-server-2012

RFC 4180:

RFC 4180定义Common Format and MIME Type for Comma-Separated Values (CSV) Files.其中一个要求RFC 4180如下所述.这是#7RFC链接中的要点.

If double-quotes are used to enclose fields, then a double-quote
appearing inside a field must be escaped by preceding it with
another double quote.  For example:

"aaa","b""bb","ccc"
Run Code Online (Sandbox Code Playgroud)

SQL Server 2000:

DTS Export/Import WizardSQL Server 2000似乎符合上述标准,即使RFC 4180本身似乎一直只公布2005年10月.我使用下面提到的SQL Server 2000版本.

Microsoft SQL Server  2000 - 8.00.2039 (Intel X86) 
May  3 2005 23:18:38 
Copyright (c) 1988-2003 Microsoft Corporation
Standard Edition on Windows NT 5.0 (Build 2195: Service Pack 4)
Run Code Online (Sandbox Code Playgroud)

SQL Server 2012:

SQL Server Import and Export Wizardin SQL Server 2012根据RFC 4180中定义的标准,不会将数据从表导出到CSV文件.我使用的是下面提到的SQL Server 2012版本.

Microsoft SQL Server 2012 - 11.0.2316.0 (X64) 
Apr  6 2012 03:20:55 
Copyright (c) Microsoft Corporation
Enterprise Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1) (Hypervisor)
Run Code Online (Sandbox Code Playgroud)

问题模拟:

这是我在SQL Server 2000SQL Server 2012中运行的示例.我运行以下查询来创建一个表并插入几条记录.该ItemDesc列包含带双引号的数据.我的目的是使用内置的导出数据向导从这两个SQL Server版本导出数据,并比较生成的CSV文件.

CREATE TABLE dbo.ItemInformation(
    ItemId nvarchar(20) NOT NULL,
    ItemDesc nvarchar(100) NOT NULL
) 
GO

INSERT INTO dbo.ItemInformation (ItemId, ItemDesc) VALUES ('100338754', 'Crown Bolt 3/8"-16 x 1" Stainless-Steel Hex Bolt');
INSERT INTO dbo.ItemInformation (ItemId, ItemDesc) VALUES ('202255836', 'Simpson Strong-Tie 5/8" SSTB Anchot Bolt');
INSERT INTO dbo.ItemInformation (ItemId, ItemDesc) VALUES ('100171631', 'Grip-Rite #11 x 1-1/2" Electro-Galvanized Steel Roofing Nails');
INSERT INTO dbo.ItemInformation (ItemId, ItemDesc) VALUES ('202210289', 'Crown Bolt 1/2" x 3" "Zinc-Plated" Universal Clevis Pin');
INSERT INTO dbo.ItemInformation (ItemId, ItemDesc) VALUES ('100136988', 'Tapcon 3/16" x 1-3/4" Climaseal Steel "Flat-Head" Phillips Concrete Anchors (75-Pack)');
INSERT INTO dbo.ItemInformation (ItemId, ItemDesc) VALUES ('203722101', 'KwikTap 3/16" x 2-1/4" "Flat-Head" Concrete Screws (100-Pack)');
GO
Run Code Online (Sandbox Code Playgroud)

DTS Export/Import WizardSQL Server 2000,我用下面的设置,以将数据导出到CSV文件.我以名字保存了文件SQLServer2000_ItemInformation.csv.

DTS导出/导入向导

SQL Server Import and Export WizardSQL Server 2012,我用下面的设置,以将数据导出到CSV文件.我以名字保存了文件SQLServer2012_ItemInformation.csv.

SQL Server导入和导出向导 - 选择目标

SQL Server导入和导出向导 - 配置平面文件目标

以下是使用Beyond Compare的两个文件之间的比较.左侧包含生成的文件SQL Server 2000,右侧包含生成的文件SQL Server 2012.您可以注意到左侧文件SQL Server 2000包含其他双引号以补偿数据列中的嵌入式引号.这符合指定的标准,RFC 4180但从生成的文件中明显丢失SQL Server 2012

文件比较

在网上搜索:

我在网上搜索了这个bug,发现了以下链接.以下是Microsoft Connect上的错误报告.所有这些问题似乎与导入文件有关,但与导出数据无关.所有这些错误都被关闭了Fixed.

MSDN博客上的帖子下面说明SQL Server 2012中已经进行了更改 Flat file source supports embedded qualifiers and a variable number of columns per row

MSDN博客上的另一篇文章在该部分中说明了相同的内容Embedded Qualifiers.

我知道的解决方法:

我知道一个解决方法来解决这个问题,方法是编写一个查询,将"我的列数据中的所有双引号()替换为两个双引号(""),这样导出的文件最终会得到正确的嵌入式限定符数据.这样可以避免直接从表中提取数据.

我的问题:

  • 我不知道这个问题是否已经真正解决了SQL Server 2012.有这个问题得到修复只针对importing已嵌入文本预选赛文件,并notexporting数据到CSV?

  • 可能,我显然做错了什么,错过了显而易见的事情.有人可以向我解释我在这里做错了什么吗?

Microsoft Connect:

我已在Microsoft Connect网站上提交了错误报告以获取他们的反馈.这是错误报告的链接.如果您同意这是一个错误,请访问以下链接在Microsoft Connect网站上投票.

导出到CSV期间的嵌入式文本限定符不符合RFC 4180

Jam*_*den 7

我不会提供这个答案,除非你努力工作以记录它,并且在一个月之后它没有得到答复.所以,这里.您唯一的选择似乎是更改数据或更改工具.

可能,我显然做错了什么,错过了显而易见的事情.有人可以向我解释我在这里做错了什么吗?

当工具坏了而且供应商不关心时,继续尝试是错误的.是时候切换了.您花了很多精力研究它是如何被破坏的,并证明它不仅违反了RFC而且侵犯了工具自己的先前版本.您需要多少证据?

CSV也是船锚.如果您有选项,最好使用普通的分隔文件格式.对于许多应用程序,制表符分隔是好的.最好的分隔符IMO是'\',因为该字符在英文文本中没有位置.(另一方面,它不适用于包含Windows路径名的数据.)

CSV有两个问题作为交换格式.首先,它不是那么标准; 不同的应用程序识别不同的版本,无论RFC如何说.第二个(和相关的)是它不构成CS术语中的常规语言,这就是为什么它不能被解析为正则表达式.与^([^\t]*\t)*[\t]*$制表符分隔的行比较.CSV定义复杂性的实际含义是(见上文)处理它们的工具相对缺乏以及它们不相容的倾向,特别是在凌晨.

如果你给CSV和DTS启动,你有很好的选择,其中之一是bcp.exe.这是非常快速和安全的,因为微软多年来一直没有想过更新它.我对DTS知之甚少,但是如果你必须将它用于自动化,IIRC有一种方法来调用外部工具.请注意,这bcp.exe不会可靠地将错误状态返回给shell.

如果您决定使用DTS并坚持使用CSV,那么您真正最好的选择是编写一个视图,为其准备适当的数据.如果支持那个角落,我会创建一个名为"DTS2012CSV"的架构,这样我就可以写作select * from DTS2012CSV.tablename,让任何关心战斗机会的人都能理解它(因为你会记录它,不会是你,视图文本中的注释?).如果需要,其他人可以将其技术复制到其他破碎的提取物中.

HTH.