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 不返回行,长查询没有错误的主要内容,如果未能解决你的问题,请参考以下文章