MSSQL + PHP - 插入东方字符时出错

时间:2014-09-24 16:41:51

标签: php sql-server linux freetds bind-variables

我在SQL Server中插入带有绑定变量的东方字符时遇到问题。 我正在使用MSSQL命令和PHP。

我的PHP代码是这样的:

$sql = "
    CREATE TABLE table_test
      (  id                int
        ,nvarchar_latin    nvarchar(255) collate sql_latin1_general_cp1_ci_as 
      );";

    $stmt = mssql_query($sql);

    $conn = mssql_connect("server","user","pass");
    mssql_select_db('test')

    $stmt = mssql_init('test..sp_chinese', $conn); 

    $id      = 1;      
    $nvarchar_latin  = '重建議';

    mssql_bind($stmt, '@id'          , $id            , SQLINT1);  
    mssql_bind($stmt, @nvarchar_latin, $nvarchar_latin, SQLVARCHAR); 

    mssql_execute($stmt);

我的程序是这样的:

ALTER PROCEDURE sp_chinese
  @id               int
 ,@nvarchar_latin   nvarchar (255) 
AS 
 BEGIN
 INSERT INTO char_chines (id, nvarchar_latin) 
      VALUES (@id, @nvarchar_latin);
 END

这项工作如果我改变正常的东方字符。 如果我直接运行这个插件,它可以正常工作:

INSERT INTO table_test (id, nvarchar_latin) 
     VALUES (1, '重建議');

因此,当我将变量从PHP发送到SQL Server时,问题就在于清楚。

任何人都知道如何使这个工作?某些演员还是什么?

谢谢!

1 个答案:

答案 0 :(得分:1)

仅使用PHP(甚至是JavaScript)的解决方案是将字符转换为其HEX值并存储它。我不知道你是否想要走这条路,但我没有时间向你展示代码,但这里是完整的理论:

检测到非英语字符,如下所示:重

转换为HEX值(Look here for starters.但是搜索Javascript将帮助您找到更好的方法来实现这一点,即使在PHP中):14af

注意:这不是HEX中真正重要的内容

以可以转换回原始值的方式存储。例如,你怎么知道这是什么:0d3114af是0d - 31 - 14 - af或者它是0d31 - 14af。您可以使用像|这样的分隔符或者a。但一种方法是在前面提供00的填充。一个英文字符只有2个字符长,如31或af非英语将4个像14af。知道了这一点,你可以将每4个字符拆分并转换为它们的值。

下行是您需要更改数据库以适应这些更改。

[更新] -----

这是一些JavaScript代码,可以向您发送正确的方向。这完全可以在PHP中复制。这不会搜索字符,它是加密程序的一部分所以它关心的是将所有内容都变成HEX。英文字符将用00填充(这是我自己的代码,因此没有链接到源代码):

function toHex(data) {
   var result = '';
   // Loop through entire string of data character by character
   for(var i=0;i<data.length;i++) {
     // Convert UTF-16 Character to HEX, if it is a 2 chracter HEX add 00 padding in front
     result += (data.charCodeAt(i) + 0x10000).toString(16).slice(1);
   }
   // Display the result for testing purposes
   document.getElementById('two').value = result;
}

function fromHex(data) {
   var result = '', block = '', pattern = /(00)/;  // Pattern is the padding
   for(var i=0;i<data.length;i = i+4) {
      // Split into separate HEX blocks
      block = data.substring(i,i+4);
      // Remove 00 from a HEX block that was only 2 characters long
      if(pattern.test(block)){
         block = block.substring(2,4);
      }
      // HEX to UTF-16 Character
      result += String.fromCharCode(parseInt(block,16));
   }
   // Display the result for testing purposes
   document.getElementById('two').value = result;
}