sqlsrv_query 不返回行,长查询没有错误

Posted

技术标签:

【中文标题】sqlsrv_query 不返回行,长查询没有错误【英文标题】:sqlsrv_query returns no rows, no errors for a long query 【发布时间】:2022-01-08 00:48:55 【问题描述】:

我有一个异常长的查询(我们的系统为 13 秒+),在使用 sqlsrv_query 时没有返回任何结果,但是当我直接在服务器上输入 SQL 查询时给了我 331 行。 sqlsrv_num_rows 返回 0,sqlsrv_errors 为空。

<?php
$connInfo = array( "Database"=>"xxx", "UID"=>"xxx", "PWD"=>"xxx", "CharacterSet" => "UTF-8");
$conn = sqlsrv_connect('SQL2008', $connInfo);

if ($conn)
    
    $sql_q = "SELECT TblOrder.FldJobNb, TblOrder.FldOrdCre As DateReception, TblOrder.FldReclamerDate As DateDebutPORev, TblOrder.FldPOReviewApprovedDate As DateFinPORev,
                        TblOrder.FldPrinted, capsule_order.temps_reception_planification As DateReceptionPLANIF, TblOrder.FldPriced,
                        CASE
                            WHEN ISNULL(TblOrder.FldContractReviewCompletedDate, 0) = 0
                            THEN capsule_order.temps_reception_planification
                            ELSE TblOrder.FldContractReviewCompletedDate
                        END As TempsFinRevue,
                        (SELECT TOP 1 TblOrderXFeredNotifications.FldDate FROM [TCS].[dbo].[TblOrderXFeredNotifications] WHERE TblOrderXFeredNotifications.FldOrdID = TblOrder.FldOrdID ORDER BY TblOrderXFeredNotifications.FldNoLigne) As DatePlanification,
                        TblOrder.FldXfer2Sched, TblOrder.FldOrdMod As DateDernierMod, TblOrder.FldOrdStatusDate As DateDernierStatut, TblOrder.FldOrdReq As DateBesoin
                FROM [TCS].[dbo].[TblOrder] RIGHT JOIN [TCS].[dbo].[capsule_order] ON TblOrder.FldJobNB = capsule_order.FldJobNB
                WHERE '" . $dateDebut->format('Y-m-d H:i:s.').'000' . "' <= TblOrder.FldOrdCre AND TblOrder.FldOrdCre <= '" . $dateFin->format('Y-m-d H:i:s.').'000' . "'";
// die($sql_q);  Query that I enter into SQL Server and gives me 331 results after 13secs
    $query= sqlsrv_query($conn, $sql_q, array(), array( "Scrollable" => 'static' ));

    if ($query)
        
        if (sqlsrv_num_rows($query) > 0)
            
            while ($result= sqlsrv_fetch_array($query))
                
                // ...
                
            
        else
             die(var_dump(sqlsrv_num_rows($query))); 
        
    else
         die("query".$sql_q.'<br>'.print_r( sqlsrv_errors(), true)); 
    
else
     die ("Connection défectueuse.");  ?>

非常感谢您的支持,

雷诺

【问题讨论】:

学习使用最佳实践编写 TSQL。为您的表提供别名并将它们用于每个列引用。当心使用 3 部分名称的问题 - 您的连接通常应确定用于对象引用的数据库。您的 RIGHT JOIN 因您对 TblOrder 中列的引用而失败 - 将其转换为内部连接。 简化你的生活(也许可以避免逻辑问题)。您的 CASE 表达式可以重写为 ISNULL(TblOrder.FldContractReviewCompletedDate, TblOrder.FldContractReviewCompletedDate),并对您在第一列中实际存储的内容进行一些假设。 【参考方案1】:

您可以考虑以下几点:

使用明确的datetime 格式(yyyy-mm-ddThh:mm:ss.zzz)将datetime 值传递给SQL Server(我的经验总结为here)。 不要连接字符串来生成语句。始终使用准备好的语句和参数化查询来防止 SQL 注入。使用 PHP Driver for SQL Server,函数 sqlsrv_query() 既可以进行语句准备,也可以执行语句,并可用于执行参数化查询。 如果您想检查当前语句的结果集是否包含一行或多行,您可以使用 sqlsrv_has_rows() 而不是 sqlsrv_num_rows() 并使用默认 (forward) 游标。

以下示例基于您的代码,是 ypur 问题的可能解决方案:

<?php
$connInfo = array( "Database"=>"xxx", "UID"=>"xxx", "PWD"=>"xxx", "CharacterSet" => "UTF-8");
$conn = sqlsrv_connect('SQL2008', $connInfo);

if ($conn)
    
    $sql_q = "
        SELECT 
            TblOrder.FldJobNb, 
            TblOrder.FldOrdCre As DateReception, 
            TblOrder.FldReclamerDate As DateDebutPORev, 
            TblOrder.FldPOReviewApprovedDate As DateFinPORev,
            TblOrder.FldPrinted, capsule_order.temps_reception_planification As DateReceptionPLANIF, TblOrder.FldPriced,
            CASE
                WHEN ISNULL(TblOrder.FldContractReviewCompletedDate, 0) = 0 THEN capsule_order.temps_reception_planification
                ELSE TblOrder.FldContractReviewCompletedDate
            END As TempsFinRevue,
            (
            SELECT TOP 1 TblOrderXFeredNotifications.FldDate 
            FROM [TCS].[dbo].[TblOrderXFeredNotifications] 
            WHERE TblOrderXFeredNotifications.FldOrdID = TblOrder.FldOrdID 
            ORDER BY TblOrderXFeredNotifications.FldNoLigne
            ) As DatePlanification,
            TblOrder.FldXfer2Sched, 
            TblOrder.FldOrdMod As DateDernierMod, 
            TblOrder.FldOrdStatusDate As DateDernierStatut, 
            TblOrder.FldOrdReq As DateBesoin
        FROM [TCS].[dbo].[TblOrder] 
        RIGHT JOIN [TCS].[dbo].[capsule_order] ON TblOrder.FldJobNB = capsule_order.FldJobNB
        WHERE ? <= TblOrder.FldOrdCre AND TblOrder.FldOrdCre <= ?
    ";
    $query = sqlsrv_query(
        $conn, 
        $sql_q, 
        array($dateDebut->format('Y-m-d\TH:i:s').'.000', $dateFin->format('Y-m-d\TH:i:s').'.000')
    );
    if ($query)
        
        if (sqlsrv_has_rows($query))
            
            while ($result= sqlsrv_fetch_array($query))
                
                // ...
                
            
        else
             die(var_dump(sqlsrv_num_rows($query))); 
        
    else
         die("query".$sql_q.'<br>'.print_r( sqlsrv_errors(), true)); 
    
else
     die ("Connection défectueuse.");  
?>

【讨论】:

以上是关于sqlsrv_query 不返回行,长查询没有错误的主要内容,如果未能解决你的问题,请参考以下文章

在 PHP 中使用带有 sqlsrv_query 函数的临时表不会产生任何结果

PHP sql查询不返回表格内容

尽管表上存在行,但休眠查询不返回任何内容

sqlsrv_num_rows 不返回任何值

VBA选择不返回任何行

Oracle - 查询没有返回结果时显示“无行”