【发布时间】:2016-05-10 14:23:48
【问题描述】:
我遇到了一个有趣的问题,尝试使用适用于 Linux 的 Microsoft ODBC 驱动程序将非 ASCII 字符插入 SQL Server 数据库。问题是它似乎在发送和接收数据时假设了不同的字符集。有关信息,服务器排序规则设置为 Latin1_General_CI_AS(我只是尝试插入欧洲重音字符)。
使用 tsql(FreeTDS 附带)进行测试,一切正常。在启动时,它会输出以下内容:
locale is "en_GB.utf8"
locale charset is "UTF-8"
using default charset "UTF-8"
我可以在表格中插入和选择一个非 ASCII 值。
但是,使用我自己的使用 ODBC API 的实用程序,它不起作用。当我进行选择查询时,数据会根据需要以 UTF-8 字符集返回。但是,如果我插入 UTF-8 字符,它们就会损坏。
SQL > update test set a = 'Béthune';
Running SQL: update test set a = 'Béthune'
Query executed OK: 1 affected rows
SQL > select * from test;
Running SQL: select * from test
+------------+
| a |
+------------+
| Béthune |
+------------+
如果我改为插入以 ISO-8859-1 编码的数据,则可以正常工作,但是选择查询仍将返回以 UTF-8 编码的数据!
我已经将语言环境设置为en_GB.utf8,并在数据库连接详细信息中设置了UTF-8 的client charset。啊!
FWIW 无论我使用 FreeTDS 驱动程序还是微软官方驱动程序,我似乎都遇到了同样的问题。
编辑:刚刚意识到一个相关点,那就是在这个测试程序中,它没有使用带有绑定变量的准备好的语句。换句话说,更新 SQL 直接传递到 SQLPrepare 调用中。 ODBC 中的某些东西肯定是在进行 iconv 翻译,但显然不是正确的字符集!
#0 0x0000003d4c41f850 in iconv () from /lib64/libc.so.6
#1 0x0000003d4d83fd94 in ?? () from /usr/lib64/libodbc.so.2
#2 0x0000003d4d820465 in SQLPrepare () from /usr/lib64/libodbc.so.2
我将尝试编译我自己的 UnixODBC,以更好地了解发生了什么。
编辑 2:我已经从源代码构建了 UnixODBC 来调试它在做什么,问题是 nl_langinfo(CODESET) 报告回 ISO-8859-1。这很奇怪,因为它的手册页说它与您从locale charmap 获得的字符串相同,它返回UTF-8。我猜这就是问题所在,但仍然不知道如何解决。
【问题讨论】:
标签: c sql-server character-encoding odbc freetds