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

PHP使用sqlsrv_query查询SQL Server仅返回部分数据该如何解决

结论

该问题和数据量过大无关,4000行结构化数据的体量极小,完全可以正常获取全部查询结果,数据丢失是代码逻辑错误搭配SQLSRV扩展默认配置限制共同导致的。

根因分析

  • 代码逻辑bug:内层遍历行的while循环中,$j变量仅在进入每个结果集时初始化为0,遍历过程中没有做自增操作,每次读取新行都会覆盖$result[$i][0]的位置,正常逻辑下甚至只能拿到每个结果集的最后一行。你当前能拿到3000行是因为触发了第二个配置问题。
  • SQLSRV扩展默认缓冲区限制:sqlsrv扩展默认开启客户端结果缓存,单查询默认最多缓存2.5MB的结果数据,按你表的字段结构计算,单条行数据约850字节,2.5MB刚好只能缓存3000行左右,超出部分不会被加载到缓冲区,导致读取中断。

修复方案

1. 修复计数逻辑+调大缓冲区

你当前的代码外层do-while是用来处理多结果集的场景,如果你的业务确实存在多结果集返回的情况,可以用以下修复后的代码:

$sql = 'SELECT * FROM ExampleData';
// 调大客户端缓冲区到10MB,足够容纳全部4000行数据
$options = [
    'Scrollable' => SQLSRV_CURSOR_CLIENT_BUFFERED,
    'ClientBufferMaxKBSize' => 10240
];
$query = sqlsrv_query($conn, $sql, [], $options);

if ($query === false) return null;

$result = [];
do {
    $currentSet = [];
    while ($row = sqlsrv_fetch_array($query, SQLSRV_FETCH_ASSOC)) {
        // 直接用数组追加,不需要手动维护i、j计数,避免遗漏自增的问题
        $currentSet[] = $row;
    }
    if (!empty($currentSet)) {
        $result[] = $currentSet;
    }
} while (sqlsrv_next_result($query));

return $result;

2. 简化单结果集查询逻辑

你当前的SQL只有单条SELECT语句,不存在多结果集的情况,完全可以去掉外层do-while循环,代码简化后更不容易出问题:

$sql = 'SELECT * FROM ExampleData';
$options = ['ClientBufferMaxKBSize' => 10240];
$query = sqlsrv_query($conn, $sql, [], $options);

if ($query === false) return null;

$result = [];
while ($row = sqlsrv_fetch_array($query, SQLSRV_FETCH_ASSOC)) {
    $result[] = $row;
}
return $result;

验证方案

修改后可以先调用sqlsrv_num_rows($query)打印返回的总行数,确认SQL Server侧已经返回了全部4000行数据,再排查后续逻辑问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 04:24:01