【问题标题】:sqlsrv_query returns no rows, no errors for a long querysqlsrv_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),并对您在第一列中实际存储的内容进行一些假设。

标签: php sql-server sqlsrv


【解决方案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."); } 
?>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-08-16
    • 2017-04-04
    • 2022-01-24
    • 2015-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-04
    相关资源
    最近更新 更多