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


MSSQL + PHP - Error to insert oriental char

在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时。

有人知道怎么做吗?选角什么的?

谢谢!

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

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

转换为HEX值(先看这里。但搜索Javascript将帮助您找到更好的方法,即使在PHP中也是如此):14af

注:事实并非如此重真的是在HEX

以可以转换回其原始值的方式存储。例如,你如何判断这是什么:0d3114af是0d-31-14-af还是0d31-14af。你可以使用像|或a这样的分母。但一种方法是在前面提供00的填充。一个英文字符将只有2个字符长,如31,或者非英文字符将是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;
}