You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP升级至8.3.8后PDO SQLSRV读取SQL timestamp类型异常问题

PHP 8.3.8 + PDO SQLSRV 读取SQL Server timestamp类型返回乱码的解决方法

在把PHP应用从5.4升级到8.3.8后,用PDO SQLSRV连接SQL Server时遇到了timestamp字段的读取问题——这里的timestamp是SQL Server用来做并发更新校验的8字节二进制类型,不是日期时间戳。旧版本PHP里查询会返回类似00000000009FA279的十六进制字符串,但升级后返回的是乱码(比如A�),虽然PDO能正确识别该列的类型为timestamp。

问题原因

SQL Server的timestamp本质是8字节二进制数据,PHP5.4对应的PDO SQLSRV驱动会自动将其转换为十六进制字符串返回;而适配PHP8+的新版驱动,改为直接返回原始二进制数据,直接输出就会显示成乱码。

解决方法

方法1:SQL查询时直接转换

在SELECT语句里用CONVERT函数把二进制数据转成十六进制字符串,这样不管PHP版本,返回的都是标准字符串:

$db = new PDO("sqlsrv:Server=MyServer;Database=MyDatabase", 'MyUser', 'MyPassword', array(PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_SYSTEM));
$stmt = $db->prepare('SELECT CONVERT(VARCHAR(MAX), [timestamp], 2) AS [timestamp] FROM MyTable WHERE Id= 1');
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
print_r($row);

参数2表示返回不带前缀的十六进制字符串,和PHP5.4的输出格式一致。

方法2:PHP层面编码二进制数据

如果不想修改SQL语句,直接在PHP里用bin2hex()对返回的二进制字段进行编码:

$db = new PDO("sqlsrv:Server=MyServer;Database=MyDatabase", 'MyUser', 'MyPassword', array(PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_SYSTEM));
$stmt = $db->prepare('SELECT [timestamp] FROM MyTable WHERE Id= 1');
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
// 将二进制数据转为十六进制字符串
$row['timestamp'] = bin2hex($row['timestamp']);
print_r($row);

补充说明

  • 方法1适合批量查询场景,减少PHP端的循环处理开销;
  • 方法2无需改动现有SQL逻辑,适配性更强;
  • 两种方法最终都能得到和PHP5.4环境一致的十六进制字符串结果,不影响原有并发校验逻辑。

内容的提问来源于stack exchange,提问作者Kyle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 05:32:36