Unicode符号变为“ ??????????”在PHP端,但数据为NVARCHAR,而SELECT显示正确的数据

时间:2018-09-15 09:34:55

标签: php sql-server collation iconv

我有一个数据库,该数据库具有SQL_Latin1_General_CP1_CI_AS排序规则,需要将其转换为utf8_unicode_ci排序规则。更改表不是一种选择。 MSSQL返回这样的数据:

[FirstName] => ??????????

但是像这样的真实数据:

[FirstName] => مریم

我尝试了以下方法:

$utf8[] = utf8_encode($saleagent['FirstName']);
$utf8[] = iconv('ISO-8859-1', 'UTF-8',$saleagent['FirstName']);
$utf8[] = mb_convert_encoding($saleagent['FirstName'], 'UTF-8', 'ISO-8859-1');

输出为:

Array
(
    [0] => ??????????
    [1] => ??????????
    [2] => ??????????
)

有什么方法可以将现有数据转换为utf8_unicode_ci?

修改


根据this answer,我更改了代码:

在SQL中:

CAST(p.FirstName AS VARBINARY(MAX)) as FirstName,

在PHP中,我编写了此函数来修复编码:

public function fixEncoding($string)
{
    $original = $string;
    $string = trim($string);
    // Detect the input string encoding.
    $encoding = mb_detect_encoding($string, mb_detect_order(), false);

    if ($encoding == 'UTF-8' || $encoding == false) {
        $hex = bin2hex($string);

        $str = "";
        for ($i = 0; $i < strlen($hex) - 1; $i += 2) {
            $str .= chr(hexdec($hex[$i] . $hex[$i + 1]));
        }
        $string = iconv('UCS-2LE', 'UTF-8', $str);
        return $string;

    } elseif ($encoding == 'ASCII') {
        $string = $original;
        return $string;
    }

    return $string;
}

让我解释一下情况。 我在mssql数据库中遇到了3种类型的字符串:

  1. 字符串,例如英语字符或数字:xyz 32 -
  2. 类似波斯字符的字符串:مریم دختر خوبی است
  3. 上面两个字符串都一样:مریم دختر خوبی است - Maryam is a good girl.

会发生什么,在 1 2 中的代码成功将其转换。但是,数字 3 在尝试用iconv进行转换时返回错误,并在下面抛出错误:

  

iconv():在输入字符串中检测到不完整的多字节字符

在这一行:

$string = iconv('UCS-2LE', 'UTF-8', $str);

您有解决所有3种情况的解决方案吗?

2 个答案:

答案 0 :(得分:1)

解决方案:

您可以尝试以下方法:

  • 以UTF-8编码您的html和php文件(此步骤我通常使用Notepad ++)。
  • 使用type Request struct { Method string `json:"func_name"` Params []interface{} `json:"params"` } requestType := reflect.TypeOf(**new(Request)**) 从MS SQL Server中选择值
  • 使用CONVERT(varbinary(max), UNICODECOLUMN);
  • 转换PHP部分中的值

您可以将功能更改为:

$value = iconv('UTF-16LE', 'UTF-8', $unicodetext);

示例:

<?php
...
public function fixEncoding($string) {
    return iconv('UTF-16LE', 'UTF-8', $string);
}
...
?>

注释:

示例使用PHP Driver for SQL Server,SQL Server 2012,带有<html> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta charset="utf-8"> </head> <body> <?php # Connection $server = "server\instance,port"; $user = "user"; $password = "password"; $database = "database"; $cinfo = array( "Database" => $database, "UID" => $user, "PWD" => $password ); $conn = sqlsrv_connect($server, $cinfo); if ($conn === false) { echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true); exit; } # Statement $sql = " SELECT CONVERT(varbinary(max), [NVARCHARTEXT]) AS [NVARCHARTEXT] FROM [dbo].UnicodeText "; $stmt = sqlsrv_query($conn, $sql); if ($stmt === false) { echo "Error (sqlsrv_prepare): ".print_r(sqlsrv_errors(), true); exit; } while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) { $value = $row["NVARCHARTEXT"]; $value = iconv('UTF-16LE', 'UTF-8', $value); echo $value.'</br>'; } # End sqlsrv_free_stmt($stmt); sqlsrv_close($conn); ?> </body> </html> 列的表。

答案 1 :(得分:0)

可能的原因:

  • 表/列未声明为UTF-8
  • 客户端中的字节未编码moment.locale('ja'); var d = moment().format('今: YYYY年M月D日 (ddd) HH時mm分ss秒'); console.log(d); -> 今: 2018年10月9日 (火) 11時03分06秒