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

PHP sqlsrv PDOStatement::rowCount返回-1但fetch可正常获取结果问题

问题原因

PDO_SQLSRV驱动对rowCount()方法的返回逻辑有特殊规则:

  • 默认情况下,rowCount()仅返回INSERT/UPDATE/DELETE这类写操作的影响行数,SELECT查询不会修改数据,默认返回-1
  • 即使开启了滚动游标PDO::CURSOR_SCROLL,如果SQL语句包含多段执行逻辑(比如你代码里先DECLARE定义变量、SET赋值,再执行SELECT),驱动会被前面非查询语句的执行计数干扰,无法正确识别最终SELECT返回的行数,就会返回-1
可落地的解决方案

你可以任选以下任意一种方案解决问题:

  • 方案1(最稳妥,全驱动兼容):放弃用rowCount()统计SELECT结果行数,改用fetchAll()获取全部结果后用count()统计
    $queryLoc->execute();
    // 先拿到所有查询结果
    $resultList = $queryLoc->fetchAll(PDO::FETCH_ASSOC);
    // 直接统计数组长度得到行数
    $numero = count($resultList);
    
    echo $numero;
    echo "<h1>MEDIA INCASSI DAL ".date('d-m-Y',strtotime($dataInizio))." AL ".date('d-m-Y',strtotime($dataFine))."</h1>";
    
    $id=0;
    // 遍历数组即可,不用再fetch
    foreach($resultList as $resultLoc){
      // 原有业务逻辑不变
    }
    
  • 方案2(优化写法同时解决问题):删除SQL内的变量声明逻辑,改用PDO参数绑定传参,单条SELECT语句下滚动游标可正常统计行数,同时还能解决原代码的SQL注入风险
    // 去掉DECLARE/SET部分,直接用占位符传参
    $sqlLoc= "
      SELECT noteincassi.CodLocale,Insegna,Citta
      FROM [Edera].[dbo].[NoteIncassi]
      JOIN edera.dbo.AnagraficaLocali ON AnagraficaLocali.CodLocale=NoteIncassi.CodLocale
      WHERE DataIncasso >= ?  AND DataIncasso <= ? AND tipoincasso = '6' AND sospeso = 0
      GROUP BY noteincassi.CodLocale,insegna,Citta
      ORDER BY Insegna
    ";
    $queryLoc = $conn->prepare($sqlLoc,array(PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL));
    // 绑定参数执行
    $queryLoc->execute([$dataInizio, $dataFine]);
    // 此时rowCount()可返回正确行数
    echo $numero=$queryLoc->rowCount();
    
  • 方案3(最小改动适配原有SQL):在SQL开头加SET NOCOUNT ON;,屏蔽前面非查询语句的计数干扰,驱动可正常获取最终SELECT的行数
    $sqlLoc= "
      -- 新增这一行即可
      SET NOCOUNT ON;
      DECLARE @Data2 AS DATE; 
      SET @Data2 = CONVERT(DATE,CONVERT(date, '$dataFine'), 102);
      
      DECLARE @Data1 AS DATE;
      SET @Data1 = CONVERT(DATE,CONVERT(date, '$dataInizio'), 102);
      
      SELECT noteincassi.CodLocale,Insegna,Citta
      FROM [Edera].[dbo].[NoteIncassi]
      JOIN edera.dbo.AnagraficaLocali ON AnagraficaLocali.CodLocale=NoteIncassi.CodLocale
      WHERE DataIncasso >= @Data1  AND DataIncasso <= @Data2 AND tipoincasso = '6' AND sospeso = 0
      GROUP BY noteincassi.CodLocale,insegna,Citta
      ORDER BY Insegna
    ";
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 21:24:00