RFC 4180 定义 Common Format and MIME Type for Comma-Separated Values (CSV) Files
。 RFC 4180
的要求之一如下所述。这是RFC链接中的 #7
点。
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"
DTS Export/Import Wizard
中的 SQL Server 2000
似乎符合上述标准,即使RFC 4180本身似乎仅在< em> 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)
SQL Server Import and Export Wizard
中的 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)
以下是我在 SQL Server 2000 和 SQL 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
在 DTS Export/Import Wizard
中的 SQL Server 2000
上,我使用以下设置将数据导出到CSV文件。我以名称SQLServer2000_ItemInformation.csv
保存了文件。
在 SQL Server Import and Export Wizard
中的 SQL Server 2012
上,我使用以下设置将数据导出到CSV文件。我以名称SQLServer2012_ItemInformation.csv
保存了文件。
以下是使用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
部分中说明了相同内容。
我知道一种解决方法可以通过编写一个查询来解决问题,该查询将使用两个双引号( {替换我的列数据中的所有双引号( "
) {1}} )以便导出的文件最终会有正确的嵌入式限定符数据。这样可以避免直接从表中提取数据。
我不知道""
是否已真正修复此问题。此问题是否仅针对已嵌入文本限定符的 SQL Server 2012
文件以及 importing
not
修复>数据到CSV?
可能,我显然做错了什么,错过了显而易见的事。有人可以向我解释我在这里做错了吗?
我已在Microsoft Connect网站上提交了错误报告以获取他们的反馈。这是错误报告的链接。如果您同意这是一个错误,请访问以下链接,在exporting
网站上投票。
Embedded text qualifier during export to CSV does not conform to RFC 4180
答案 0 :(得分: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。
答案 1 :(得分:2)
我知道这已经有两年了,但我现在也遇到了这个问题,因为我们需要使用SQL Server 2008来签订合同(不要问)。阅读完这个问题之后,我意识到我需要做替换建议,但是当我去查询时,我遇到了截断问题,因为在查询中使用replace()函数会将文本转换为varchar(8000)默认情况下。
但是,我发现在DB Source和Flat File对象之间使用Derived Column步骤可以做同样的事情。例如,我有一个名为“short_description”的列,其中可能包含引号,因此我只使用以下函数作为表达式,并在派生列中选择“替换short_description”:
REPLACE(short_description,"\"","\"\"")
这似乎已经为我解决了这个问题。
答案 2 :(得分:0)
通常名字和姓氏都在同一个字段中并进行格式化(Last,First)。如果您正在使用任务 - &gt;直接从数据库导出数据(而不是通过SSIS,您有更多选项),则需要进行文本限定,并且需要以逗号分隔文件的形式导出到CSV。
这将有助于您的非空选定字段需要双引号...
CASE WHEN NOT PersonName IS NULL AND LEN(PersonName) > 0 THEN QUOTENAME(PersonName, '"') ELSE NULL END as 'PersonName'
结果:
PERSONNAME
“COLLINS,ZACKERY E”