我使用批量插入将csv导入db。 它是逗号分隔的csv文件。所有字段都没有文本限定符。
但有些字段可能会将逗号作为数据的一部分。 例如,ADDRESS字段值。这些值用双引号括起来。 这些双引号仅在字段值中包含逗号时出现,否则值不会被双引号括起来。 因此,在某些行中,ADDRESS值用双引号括起来,但在其他行中它们不是。 有没有办法在批量插入命令中指定text-qualifier?
我尝试使用格式文件选项批量插入。
BULK INSERT Test_Imported FROM 'C:\test.csv'
WITH (FIRSTROW=0,FIELDTERMINATOR = ',',ROWTERMINATOR = '\n',FORMATFILE = 'C:\test.Fmt')
但我无法在格式文件中将双引号作为可选文本限定符提及。
PS: 这个函数实际上是更大模块的一部分,用c#编写。 从c#调用bulk insert命令。
csv文件来自另一个自动化系统的电子邮件。我无法控制格式 csv文件。大约有150列。 平均每个csv文件中有12000行。 忘了spcify DB。它是SQL server 2005。
答案 0 :(得分:4)
批量插入语句真的很糟糕,因为它不处理可选的限定符。
TextFieldParser 类可以帮助我们清理文件( Microsoft.VisualBasic.FileIO.TextFieldParser )
我已经粘贴了一个函数,该函数使用 TextFieldParser 类来清理分隔文件,以便您可以在批量插入语句中使用它。
String newDel = CleanDelimitedFile("c:\temp.csv",new String[] {","},"\t,\t");
这是一个清理分隔文件的函数。
/// <summary>
/// This function opens a delimited file and cleans up any string quantifiers
/// </summary>
/// <param name="FileFullPath">Full path of the delimited string</param>
/// <param name="CurrentDelimiter">What string / character the file uses as the delimiter</param>
/// <param name="NewDelimiter">What new delimiter string to use</param>
/// <returns>Returns String representation of the new delimited file</returns>
private static String CleanDelimitedFile(String FileFullPath, String[] CurrentDelimiter, String NewDelimiter) {
//-- if the file exists stream it to host
if (System.IO.File.Exists( FileFullPath )) {
Microsoft.VisualBasic.FileIO.TextFieldParser cvsParser = null;
System.Text.StringBuilder parseResults = new System.Text.StringBuilder();
try {
// new parser
cvsParser = new Microsoft.VisualBasic.FileIO.TextFieldParser(FileFullPath);
// delimited file has certain fields enclosed in quotes
cvsParser.HasFieldsEnclosedInQuotes = true;
// the current delimiter
cvsParser.Delimiters = CurrentDelimiter;
// iterate through all the lines of the file
Boolean FirstLine = true;
while (!cvsParser.EndOfData ) {
if (FirstLine) {
FirstLine = false;
}
else {
parseResults.Append("\n");
}
Boolean FirstField = true;
// iterate through each field
foreach (String item in cvsParser.ReadFields()) {
if (FirstField) {
parseResults.Append(item);
FirstField = false;
}
else {
parseResults.Append(NewDelimiter + item);
}
}
}
return parseResults.ToString();
}
finally {
if (cvsParser != null) {
cvsParser.Close();
cvsParser.Dispose();
}
}
}
return String.Empty;
}
答案 1 :(得分:3)
不幸的是,您必须预先处理文件以使其保持一致。 SQL批量操作将字符串拆分为字段分隔符。
一些选项:
你说你无法控制格式,但你拥有的东西是无法使用的......
答案 2 :(得分:1)
可悲的是,SQL 2005和2008导入XLS文件比CSV文件更顺畅。我从来都不是反微软,但除非所有ANSI标准的数据库管理都发生了巨大的变化,并且文本限定符的概念被放弃了(我非常怀疑),那么这可能是MS的专有举措。 SQL 2000处理文本限定符很好(不确定BULK命令,因为我一直只使用导入向导)。想象一下,当我们迁移到2005年时,我不得不将我的所有进程重新编译为不导入平面文件,而是导入XLS。我只花了16个小时(是的,两个工作日)来得出这个结论,我实际上在那个星期失去了睡眠,因为我因为不允许使用文本限定符而对MS感到非常沮丧(我甚至进入我的老板办公室道歉把这么多时间花在应该是10分钟的任务上。具有讽刺意味的是,您不能告诉Excel导出任何包含双引号文本限定符(或几乎任何其他软件导出器)的内容。 GRRRRRR。
所有这一切中最令人沮丧的部分是SQL 2005导入向导有一个定义文本限定符的地方!
...我敢说在这次经历之后我开始理解所有的反M $修辞!
答案 3 :(得分:0)
非常好的解释文章
如何创建格式文件
逐步解释了每一栏的含义
SQL版,如何使用。
答案 4 :(得分:0)
我知道这是一个老问题,但我有一个TSQL方法来处理间歇引用分隔符。它可能不是很漂亮,但它可能会帮助那些在那里找到方法的人:
*&*
UPDATE InitialTable
SET BulkColumn =
REPLACE(BulkColumn,
SubString(BulkColumn,
CHARINDEX('"', BulkColumn, 0),
CHARINDEX('"', BulkColumn, CHARINDEX('"', BulkColumn, 0) + 1) - CHARINDEX('"', BulkColumn, 0) + 1),
REPLACE(
SubString(BulkColumn,
CHARINDEX('"', BulkColumn, 0),
CHARINDEX('"', BulkColumn, CHARINDEX('"', BulkColumn, 0) + 1) - CHARINDEX('"', BulkColumn, 0) + 1),
',',
'*&*'))
WHERE BulkColumn LIKE '%"%'
答案 5 :(得分:0)
对我有用的是改变
ROWTERMINATOR = '\n'
收件人:
ROWTERMINATOR = '0x0a'