MSSQL存储过程插入阿拉伯语乱码问题求助
问题背景
现有MS SQL数据库默认排序规则为SQL_Latin1_General_CP1_CI_AS,已将表myTable的cLineNotes列修改为NVARCHAR(MAX)并指定排序规则Arabic_CI_AI_KS_WS,但通过存储过程插入/更新数据时,阿拉伯语内容出现乱码——示例输入اختبار يونيكود存入后变为ط§ط®طھط¨ط§ط± ظٹظˆظ†ظٹظƒظˆط¯,存储过程本身可正常保存执行。
涉及代码
修改列的SQL语句:
ALTER TABLE myTable ALTER COLUMN cLineNotes nvarchar(max) COLLATE Arabic_CI_AI_KS_WS
存储过程代码:
CREATE PROCEDURE spMyProcedure ... --3 more lines here @pcLineNotes nvarchar(max) AS BEGIN SET NOCOUNT ON; ... -- more lines here INSERT INTO myTable (cLineNotes ) VALUES (@pcLineNotes ) ... -- more lines here END
PHP连接与调用代码:
// 数据库连接配置 $connectionInfo = array("Database" => $this->db_name, "UID" => $this->db_user, "PWD" => $this->db_pwd , "CharacterSet" => "UTF-8"); // 调用存储过程 $query = "{CALL spMyProcedure( ?,?,?,? )}"; $params = array( array($param1, SQLSRV_PARAM_IN,), array(&$param2, SQLSRV_PARAM_IN), array(&$param3, SQLSRV_PARAM_IN), array(&$cLineNotes, SQLSRV_PARAM_IN) );
问题原因
乱码是典型的UTF-8字符串被错误解析为单字节编码导致的:虽然目标列已配置为Unicode类型,但存储过程的参数未明确指定匹配的排序规则,且PHP传递参数时未标记为Unicode类型,导致SQL Server将传入的UTF-8内容按Latin1编码解析后再转存为Unicode,最终出现乱码。
解决方案
1. 为存储过程参数指定匹配的排序规则
修改存储过程的参数定义,添加与目标列一致的排序规则,确保参数接收的Unicode字符串按正确规则处理:
CREATE PROCEDURE spMyProcedure ... -- 其他参数 @pcLineNotes nvarchar(max) COLLATE Arabic_CI_AI_KS_WS AS BEGIN SET NOCOUNT ON; ... -- 其他逻辑 INSERT INTO myTable (cLineNotes ) VALUES (@pcLineNotes ) ... -- 其他逻辑 END
2. PHP调用时明确标记参数为Unicode类型
在PHP的参数数组中,为cLineNotes参数指定SQLSRV_SQLTYPE_NVARCHAR类型,让SQL Server明确识别这是Unicode参数:
$params = array( array($param1, SQLSRV_PARAM_IN), array(&$param2, SQLSRV_PARAM_IN), array(&$param3, SQLSRV_PARAM_IN), array(&$cLineNotes, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_NVARCHAR('max')) );
注:若使用新版SQLSRV扩展,可简化为直接指定SQLSRV_SQLTYPE_NVARCHAR常量。
3. 验证连接字符集(可选)
若前两步仍未解决,可检查数据库连接的排序规则是否生效:
SELECT CONVERT(varchar(100), SESSIONPROPERTY('Collation'));
若返回结果与Arabic_CI_AI_KS_WS不符,可在连接配置中添加排序规则指定:
$connectionInfo = array( "Database" => $this->db_name, "UID" => $this->db_user, "PWD" => $this->db_pwd, "CharacterSet" => "UTF-8", "ConnectionCollation" => "Arabic_CI_AI_KS_WS" );
验证
插入示例值اختبار يونيكود,检查数据库中存储的内容是否与输入完全一致。
内容的提问来源于stack exchange,提问作者Nathan DevX

