【发布时间】:2015-11-19 17:14:48
【问题描述】:
PHP PDO ODBC 似乎无法在没有手动编码的情况下存储 NVARCHAR 字符 (UTF-16)。这似乎是整个互联网上非常常见的“错误”,似乎没有人有明确的解决方案。
如何重现错误
- 尝试使用 PDO 插入以下日文字符:
こんにちは(表示你好) - 以下内容将存储在您的数据库中:
ã“ã‚“ã«ã¡ã¯ - 然后通过 PDO 检索它并打印在屏幕上,你会得到:
こんにちは
这不是那么糟糕,但也不是很好。 PHP 可以工作,但是当您有其他不在 PHP 中的应用程序从您的数据库中访问该信息时,它们会得到错误的字符串:ã“ã‚“ã«ã¡ã¯。
理想情况下,您希望在任何地方都有こんにちは。
症状
似乎 PDO 没有任何 NVARCHAR 概念,即使用 16 位编码的字符。事实上,您通过 PDO 传递给 SQL SERVER 或从 SQL SERVER 检索的所有内容都将是 8 位块。如何“证明”它?这里是:
- 你从你的日文字符串
こんにちは开始。
您首先必须知道 PHP 将字符串视为二进制,并且(如果设置为这样)它将以 UTF-8 存储它们。
因此,如果我们查看こんにちは 的二进制表示,您将得到E38193E38293E381ABE381A1E381AF,这也是SQL SERVER 将为您提供ã“ã‚“ã«ã¡ã¯ 的二进制表示。 (取决于你的整理)
-
接下来,我们把它换成 UTF-16,因为那是 NVARCHAR 的格式。
$utf16_string = mb_convert_encoding('こんにちは', 'UTF-16LE');
以下内容会将 PHP 中 こんにちは 的二进制表示更改为 533093306B3061306F30,这正是 SQL SERVER NVARCHAR 中 こんにちは 的二进制表示。
- 接下来尝试通过 PDO 将其保存在 SQL 中,您将得到以下信息:
S0“0k0a0o0
S0“0k0a0o0 在 VARCHAR 中的 SQL SERVER 二进制表示是 533093306B3061306F30,这也是 こんにちは 在 NVARCHAR 中的二进制表示。
肮脏的解决方案
您可以使用以下方法通过 PDO ODBC 在 SQL SERVER 中保存和检索 unicode 数据,但这很丑...
-
您希望将数据转换为与 SQL SERVER NVARCHAR 完全相同的二进制表示 会存储它
mb_convert_encoding('こんにちは', 'UTF-16LE');
-
您希望在 SQL SERVER 端将其作为二进制文件接收,然后将其转换为 NVARCHAR。
@binary VARBINARY(40) SELECT @string = CONVERT(NVARCHAR(20), @binary);
此时您的数据库中有
こんにちは。要检索它,您需要将其作为二进制文件重新发送到 PHP-
一旦你在 PHP 中获得二进制文件,PHP 已经将其转换为十六进制字符串...所以,你想将十六进制字符串转换为二进制,然后将编码从 utf-16 更改为 utf-8
$result = mb_convert_encoding(hex2bin($string), 'UTF-8', 'UTF-16LE');
当您将 こんにちは 回显到您的网页时,您将返回它。
基本上,这就是 SQL 驱动程序应该为我做的事情,而不是我手动做的事情。
是我忘了配置还是必须手动配置?
【问题讨论】:
标签: php sql-server pdo odbc nvarchar