使用PHP的sqlsrv_fetch_object读取MSSQL数据出现字符串右截断错误
错误触发原因
该错误是SQL Server for PHP驱动的常见问题,核心原因是驱动预先分配的字符串缓冲区长度小于实际返回的字段内容长度,触发右截断校验报错,常见触发场景如下:
- 使用
SQLSRV_CURSOR_KEYSET可滚动游标时,驱动会提前根据字段定义估算长度分配缓冲区,comments这类长文本字段如果某行存储内容长度超过估算值,就会触发报错 - 字符集不匹配也会导致长度计算错误:如果数据库字段是
nvarchar类型存储中文等多字节字符,驱动默认按单字节计算长度,多字节字符实际占用的缓冲区空间会超出估算值 - 视图本身的字段定义存在偏差:如果视图关联的底层表字段长度大于视图定义的对应字段长度,返回数据时也会触发截断
可行解决方案
按优先级从高到低测试即可:
- 调整连接与查询配置,解决字符集与长度预估问题
// 连接配置新增字符集参数,避免多字节长度计算错误 $connectionInfo = array( "UID"=>$uid, "PWD"=>$pwd, "Database"=>$databaseName, "CharacterSet" => "UTF-8" ); // 查询语句中对长文本字段做显式类型转换,指定足够大的长度,避免驱动预判错误 $tsql = "SELECT custCode, custName, CAST(comments AS NVARCHAR(MAX)) AS comments, incharge, currency, country, sellerID, sellerName, paymentMethod, category, dispatchMethod FROM [DataBase-Name].[dbo].[eshopCustomers]";
- 替换游标类型
如果你的业务不需要随机访问、倒序遍历结果集,直接去掉Scrollable参数使用默认前向游标即可,KEYSET游标本身的长度限制会消失:
// 去掉游标参数,使用默认前向游标 $stmt = sqlsrv_query($conn, $tsql);
- 临时关闭截断报错(仅排查用,不建议线上长期使用)
// 执行查询前设置,关闭字符串截断警告的错误抛出 sqlsrv_configure('WarningsReturnAsErrors', 0);
验证步骤
- 优先测试替换游标类型的方案,能正常返回数据即可确认是
KEYSET游标对长字段的长度预判错误导致 - 如果替换游标无效,再测试长字段显式转
NVARCHAR(MAX)的方案,同时确认视图关联的底层表字段长度定义无异常
内容的提问来源于stack exchange,提问作者netdev
相关产品推荐
相关产品推荐

