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

PHP PDO:SQLSRV/SQLSRV连接MS SQL执行复合SQL无结果求助

问题分析与解决方案

你的问题核心在于:你的SQL语句会返回多个结果集,而PHP的两个SQL Server扩展默认只会处理第一个结果集,导致了不同的异常表现:

  • PDO_SQLSRV的第一个结果集是INSERT操作的影响行数(没有字段),调用fetch()时就会抛出"The active result for the query contains no fields"错误;
  • SQLSRV扩展同样只处理第一个结果集(无有效数据),所以sqlsrv_fetch_array()拿不到内容,自然没有输出。

而SQL Server Management Studio会自动解析并展示所有结果集,所以你能正常看到返回数据。


针对PDO_SQLSRV的修改方案

你需要手动遍历所有结果集,跳过没有字段的结果集,直到获取到包含数据的那个结果集:

<?php
try {
    $db = new PDO("sqlsrv:Server=sql_server;Database=database", "username", "password");
    $db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
    $test = $db->prepare('declare @t2 code.instancereferencestable; insert into @t2 select top 10 [Instance Reference] from imported.instance where [Instance Type] = \'CENAS\' and [Instance Reference] = \'CENAS.8000\' order by [Instance (Id)] desc; select * from transformed.attribute_instance_extended_from_references(@t2)');
    $test->execute();

    // 遍历所有结果集,筛选出有数据的结果
    do {
        if ($test->columnCount() > 0) {
            // 处理有效结果集
            $result = $test->fetch(PDO::FETCH_OBJ);
            print_r($result);
        }
    } while ($test->nextRowset());

    echo "Connected!". "\n";
} catch(Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}
?>

关键逻辑是用columnCount()判断当前结果集是否包含字段,并用nextRowset()切换到下一个结果集。


针对SQLSRV扩展的修改方案

同样需要手动切换到下一个结果集,因为第一个结果集是INSERT的执行状态,第二个才是你需要的查询结果:

<?php
$serverName = "sql_server";
$connectionOptions = array(
    "Database" => "database",
    "Uid" => "username",
    "PWD" => "password"
);
$conn = sqlsrv_connect($serverName, $connectionOptions);
if ( $conn ) {
    echo "Connection established.".PHP_EOL;
    $sql = ("declare @t2 code.instancereferencestable; insert into @t2 select top 10 [Instance Reference] from imported.instance where [Instance Type] = 'CENAS' and [Instance Reference] = 'CENAS.8000' order by [Instance (Id)] desc; select * from transformed.attribute_instance_extended_from_references(@t2);");
    $stmt = sqlsrv_query($conn, $sql);
    if ( $stmt === false ) {
        die( print_r( sqlsrv_errors(), true));
    } else {
        // 跳过第一个无数据的结果集(INSERT操作的返回)
        sqlsrv_next_result($stmt);
        // 循环获取第二个结果集的所有数据
        while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
            print_r ($row);
        }
    }
} else {
    echo "Connection could not be established.".PHP_EOL;
    die( print_r( sqlsrv_errors(), true)).PHP_EOL;
}
?>

这里用sqlsrv_next_result()切换到第二个结果集,再循环读取所有数据。


额外提示

如果你的SQL语句中包含多个SELECT、存储过程调用这类会返回结果的操作,都需要注意处理多结果集的情况。两个扩展都不会自动跳过无数据的结果集,必须手动处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:57:24