sqlsrv_fetch_array()返回一个空字符串,而sqlsrv_has_rows()返回true

时间:2014-05-02 16:42:58

标签: php sqlsrv

虽然我对php和ajax比较陌生,但我一定会彻底研究这个问题。我有一个PHP脚本(Environment.php)调用我的数据库并成功填充导航面板与我的所有环境。点击环境(这是一个指向javascript函数的超链接)后,环境信息应该通过ajax填充导航菜单旁边的div,调用另一个php脚本(GetEnvironment.php)。此脚本与之前的脚本具有相同的数据库和代码,具有不同的查询。

现在,任何理智的人都会说,“一定是查询。”当我打印出查询并在SSMS中运行它时,我得到了我想要的那一行。当我检查sqlsrv_has_rows()时,它返回true。当我运行sqlsrv_fetch_array()时,它返回一个空字符串。当我从查询中删除WHERE子句时,它返回环境数组就好了。 “那么它必须是查询中的where子句!”你是这么认为的,但是 - 就像我说的那样,打印出我的php正在使用的查询,并将此查询粘贴到SSMS中时,它会完美地返回。

如果我将where子句更改为“WHERE is_active = 1”或“WHERE e.env_type_id = 1”,我会得到结果。如果我将where子句更改为“WHERE e.id = 102”或“WHERE e.short_desc ='ABB'”,我会遇到同样的问题。重要的是要注意is_active有点,env_type_id是tinyint,而id是int,short_desc是varchar。

请记住,所有这些查询都在SSMS中进行了双重检查,因为它们会返回结果。我对id进行了硬编码,但没有区别,所以它不应该是$ _GET ['id']。

在我打电话的同时在数据库上运行跟踪时,没有记录任何错误,它似乎工作正常。在安装netbeans并尝试调试问题可能时,我仍然找不到根本原因。

Environment.php

<!DOCTYPE html>
<html>
    <head>
        <link href='../CSS/Primary.css' rel='stylesheet' type='text/css' />
        <script>
            function loadEnvInfo(id)
            {
                var xmlhttp;
                <!-- The XMLHttpRequest object is used to exchange data with a server behind the scenes. This means that it is possible to update parts of a web page, without reloading the whole page. -->
                if (window.XMLHttpRequest)
                {// code for IE7+, Firefox, Chrome, Opera, Safari
                    xmlhttp=new XMLHttpRequest();
                }
                else
                {// code for IE6, IE5
                    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
                }

                xmlhttp.onreadystatechange=function()
                                            {
                                                if (xmlhttp.readyState===4 && xmlhttp.status===200)
                                                {
                                                    document.getElementById("envInfo").innerHTML = xmlhttp.responseText;
                                                }
                                            };
                xmlhttp.open("GET","GetEnvironment.php?id="+id,true);
                xmlhttp.send();
            }
    </script>
</head>
<body>
    <div id="pagewidth">
        <div id="header">
            <h2><a href="../index.php">Home</a>
            <a href="Environment.php">Environments</a>
        </div>
        <div id="wrapper">
            <div id="nav">
                <?php
                    $serverName = "myServer\myInstance";
                    $connectionInfo = array( "Database"=>"myDatabase");
                    $conn = sqlsrv_connect( $serverName, $connectionInfo);

                    if ($conn === false)
                    {
                        echo "Connection could not be established.<br />";
                        die( print_r( sqlsrv_errors(), true));
                    }

                    $query = "SELECT e.id,e.long_desc,et.short_desc FROM myTable e INNER JOIN myOtherTable et ON e.env_type_id = et.id";

                    $returnedValue = sqlsrv_query($conn, $query);

                    if ($returnedValue === false)
                    {
                        die(print_r(sqlsrv_errors(),true));
                    }

                    if (sqlsrv_fetch_array($returnedValue) === false)
                    {
                        echo "fetch error";
                    }

                    $envTypes = array();

                    while ( $row = sqlsrv_fetch_array( $returnedValue, SQLSRV_FETCH_ASSOC) )
                    {
                        $env_type = $row['short_desc'];
                        if (array_key_exists($env_type, $envTypes) == false)
                        {
                            $envTypes[$env_type] = array($row['id']=>$row['long_desc']);
                        }

                        $envTypes[$env_type][$row['id']] = $row['long_desc'];
                    }

                    echo "<ul>";

                    foreach($envTypes as $et=>$et_value)
                    {
                        echo "<li>".$et;

                        if(count($et_value) > 0)
                        {
                            echo "<ul>";

                            foreach($et_value as $id=>$long_desc)
                            {
                                echo "<li><a href=\"javascript:loadEnvInfo(".$id.")\">".$long_desc."</a></li>";
                            }

                            echo "</ul>";
                        }

                        echo "</li>";
                    }

                    echo "</ul>";

                    /* Close the connection. */
                    sqlsrv_free_stmt( $returnedValue);
                    sqlsrv_close( $conn);
                ?>
            </div>
            <div id="maincol">
                <div id="envName"><h1>Environment</h1></div>
                <div id="envInfo"><h2>Environment Info</h2></div>
            </div>
        </div>
    </div>
</body>
</html>

GetEnvironment.php

