嵌套查询 - 内部查询循环结束外部查询循环

Posted

技术标签:

【中文标题】嵌套查询 - 内部查询循环结束外部查询循环【英文标题】:nested queries - inner query loop ends outer query loop 【发布时间】:2019-07-17 16:11:42 【问题描述】:

我有 2 个查询循环遍历它们的记录集以从内部循环提供输出。外部查询循环有几条记录,内部查询应该为每条记录触发。一旦内部循环运行,我只会得到外部查询循环的第一个 recoed。

我尝试将内部查询的 $result 命名为 $result2 并得到错误:sqlsrv_fetch_array(): 提供的资源不是有效的 ss_sqlsrv_stmt 资源。

// outer loop
$serverName = "livedata";
$connectionInfo = array( "Database"=>"ParishHomilyArchive", "UID"=>"ParishUser", "PWD"=>"P@\$\$word" );
$conn = sqlsrv_connect( $serverName, $connectionInfo);
if( $conn === false ) 
 die( print_r( sqlsrv_errors(), true));


if (isset($_REQUEST['Par_Num']))
    $PN = $_REQUEST['Par_Num'];

else
    $PN = 0;


$sql="SELECT Staff.StaffID, Staff.Name, Staff.Photo,     Staff_Position.StaffPage_ID, StaffPages.StaffPageName FROM parishStaff.dbo.StaffPages RIGHT JOIN (ParishStaff.dbo.Staff_Position RIGHT JOIN ParishStaff.dbo.Staff ON Staff_Position.Staff_ID = Staff.StaffID) ON StaffPages.StaffPageID = Staff_Position.StaffPage_ID WHERE (((Staff.par_Num)=" . $PN . ")) ORDER BY Staff.Name, StaffPages.StaffPageName;";



$stmt = sqlsrv_query( $conn, $sql);
if( $stmt === false ) 
     die( print_r( sqlsrv_errors(), true));


$result = sqlsrv_query($conn, $sql);

while($row = sqlsrv_fetch_array($result)) 

    //output outer loop stuff



    //inner loop
    $serverName = "livedata";
    $connectionInfo = array( "Database"=>"database", "UID"=>"User", "PWD"=>"password" );
    $conn = sqlsrv_connect( $serverName, $connectionInfo);
    if( $conn === false ) 
         die( print_r( sqlsrv_errors(), true));
    

    if (isset($_REQUEST['Par_Num']))
        $PN = $_REQUEST['Par_Num'];
    
    else
        $PN = 0;
    

    $sql2="SELECT StaffPages.StaffPageID, StaffPages.StaffPageName FROM parishStaff.dbo.ParishPages INNER JOIN ParishStaff.dbo.StaffPages ON ParishPages.StaffPage_ID = StaffPages.StaffPageID WHERE (((ParishPages.Par_Num)=" . $PN . ") AND (Not (StaffPages.StaffPageID)=(SELECT StaffPages.StaffPageID FROM ParishStaff.dbo.StaffPages LEFT JOIN (ParishStaff.dbo.Staff_Position LEFT JOIN ParishStaff.dbo.Staff ON Staff_Position.Staff_ID = Staff.StaffID) ON StaffPages.StaffPageID = Staff_Position.StaffPage_ID WHERE (((Staff.StaffID)=" . $row['StaffID']. " )))));"; 

    $stmt = sqlsrv_query( $conn, $sql2);
    if( $stmt2 === false ) 
         die( print_r( sqlsrv_errors(), true));
    
    $result = sqlsrv_query($conn, $sql2);

    while($row2 = sqlsrv_fetch_array($result)) 

        //output inner loop stuff

    




我希望外循环在内循环的第一次迭代后不结束。

【问题讨论】:

您迫切需要阅读、理解并开始使用参数化查询。您的代码对 sql 注入是开放的。看看我的朋友bobby tables。他解释了这是多么危险以及如何解决它。 我同意@SeanLange,但除此之外,您在内部和外部循环中都使用相同的变量($result),这是有问题的。 【参考方案1】:

回答您的问题我稍微重新排列了您的代码,并在外循环结果集和内循环结果集上设置了不同的变量。我还删除了实际上无用的代码,例如:

$stmt = sqlsrv_query( $conn, $sql2);
if( $stmt2 === false ) 
     die( print_r( sqlsrv_errors(), true));

$result = sqlsrv_query($conn, $sql2);

Above 在$stmt 中创建一个结果集,然后在$result 中创建一个结果集。这里只需要调用一次sqlserver。

<?php
//This is BEFORE loop.. Just need to connect once
$serverName = "livedata";
$connectionInfo = array( "Database"=>"dbname", "UID"=>"user", "PWD"=>"password" );
$conn = sqlsrv_connect( $serverName, $connectionInfo);
if( $conn === false ) 
 die( print_r( sqlsrv_errors(), true));


if (isset($_REQUEST['Par_Num']))
    $PN = $_REQUEST['Par_Num'];

else
    $PN = 0;


$sql="your SQL-statement";
$result_outerloop = sqlsrv_query($conn, $sql);
if( $result_outerloop === false ) 
     die( print_r( sqlsrv_errors(), true));


while($row = sqlsrv_fetch_array($result_outerloop)) 

    $sql2="your SQL-statement"; 
    $result_innerresult = sqlsrv_query($conn, $sql2); //Not same variable as $result_outerloop
    if( $result_innerresult === false ) 
        die( print_r( sqlsrv_errors(), true));
    

    while($row2 = sqlsrv_fetch_array($result_innerresult)) 
        //output inner loop stuff
    


但正如@Sean Lange 指出的那样,SQL 本身根本不是好的做法。请阅读参数化查询。这实际上比按照你的方式做要容易得多。

【讨论】:

子查询返回多行时出现错误:子查询返回超过 1 个值。当子查询跟随 =、!=、、>= 或子查询用作表达式时,这是不允许的。我预计主查询中的某些结果会有多行。 我终于解决了这个问题。子查询循环正在查看办公室工作人员并查找该工作人员不属于的办公室。为此,我首先使用 Office_ID 查询所有办公室的列表。然后,我使用工作人员链接到的页面的子查询过滤了办公室列表。引用子查询时,我使用了不等于( )而不是我需要使用( not in )。这绕过了返回多个项目错误的子查询。

以上是关于嵌套查询 - 内部查询循环结束外部查询循环的主要内容,如果未能解决你的问题,请参考以下文章

SQL嵌套子查询和相关子查询的执行过程有啥区别

如何使用嵌套循环加速查询

使用嵌套循环提高 SQL 查询的性能 - PostgreSQL

具有深度嵌套数组循环的 SQL 查询 OpenJson

在 Redshift 中取消嵌套 json 会导致查询计划中出现嵌套循环

Oracle三层嵌套查询