sql-server – PDO DBLIB多字节(中文)字符编码 – SQL服务器

Linux机器上,我使用PDO DBLIB连接到MSsql数据库,并在sql_latin1_General_CP1_CI_AS表中插入数据.问题是当我试图插入汉字(多字节)时,它们被插入为“å¸,é|™åŠåŒºç江路å·.

我的(部分)代码如下:

$DBH = new PDO("dblib:host=$myServer;dbname=$myDB;",$myUser,$myPass);

$query = "
    INSERT INTO UserSignUpInfo
    (FirstName)
    VALUES
    (:firstname)";

$STH = $DBH->prepare($query);

$STH->bindParam(':firstname',$firstname);

到目前为止我已经尝试过

>在$firstname和CAST中将mb_convert_encoding转换为UTF-16LE作为VARBINARY,如下所示:

$firstname = mb_convert_encoding($firstname,’UTF-16LE’,’UTF-8′);

VALUES
(CAST(:firstname AS VARBINARY));

这导致正确插入字符,直到有一些不是多字节字符,这会破坏PDO的执行.
>将我的连接设置为utf8:

$DBH = new PDO("dblib:host=$myServer;dbname=$myDB;charset=UTF-8;",$myPass);
$DBH->exec('SET CHaraCTER SET utf8');
$DBH->query("SET NAMES utf8");

>在我的freetds.conf中将客户端字符集设置为UTF-8

哪个没有影响.

有什么办法可以在该sql数据库中插入多字节数据吗?还有其他解决方法吗?我想过尝试使用PDO ODBC甚至是mssql,但是以前在浪费更多时间之前,请问这里更好.

提前致谢.

编辑:

我最终使用了MSSQL和N数据类型前缀.当我有更多的时间时,我会交换并尝试PDO_ODBC.感谢大家的答案!

解决方法

Is there any way at all,to insert multibyte data in [this particular] sql
database? Is there any other workaround?

>如果您可以切换到PDO_ODBC,Microsoft为Linux提供免费的sql Server ODBC驱动程序(仅适用于支持Unicode的64位Red Hat Enterprise Linux和64位SUSE Linux Enterprise).
>如果您可以更改为PDO_ODBC,则插入Unicode的N前缀将起作用.
>如果可以将受影响的表从sql_latin1_General_CP1_CI_AS更改为UTF-8(这是MSsql认值),那么这将是理想的.

你的情况更受限制此解决方案适用于您的输入字符串中具有混合多字节和非多字节字符的情况,您需要将其保存到拉丁表中,并且N数据类型前缀不起作用,您不想要改变PDO DBLIB(因为Microsoft的Unicode PDO_ODBC在linux上是barely supported).这是一个解决方法.

有条件地将输入字符串编码为base64.毕竟,这就是我们可以安全地按照电子邮件传输图片.

工作实例:

$DBH = new PDO("dblib:host=$myServer;dbname=$myDB;",$myPass);

$query = "
INSERT INTO [StackOverflow].[dbo].[UserSignUpInfo]
           ([FirstName])
     VALUES
           (:firstname)";

$STH = $DBH->prepare($query);

$firstname = "输入中国文字!Okay!";

/* First,check if this string has any Unicode at all */
if (strlen($firstname) != strlen(utf8_decode($firstname))) {
    /* If so,change the string to base64. */
    $firstname = base64_encode($firstname);
}

$STH->bindParam(':firstname',$firstname);
$STH->execute();

然后向后退,您可以测试base64字符串,并仅解码它们,而不会损坏现有条目,如下所示:

while ($row = $STH->fetch()) {
    $entry = $row[0];

    if (base64_encode(base64_decode($entry,true)) === $entry) {

         /* Decoding and re-encoding a true base64 string results in the original entry */
         print_r(base64_decode($entry) . PHP_EOL);

    } else {

         /* PrevIoUs entries not encoded will fall through gracefully */
         print_r($entry  . PHP_EOL);
    }
}

条目将被保存如下:

Guan Tianlang
5pys6Kqe44KS5a2maGVsbG8=

但是您可以轻松地将其转换回:

Guan Tianlang
输入中国文字!Okay!

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 'EastRiver' 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...