<?php
    $serverName = "myServer\myInstance";
    $connectionInfo = array( "Database"=>"myDatabase");
    $conn = sqlsrv_connect( $serverName, $connectionInfo);

    if ($conn === false)
    {
        echo "Could not connect.\n";
        die( print_r( sqlsrv_errors(), true));
    }

    $query = "SELECT e.[id]
            ,e.[short_desc]
            ,e.[long_desc]
            ,e.[is_active]
            ,et.[short_desc] as env_type
            FROM [myTable] e
            INNER JOIN [myOtherTable] et on e.[env_type_id] = et.[id]
            WHERE e.[id] = ".$_GET['id'];

    // Returns SELECT e.[id] ,e.[short_desc] ,e.[long_desc] ,e.[is_active]
    // ,et.[short_desc] as env_type
    // FROM [myTable] e
    // INNER JOIN [myOtherTable] et on e.[env_type_id] = et.[id]
    // WHERE e.[id] = 102
    echo "Query: ".$query."<br />";

    $returnedValue = sqlsrv_query($conn, $query);

    // $returnedValue returns "Resource id #3"
    if ($returnedValue === false)
    {
        echo "Error in query preparation/execution.<br />";
        die(print_r(sqlsrv_errors(),true));
    }

    if (sqlsrv_fetch_array($returnedValue) === false)
    {
        echo "fetch error";
        die(print_r(sqlsrv_errors(),true));
    }

    // Returns "Has Rows!"
    if (sqlsrv_has_rows($returnedValue))
    {
        echo "Has Rows!";
    }
    else
    {
        echo "No Rows!";
    }

    // Returns "empty string"
    if (sqlsrv_fetch_array($returnedValue) == "")
    {
        echo "empty string";
    }
    else if (sqlsrv_fetch_array($returnedValue) == null)
    {
        echo "null";
    }

    // Does not enter the while loop, skips over it to close the connection
    while ( $row = sqlsrv_fetch_array( $returnedValue, SQLSRV_FETCH_ASSOC ))
    {
        echo "Inside While loop!";
    }

    /* Close the connection. */
    sqlsrv_free_stmt( $returnedValue);
    sqlsrv_close( $conn);
?>

3 个答案:

答案 0 :(得分:1)

通常情况下,最好改变查询方式,使其更加“安全”。

$query = sprintf(
    "SELECT e.[id]
        ,e.[short_desc]
        ,e.[long_desc]
        ,e.[is_active]
        ,et.[short_desc] as env_type
        FROM [myTable] e
        INNER JOIN [myOtherTable] et on e.[env_type_id] = et.[id]
        WHERE e.[id] = '%s'",
     addslashes($_GET['id']));

这样可以防止对数据库造成任何类型的攻击,并在您的ID周围添加单个刻度可能会解决您遇到的问题。

答案 1 :(得分:1)

删除if语句(检查我的returnedValue是否有任何值)后,脚本开始工作。这是工作的PHP。我将继续研究这个问题,看看我是否能找到这个脚本的工作原理,而我的原始脚本却没有。对此问题的任何其他见解将非常感激。


我建议的答案:通过在if语句中调用sqlsrv_fetch_array($ returnedValue),我从返回的值中删除了数组。我已经拿出了信息,并试图再次调用相同的引用,它返回给我一个空字符串,因为它不再包含该数组。

使用php:

<?php
    $serverName = "myServer\myInstance";
    $connectionInfo = array( "Database"=>"myDatabase");
    $conn = sqlsrv_connect( $serverName, $connectionInfo);

    if ($conn === false)
    {
         echo "Could not connect.\n";
         die( print_r( sqlsrv_errors(), true));
    }

    $query = "SELECT e.[id]
        ,e.[short_desc]
        ,e.[long_desc]
        ,e.[is_active]
        ,et.[short_desc] as env_type
        FROM [myTabel] e
        INNER JOIN [myOtherTable] et on e.[env_type_id] = et.[id]
        WHERE e.[id] = ".$_GET['id'];

    $returnedValue = sqlsrv_query($conn, $query);

    if( $returnedValue === false)
    {
         echo "Error in query preparation/execution.\n";
         die( print_r( sqlsrv_errors(), true));
    }

    while ( $row = sqlsrv_fetch_array( $returnedValue, SQLSRV_FETCH_ASSOC ))
    {
        echo "Inside loop!";
    }

    /* Free statement and connection resources. */
    sqlsrv_free_stmt($returnedValue);
    sqlsrv_close( $conn);
?>

答案 2 :(得分:0)

正如提问者的回答所述,脚本在if语句中使用:

获取一个数组

if (sqlsrv_fetch_array($returnedValue) === false)

如果您想检查sqlsrv_fetch_array()的结果并成功获取所有结果,那么我的建议如下:

$row = sqlsrv_fetch_array( $returnedValue, SQLSRV_FETCH_ASSOC );

if( $row === false ) {
   echo "Error while fetching array.\n";
   die( print_r( sqlsrv_errors(), true));
} else if( $row === null ) {
   echo "No results were found.\n";
} else {
   do {
      echo "Inside loop!";
   } while( $row = sqlsrv_fetch_array( $returnedValue, SQLSRV_FETCH_ASSOC ) );
}

sqlsrv_free_stmt( $returnedValue);
sqlsrv_close( $conn);

使用这种方法,您可以在至少在开始时获取数组时检查错误并控制空结果。