如何将PHP PDO ODBC与SQL Server和Unicode字符一起使用?

如何将PHP PDO ODBC与SQL Server和Unicode字符一起使用?,php,sql-server,pdo,odbc,nvarchar,Php,Sql Server,Pdo,Odbc,Nvarchar,PHP PDO ODBC似乎无法在没有一些手动编码的情况下存储NVARCHAR字符(UTF-16)。这在互联网上似乎是一个相当普遍的“bug”,似乎没有人有一个明确的解决方案 如何重现错误 尝试使用PDO插入以下日语字符:こんにちは(意思是你好) 以下内容将存储在您的数据库中:ã“ã”ã«ã 然后通过PDO检索并在屏幕上打印,您将得到:こんにちは 这不是很糟糕,但也不是很好。PHP可以工作,但当您有其他非PHP应用程序从数据库访问这些信息时,它们会得到错误的字符串:ã“㔓ã«ã 理想情况下,

PHP PDO ODBC似乎无法在没有一些手动编码的情况下存储NVARCHAR字符(UTF-16)。这在互联网上似乎是一个相当普遍的“bug”,似乎没有人有一个明确的解决方案

如何重现错误

  • 尝试使用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_编码('こんにちは', 'UTF-16LE’

  • 以下内容将更改PHP中的二进制表示形式
    こんにちは
    53309306b3061306f30
    这正是
    こんにちは

  • 接下来,尝试通过PDO将其保存到SQL中,您将获得以下信息:
    S0“0k0a0o0
  • VARCHAR中
    S0“0k0a0o0
    的SQL SERVER二进制表示形式是
    53309306b3061306f30
    ,这也是
    こんにちは在NVARCHAR中

    肮脏的解决方案

    您可以使用以下方法通过PDO ODBC在SQL SERVER中保存和检索unicode数据,但这很难看

  • 您希望将数据转换为与SQL SERVER NVARCHAR完全相同的二进制表示形式 我会把它储存起来

    mb_转换_编码('こんにちは', 'UTF-16LE’

  • 您希望在SQL SERVER端将其作为二进制文件接收,然后将其转换为NVARCHAR

    @二进制VARBINARY(40) 选择@string=CONVERT(NVARCHAR(20),@binary)

  • 此时,您有了
    こんにちは在数据库中。要检索它,您需要将其作为二进制文件重新发送到PHP

  • 一旦您在PHP中获得二进制文件,PHP将已经将其转换为十六进制字符串…因此,您希望将十六进制字符串转换为二进制文件,然后将编码从utf-16更改为utf-8

    $result=mb_convert_编码(hex2bin($string),'UTF-8','UTF-16LE')

  • 您将带着您的
    こんにちは当您将其回显到您的网页时

    基本上,这就是SQL驱动程序应该为我做的事情,而不是我手动完成


    我是忘了配置还是必须手动配置?不,我不认为你忘了配置任何东西。事实上,你的解释是迄今为止我发现的关于PHP和Microsoft ODBC驱动程序之间长期存在的“问题”的最好解释。这些问题特别令人费解,因为

    在Windows上,PDO_ODBC…是连接到Microsoft SQL Server数据库的推荐驱动程序

    然而,在Windows上,它们也提供了看起来确实可以正常工作的功能

    因此,PDO似乎“没有任何NVARCHAR的概念”,而不是PDO作为一个整体

    (如果涉及Unicode字符,尝试将PHP与Microsoft Access ODBC结合使用时也会出现类似问题)


    结论:PHP对ODBC的支持仍然有点混乱,至少在Microsoft数据库方面是这样。

    我一整天都在努力,试图找出ODBC/PHP的可行性