如何在SQL Server中使用批量插入编写UTF-8字符?

时间:2011-03-31 09:53:22

标签: sql-server utf-8 sql-server-2008-r2 bulkinsert

我正在对sqlserver进行BULK INSERT,并且没有正确地将UTF-8字符插入数据库。数据文件包含这些字符,但在批量插入执行后数据库行包含乱码。

我的第一个嫌疑人是格式文件的最后一行:

10.0
3
1 SQLCHAR  0  0  "{|}"  1 INSTANCEID ""
2 SQLCHAR  0  0  "{|}"  2 PROPERTYID ""
3 SQLCHAR  0  0  "[|]"  3 CONTENTTEXT "SQL_Latin1_General_CP1_CI_AS"

但是,在阅读this official page之后,在我看来,这实际上是SQL Server 2008版中的插入操作读取数据文件时的错误。我们使用的是版本2008 R2。

此问题的解决方案是什么或至少是解决方法?

13 个答案:

答案 0 :(得分:31)

在找到批量插入特殊字符的解决方案之前,我来到这里。 不喜欢UTF-16的解决方法(这将使csv文件的大小加倍)。 我发现你绝对可以,而且非常简单,你不需要格式文件。 因此,我正在为其他正在寻找相同内容的人添加此评论,因为它似乎没有在任何地方记录得很好,我相信这对非英语国家的人来说是一个非常普遍的问题。解决方案是: 只需在批量插入的with语句中添加CODEPAGE ='65001'。 (65001 = UTF-8的代码页编号)。 可能不适合Michael O所建议的所有unicode角色,但至少它适用于拉丁语,希腊语和西里尔语,可能还有很多其他人。

注意:MSDN文档说不支持utf-8,不相信它,对我来说这在SQL Server 2008中是完美的,但是没有尝试其他版本。

e.g:

BULK INSERT #myTempTable 
FROM  'D:\somefolder\myCSV.txt'+
WITH 
    ( 
        CODEPAGE = '65001',
        FIELDTERMINATOR = '|',
        ROWTERMINATOR ='\n'
    );

如果所有特殊字符都在160-255(iso-8859-1或windows-1252)中,您还可以使用:

BULK INSERT #myTempTable 
FROM  'D:\somefolder\myCSV.txt'+
WITH 
    ( 
        CODEPAGE = 'ACP',
        FIELDTERMINATOR = '|',
        ROWTERMINATOR ='\n'
    );

答案 1 :(得分:27)

你做不到。您应该首先使用N类型数据字段,将文件转换为UTF-16然后导入它。该数据库不支持UTF-8。

答案 2 :(得分:7)

  1. 在excel中将文件保存为CSV(逗号分隔)
  2. 在记事本++中打开已保存的CSV文件
  3. 编码 - >转换为UCS-2 Big Endian
  4. 保存
  5.   

    BULK INSERT #tmpData

        FROM 'C:\Book2.csv'
        WITH
        (
            FIRSTROW = 2,
            FIELDTERMINATOR = ';',  --CSV field delimiter
            ROWTERMINATOR = '\n',   --Use to shift the control to next row
            TABLOCK
        )
    

    完成。

答案 3 :(得分:4)

您可以使用UTF-16重新编码数据文件。这就是我所做的。

答案 4 :(得分:4)

Microsoft刚刚向SQL Server 2014 SP2添加了UTF-8支持:

https://support.microsoft.com/en-us/kb/3136780

答案 5 :(得分:2)

使用这些选项 - `https://graph.facebook.com/${matchedResult.username}/posts?access_token=${matchedResult.token}` DATAFILETYPE='char'

答案 6 :(得分:2)

请注意,自Microsoft SQL Server 2016起,bcpBULK_INSERT (as was part of the original question)OPENROWSET支持UTF-8。

答案 7 :(得分:1)

你不应该使用SQLNCHAR代替SQLCHAR来获取unicode数据吗?

答案 8 :(得分:0)

我设法使用SSIS和ADO NET目的地而不是OLEDB。

答案 9 :(得分:0)

我的导出数据是来自DB的TSV格式,具有Latin-1编码。

这很容易检查: SELECT DATABASEPROPERTYEX('DB', 'Collation') SQLCollation;

提取文件采用UTF-8格式。

BULK INSERT不使用UTF-8,因此我使用简单的Clojure脚本将UTF-8转换为ISO-8859-1(又名Latin-1):

(spit ".\\dump\\file1.txt" (slurp ".\\dump\\file1_utf8.txt" :encoding "UTF-8") :encoding "ISO-8859-1")

执行 - 纠正路径和 java.exe -cp clojure-1.6.0.jar clojure.main utf8_to_Latin1.clj

答案 10 :(得分:0)

我已使用UTF -8格式测试了批量插入。它在Sql Server 2012中工作正常。

string bulkInsertQuery = @"DECLARE @BulkInsertQuery NVARCHAR(max) = 'bulk insert [dbo].[temp_Lz_Post_Obj_Lvl_0]
                                      FROM ''C:\\Users\\suryan\\Desktop\\SIFT JOB\\New folder\\POSTdata_OBJ5.dat''
                                      WITH ( FIELDTERMINATOR =  '''+ CHAR(28) + ''', ROWTERMINATOR = ''' +CHAR(10) + ''')'
                                      EXEC SP_EXECUTESQL @BulkInsertQuery";

我使用*.DAT文件将FS作为列分隔符。

答案 11 :(得分:0)

以为我会加入我的想法。我们试图使用bcp将数据加载到SqlServer中并且遇到了很多麻烦。

在大多数版本中,bcp不支持任何类型的UTF-8文件。我们发现UTF-16可以工作,但它比这些帖子中显示的更复杂。

使用Java我们使用以下代码编写文件:

PrintStream fileStream = new PrintStream(NEW_TABLE_DATA_FOLDER + fileName, "x-UTF-16LE-BOM");

这为我们提供了正确的数据插入。

utf-16 little-endian

我们尝试使用UTF16并不断出现EOF错误。这是因为我们错过了文件的BOM部分。来自维基百科:

  

UTF-16,BOM(U + FEFF)可以作为文件或字符流的第一个字符,以指示文件或流的所有16位代码单元的字节顺序(字节顺序)。

如果这些字节不存在,则该文件将不起作用。所以我们有了这个文件,但还有一个秘密需要解决。在构造命令行时,必须包含-w以告诉bcp它是什么类型的数据。仅使用英语数据时,可以使用-c(字符)。所以看起来像这样:

  

bcp dbo.blah在C:\ Users \ blah \ Desktop \ events \ blah.txt -S tcp:databaseurl,someport -d thedatabase -U username -P password -w

当这一切都完成后,你会得到一些甜美的数据!

Good little endian!

答案 12 :(得分:0)

我只想分享一个问题,我在文件中添加了葡萄牙语的重音符号,并bcp导入了垃圾字符(例如À变成┴) 我尝试使用-C几乎所有代码页都没有成功。几个小时后,我在bcp MS帮助页面上找到了提示。

  

格式文件代码页的优先级高于-C属性

表示在格式文件中,我必须像姓氏中那样使用“”,更改代码页后,属性-C 65001导入了UTF8文件而没有任何问题

ListItemWriter.getWrittenItems