我正在尝试在 SQL Server 2017 14.0.1000.169 中批量插入文件。我想准确地获取文件到达时的状态,将其保存到所需位置,然后运行批量插入查询,而无需修改文件。我很难让脚本识别并忽略文本文件中的双引号,除非我手动将行结尾从 Unix 更改为 Windows。我在这里和之外阅读了很多主题,讨论与此主题相关的主题,唉,没有一个主题给了我问题的答案:
如何批量插入带有 Unix 行结尾的文件而不以双引号结尾?
我的文件看起来像这样:
"Report Name","Daily Extract (ID: 111111)"
"Date/Time Generated(UTC)","01-Mar-2020 15:08:51"
"Workspace Name","Company (ID: 22222)"
"Account Name","Client Account"
"Date Range","01-Jan-2019 - 29-Feb-2020"
"Dimension 1","Dimension 2","Dimension 3","Dimension 4","Dimension 5","Dimension 6","Dimension 7","Dimension 8","Dimension 9","Dimension 10","Dimension 11","Dimension 12","Dimension 13","Dimension 14","Dimension 15","Dimension 16","Dimension 17","Metric 1","Metric 2","Metric 3","Metric 4","Metric 5","Metric 6","Metric 7","Metric 8","Metric 9","Metric 10","Metric 11","Metric 12"
"string","string","date as string","string","string","string","string","string","string","string","string","string","string","string","string","string","string","bigint","bigint","decimal","decimal","decimal","bigint","decimal","decimal","bigint","decimal","bigint","bigint"
我使用的查询如下:
DROP TABLE IF EXISTS Table
GO
CREATE TABLE [dbo].[Table](
[Dimension 1] [varchar] (255) NULL,
[Dimension 2] [varchar] (255) NULL,
[Dimension 3] [varchar] (255) NULL,
[Dimension 4] [varchar] (255) NULL,
[Dimension 5] [varchar] (255),
[Dimension 6] [varchar] (255) NULL,
[Dimension 7] [varchar] (255) NULL,
[Dimension 8] [varchar] (255) NULL,
[Dimension 9] [varchar] (1000) NULL,
[Dimension 10] [varchar] (255) NULL,
[Dimension 11] [varchar] (255) NULL,
[Dimension 12] [varchar] (255) NULL,
[Dimension 13] [varchar] (1000) NULL,
[Dimension 14] [varchar] (1000) NULL,
[Dimension 15] [varchar] (1000) NULL,
[Dimension 16] [varchar] (1000) NULL,
[Dimension 17] [varchar] (1000) NULL,
[Metric 1] [varchar] (50) NULL,
[Metric 2] [varchar] (50) NULL,
[Metric 3] [varchar] (50) NULL,
[Metric 4] [varchar] (50) NULL,
[Metric 5] [varchar] (50) NULL,
[Metric 6] [varchar] (50) NULL,
[Metric 7] [varchar] (50) NULL,
[Metric 8] [varchar] (50) NULL,
[Metric 9] [varchar] (50) NULL,
[Metric 10] [varchar] (255) NULL,
[Metric 11] [varchar] (50) NULL,
[Metric 12] [varchar] (50) NULL
) ON [PRIMARY]
GO
BULK
INSERT Table
FROM 'C:\Users\username\Folder\File.csv'
WITH
(
--FORMAT = 'CSV',
DATAFILETYPE = 'char',
FIELDTERMINATOR = ',',
--ROWTERMINATOR = '\n',
ROWTERMINATOR = '0x0a',
FIRSTROW = 7,
--FIELDQUOTE = '"'
FIELDQUOTE = '0x22'
)
;
正如您在上面看到的,我将所有内容都作为 varchar 导入。最初,我仅将其用于一个指标(由于供应端的数据质量问题),因为我完全打算在文件加载后纠正每个缺陷。但遇到困难后,我已将所有指标设置为 varchar,因此至少文件会加载,我可以看到它的样子并进一步挖掘。
到目前为止,我已经尝试过以下内容:
保持文件不变,并使用双引号而不是 0x22 运行上面的脚本 - 这也可以,但最终结果是每个值都在双引号中
保持文件不变并按原样运行上面的脚本(即使用 0x22 作为 FIELDQUOTE) - 再次,可以工作,但到处都带有双引号
到目前为止,我尝试过的所有其他事情都导致了各种错误,这些错误都导致了相同的两件事:要么我不能使用 FORMAT = 'CSV' (如果我保留 Unix 行结尾),要么我的那一刻尝试将指标加载为浮点数,由于双引号,它会出错。
我暂时有一个解决方法(我可以删除双引号并在加载内容后转换字段),但我确实想知道是否可以将该步骤集成到批量插入中(就像我加载时所做的那样)以 Windows 结尾的文件)。
注意我知道 FIELDQUOTE 出现的时间并不长,但是,根据 Microsoft 的说法,它应该适用于我的构建:
“FIELDQUOTE = 'field_quote' 适用于:SQL Server 2017 (14.x) CTP 1.1.指定将在 CSV 文件中用作引号字符的字符。如果未指定,将使用引号字符 (") 作为 RFC 4180 标准中定义的引号字符。”
我是不是忘了透露什么?如果没有,我可能忽略了什么想法?
提前致谢!
好的。这里最大的问题是你的文件。首先,由于顶部的行,该文件不符合 RFC 4180。这让人头疼。
接下来是关于FIRSTROW
的
重要警告:
跳过行时,SQL Server 数据库引擎仅查看字段终止符,并且不会验证跳过行的字段中的数据。
注意,这里说的是 字段终止符 不是 行终止符。这是第二个问题。对于您的数据,您一开始就有这个:
"Report Name","Daily Extract (ID: 111111)"
"Date/Time Generated(UTC)","01-Mar-2020 15:08:51"
"Workspace Name","Company (ID: 22222)"
"Account Name","Client Account"
"Date Range","01-Jan-2019 - 29-Feb-2020"
<-- Blank Line -->
这是 6 个字段终止符和 6 个行终止符。
接下来,CSV 文件中的列数比表中的列数Table
多。
Table
没有列 Dimension 17
。添加这个缺失的列后,我设法得到了这个结果,我相信你会得到以下结果:
BULK INSERT [Table]
FROM '/tmp/YourFile2.txt'
WITH (FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n',
FIRSTROW = 2,
FORMAT = 'CSV',
FIELDQUOTE = '"');
这将在表中插入 1 行。