SQL Server批量插入带双引号字段CSV的格式文件正确格式
解决BULK INSERT导入带双引号CSV时残留引号的问题
我之前也碰到过这个一模一样的头疼问题!用bcp生成格式文件后改来改去,结果总有字段带着双引号残留,后来才搞明白:SQL Server不会自动识别CSV里的引号包裹,必须在格式文件里明确告诉它要处理引号。
问题根源
你的CSV格式是每个字段都用双引号包裹(包括空值的""),比如示例行:
"SONC","Sonic Corp.","981","amc","0.22","0.24","+0.02","+9.09%","5.15%",""
默认bcp生成的格式文件只会处理分隔符(比如逗号),不会理会引号——所以如果只是把终止符改成",",SQL Server会把引号当成字段内容的一部分,导致导入后残留引号。
解决方案:用XML格式文件处理引号
XML格式文件比传统的非XML格式更灵活,能直接指定QUOTE属性让SQL Server自动去掉字段前后的双引号。下面是针对你的CSV结构的完整示例:
1. 创建XML格式文件(比如stock_format.xml)
<?xml version="1.0"?> <BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <RECORD> <!-- 前9个字段的终止符是",",每个字段都用双引号包裹 --> <FIELD ID="1" xsi:type="CharTerm" TERMINATOR='","' QUOTE='"'/> <FIELD ID="2" xsi:type="CharTerm" TERMINATOR='","' QUOTE='"'/> <FIELD ID="3" xsi:type="CharTerm" TERMINATOR='","' QUOTE='"'/> <FIELD ID="4" xsi:type="CharTerm" TERMINATOR='","' QUOTE='"'/> <FIELD ID="5" xsi:type="CharTerm" TERMINATOR='","' QUOTE='"'/> <FIELD ID="6" xsi:type="CharTerm" TERMINATOR='","' QUOTE='"'/> <FIELD ID="7" xsi:type="CharTerm" TERMINATOR='","' QUOTE='"'/> <FIELD ID="8" xsi:type="CharTerm" TERMINATOR='","' QUOTE='"'/> <FIELD ID="9" xsi:type="CharTerm" TERMINATOR='","' QUOTE='"'/> <!-- 最后一个字段的终止符是" + 行结束符(\r\n) --> <FIELD ID="10" xsi:type="CharTerm" TERMINATOR='"\r\n' QUOTE='"'/> </RECORD> <ROW> <!-- 这里要对应你的目标表字段名和SQL类型 --> <COLUMN SOURCE="1" NAME="Symbol" xsi:type="SQLVARYCHAR"/> <COLUMN SOURCE="2" NAME="CompanyName" xsi:type="SQLVARYCHAR"/> <COLUMN SOURCE="3" NAME="SomeNum" xsi:type="SQLINT"/> <COLUMN SOURCE="4" NAME="Exchange" xsi:type="SQLVARYCHAR"/> <COLUMN SOURCE="5" NAME="Price1" xsi:type="SQLDECIMAL" PRECISION="5" SCALE="2"/> <COLUMN SOURCE="6" NAME="Price2" xsi:type="SQLDECIMAL" PRECISION="5" SCALE="2"/> <COLUMN SOURCE="7" NAME="ChangeVal" xsi:type="SQLVARYCHAR"/> <COLUMN SOURCE="8" NAME="ChangePct" xsi:type="SQLVARYCHAR"/> <COLUMN SOURCE="9" NAME="PctOfSomething" xsi:type="SQLVARYCHAR"/> <COLUMN SOURCE="10" NAME="EmptyField" xsi:type="SQLVARYCHAR"/> </ROW> </BCPFORMAT>
2. 执行BULK INSERT命令
假设你的目标表叫StockData,CSV路径是C:\Data\stocks.csv,格式文件路径是C:\Data\stock_format.xml,执行以下SQL:
BULK INSERT StockData FROM 'C:\Data\stocks.csv' WITH ( FORMATFILE = 'C:\Data\stock_format.xml', FIRSTROW = 1, -- 如果CSV有表头行,改成2跳过表头 ROWTERMINATOR = '\r\n' -- 和格式文件里的行终止符保持一致 );
关键说明
QUOTE='"'属性:这是核心!告诉SQL Server每个字段被双引号包裹,导入时会自动去掉前后的引号,包括空值的""会被处理成空字符串(如果目标字段允许NULL,会转成NULL)。- 字段终止符:前9个字段的终止符是
","(对应CSV里字段之间的","),最后一个字段的终止符是"\r\n"(对应行尾的"加上换行)。 - 类型转换:如果目标字段是数值类型(比如INT、DECIMAL),在
<COLUMN>节点里指定对应的SQL类型(比如SQLINT、SQLDECIMAL),SQL Server会自动完成类型转换,不需要手动处理引号和数值格式。
为什么之前的格式文件没用?
你用bcp生成的默认格式文件没有QUOTE属性,就算修改了终止符,SQL Server也不知道要去掉引号——它只会把引号当成字段内容的一部分,所以才会残留。XML格式文件的QUOTE属性是解决这个问题的关键。
内容的提问来源于stack exchange,提问作者Tony_Henrich
相关产品推荐
相关产品推荐

