此文件正常工作(UTF-8):
$ cat ok.txt
291054 Ţawī Rifā
此文件导致错误(UTF-8):
$ cat bad.txt
291054 Ţawī Rifā‘
以下是信息:
$ freebcp 'DB.dbo.table' in bad.txt ... -c
Starting copy...
Msg 20050, Level 4
Attempt to convert data stopped by syntax error in source field
Msg 4895, Level 16, State 2
Server '...', Line 1
Unicode data is odd byte size for column 2. Should be even byte size.
Msg 20018, Level 16
General SQL Server error: Check messages from the SQL Server
唯一的区别是最后一个字符,即unicode 2018(左侧单引号)
知道是什么导致了这个错误吗?
SQL Server使用UTF-16LE(虽然TDS以UCS-2LE开头并切换到我相信)
相关列是nvarchar(200)
这是错误之前发送的数据包:
packet.c:741:Sending packet
0000 07 01 00 56 00 00 01 00-81 02 00 00 00 00 00 08 |...V.... ........|
0010 00 38 09 67 00 65 00 6f-00 6e 00 61 00 6d 00 65 |.8.g.e.o .n.a.m.e|
0020 00 69 00 64 00 00 00 00-00 09 00 e7 90 01 09 04 |.i.d.... ...ç....|
0030 d0 00 34 04 6e 00 61 00-6d 00 65 00 d1 ee 70 04 |Ð.4.n.a. m.e.Ñîp.|
0040 00 13 00 62 01 61 00 77-00 2b 01 20 00 52 00 69 |...b.a.w .+. .R.i|
0050 00 66 00 01 01 18 - |.f....|
答案 0 :(得分:12)
更新:此问题显然已在2016-11-04发布的FreeTDS v1.00.16中修复。
我可以使用FreeTDS v1.00.15重现您的问题。它绝对看起来像U+20xx
中的一个错误,当文本字段的最后一个字符具有291054 Ţawī Rifā
形式的Unicode代码点时,它会导致失败。 (感谢@srutzky纠正我对原因的结论。)正如你所说,这有效......
291054 Ţawī Rifā‘
......这失败了......
291054 Ţawī Rifā‘x
...但我发现这也有效:
x
因此,一个丑陋的解决方法是针对您的输入文件运行一个脚本,该脚本会将低位非空格Unicode字符附加到每个文本字段(例如,U+0078
,即freebcp
,如上例中的最后一个示例所示,使用UPDATE
上传数据,然后针对导入的行运行bcp
语句以去除额外的字符。
就个人而言,我倾向于从FreeTDS切换到Microsoft的Linux SQL Server ODBC驱动程序,其中包括使用此处所述的说明安装的sqlcmd
和libssl.so.1.0.0
实用程序: / p>
https://gallery.technet.microsoft.com/scriptcenter/SQLCMD-and-BCP-for-Ubuntu-c88a28cc
我刚刚在Xubuntu 16.04下进行了测试,虽然我不得不稍微调整一下程序来使用libssl.so.0.9.8
而不是libcrypto
(和bcp
相同),一旦我得到了它在freebcp
失败的情况下成功安装了Microsoft的connectionUrl = "jdbc:sqlserver://servername:49242"
+ ";databaseName=myDb"
+ ";integratedSecurity=false";
String myUserid = "sa", myPassword = "whatever";
String dataFileSpec = "C:/Users/Gord/Desktop/bad.txt";
try (
Connection conn = DriverManager.getConnection(connectionUrl, myUserid, myPassword);
SQLServerBulkCSVFileRecord fileRecord = new SQLServerBulkCSVFileRecord(dataFileSpec, "UTF-8", "\t", false);
SQLServerBulkCopy bulkCopy = new SQLServerBulkCopy(conn)) {
fileRecord.addColumnMetadata(1, "col1", java.sql.Types.NVARCHAR, 50, 0);
fileRecord.addColumnMetadata(2, "col2", java.sql.Types.NVARCHAR, 50, 0);
bulkCopy.setDestinationTableName("dbo.freebcptest");
bulkCopy.writeToServer(fileRecord);
} catch (Exception e) {
e.printStackTrace(System.err);
}
实用程序。
如果用于Linux的SQL Server ODBC驱动程序无法在Mac上运行,那么另一种选择是使用Microsoft JDBC驱动程序6.0 for SQL Server和一些Java代码,如下所示:
continue
答案 1 :(得分:2)
这可能是源文件的编码问题。
当您使用非标准字符时,源文件可能本身应该是unicode。其他编码使用不同的字节数(一个最多三个)来编码一个单个字符。例如。您的Unicode 2018
为0xE2 0x80 0x98
,为UTF-8。
您的数据包以.R.i.f....|
结尾,而应该有ā‘
。错误显示Server '...', Line 1
。
尝试找出源文件的编码(同时查看big and little endian
)并尝试将文件转换为可靠的unicode格式。
答案 2 :(得分:1)
这可以解决它:
inf your /etc/freetds/freetds.conf
添加:
client charset = UTF-8
还发现this标志使用utf-16
use utf-16
而不是在数据库范围内使用UCS-2 字符编码使用UTF-16。较新的Windows版本使用此功能 编码而不是UCS-2。如果客户端,这可能会导致一些问题 假设一个字符总是2个字节。