【问题标题】:Automatic character encoding handling in Perl / DBI / DBD::ODBCPerl / DBI / DBD::ODBC 中的自动字符编码处理
【发布时间】:2011-05-06 13:23:54
【问题描述】:

我正在使用 Perl 和 DBI / DBD::ODBC 从 SQL Server 数据库中检索数据,但在字符编码方面存在一些问题。

数据库的默认排序规则为 SQL_Latin1_General_CP1_CI_AS,因此 varchar 列中的数据以 Microsoft 的 Latin-1 版本编码,也称为 windows-1252

似乎没有办法在 DBI/DBD::ODBC 中透明地处理这个问题。我得到的数据仍然编码为windows-1252,例如,€“”被编码为字节 0x80、0x93 和 0x94。当我将它们写入 UTF-8 编码的 XML 文件而不先解码它们时,它们被写为 Unicode 字符 0x80、0x93 和 0x94,而不是 0x20AC、0x201C、0x201D,这显然是不正确的。

我目前的解决方法是在每个 fetch 之后的每一列上调用 $val = Encode::decode('windows-1252', $val)。这行得通,但似乎不是正确的方法。

有没有办法告诉DBIDBD::ODBC 为我做这个转换?

我正在使用 ActivePerl (5.12.2 Build 1202),DBI (1.616) 和 DBD::ODBC (1.29) 由 ActivePerl 提供并更新为 ppm;在托管数据库的同一台服务器上运行 (SQL Server 2008 R2)。

我的连接字符串是:

dbi:ODBC:Driver={SQL Server Native Client 10.0};Server=localhost;Database=$DB_NAME;Trusted_Connection=yes;

提前致谢。

【问题讨论】:

  • 这让我很吃惊。柱子的类型是什么? search.cpan.org/~mjevans/DBD-ODBC-1.29/ODBC.pm#odbc_has_unicode 为您返回什么。 Windows 上的 DBD::ODBC 通常是用 -u 构建的(默认情况下),因此会进行 unicode ODBC 调用并要求 SQL_WCHARs 应该返回 UCS2 编码的数据,对于 Perl,该数据被重新编码为 UTF-8。
  • @bohica:$dbh->{odbc_has_unicode} == 1。列都是varchar不是nvarchar
  • 我维护 DBD::ODBC。您能否将其简化为一个检索行的简单脚本,然后使用 DBI_TRACE=15=x.log 运行它并将日志文件发布到某处(在 Windows 上可能设置 DBI_TRACE=15=x.log)。
  • @bohica:会的。同时,即使手动绑定类型为 SQL_WVARCHAR 或 SQL_WCHAR 的列也没有什么不同。看起来 ODBC 驱动程序或 DBD::ODBC 不知道数据在 windows-1252-encoding...
  • 就我而言,如果要求作为 SQL_WCHAR,它不应该在 windows-1252 中。

标签: sql-server perl odbc dbi


【解决方案1】:

DBD::ODBC(和 ODBC API)不知道底层列的字符集,因此 DBD::ODBC 无法对返回的 8 位数据执行任何操作,它只能按原样返回,您需要知道什么它是并解码它。如果将列绑定为 SQL_WCHAR/SQL_WVARCHAR,则驱动程序/sql_server 应将字符转换为 UCS2,并且 DBD::ODBC 应将列视为 SQL_WCHAR/SQL_WVARCHAR。当 DBD::ODBC 以 unicode 模式构建时,SQL_WCHAR 列被视为 UCS2 并以 UTF-8 解码和重新编码,Perl 应该将它们视为 unicode 字符。

你需要在 bind_columns 之后将 SQL_WCHAR 设置为绑定类型,因为绑定类型不像参数类型那样具有粘性。

如果你想继续读取你的 varchar 数据,windows 1252 作为字节,那么目前你别无选择,只能解码它们。我并不急于向 DBD::ODBC 添加一些东西来为您做这件事,因为这是第一次有人向我提到这一点。您可能希望查看 DBI 回调,因为在这些回调中解码返回的数据可能更容易(比如 fetch 方法)。

您可能还想研究较新的 SQL Server ODBC 驱动程序中的“对字符数据执行转换”设置,尽管我自己对此没有什么经验。

【讨论】:

  • 谢谢。将varchar 列绑定为SQL_WCHARSQL_WVARCHAR 可能是我目前最好的选择。当然比手动解码要好...
  • 仅供参考,我在 1.30_1 中更改了 DBD::ODBC unicode build,因此所有 char 数据都绑定为 SQL_WCHARs,它应该避免您在 rt.cpan.org/Ticket/Display.html?id=67994 报告的问题
猜你喜欢
  • 1970-01-01
  • 2011-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-24
相关资源
最近更新 更多