mysql_fetch_array()/ mysql_fetch_assoc()/ mysql_fetch_row()/ mysql_num_rows等…期望参数1是资源

我试图从MySQL表中选择数据,但是我收到以下错误消息之一:

mysql_fetch_array()期望参数1是资源,布尔给定

要么

mysqli_fetch_array()期望参数1是mysqli_result,布尔给定

要么

在布尔/非对象上调用成员函数fetch_array()

这是我的代码:

$username = $_POST['username'];
$password = $_POST['password'];

$result = mysql_query('SELECT * FROM Users WHERE UserName LIKE $username');

while($row = mysql_fetch_array($result)) {
    echo $row['FirstName'];
}

这同样适用于类似的代码

$result = mysqli_query($mysqli, 'SLECT ...');
// mysqli_fetch_array() expects parameter 1 to be mysqli_result, boolean given
while( $row=mysqli_fetch_array($result) ) {
    ...

$result = $mysqli->query($mysqli, 'SELCT ...');
// Call to a member function fetch_assoc() on a non-object
while( $row=$result->fetch_assoc($result) ) {
    ...

$result = $pdo->query('SLECT ...', PDO::FETCH_ASSOC);
// Invalid argument supplied for foreach()
foreach( $result as $row ) {
    ...

$stmt = $mysqli->prepare('SLECT ...');
// Call to a member function bind_param() on a non-object
$stmt->bind_param(...)

$stmt = $pdo->prepare('SLECT ...');
// Call to a member function bindParam() on a non-object
$stmt->bindParam(...)



答案

由于各种原因,查询可能会失败,在这种情况下,mysql_ *和mysqli扩展名将false从其各自的查询函数/方法返回。您需要测试该错误情况并相应处理。

mysql_ *扩展名

注:mysql_功能已被弃用,并在PHP版本7已被删除。

$result传递给它之前检查mysql_fetch_array。你会发现这是false因为查询失败。请参阅mysql_query文档以了解可能的返回值以及如何处理这些值的建议。

$username = mysql_real_escape_string($_POST['username']);
$password = $_POST['password'];
$result = mysql_query("SELECT * FROM Users WHERE UserName LIKE '$username'");

if($result === FALSE) { 
    die(mysql_error()); // TODO: better error handling
}

while($row = mysql_fetch_array($result))
{
    echo $row['FirstName'];
}

mysqli扩展
程序风格

$username = mysqli_real_escape_string($mysqli, $_POST['username']);
$result = mysqli_query($mysqli, "SELECT * FROM Users WHERE UserName LIKE '$username'");

// mysqli_query returns false if something went wrong with the query
if($result === FALSE) { 
    yourErrorHandler(mysqli_error($mysqli));
}
else {
    // as of php 5.4 mysqli_result implements Traversable, so you can use it with foreach
    foreach( $result as $row ) {
        ...

oo风格

$username = $mysqli->escape_string($_POST['username']);
$result = $mysqli->query("SELECT * FROM Users WHERE UserName LIKE '$username'");

if($result === FALSE) { 
    yourErrorHandler($mysqli->error); // or $mysqli->error_list
}
else {
    // as of php 5.4 mysqli_result implements Traversable, so you can use it with foreach
    foreach( $result as $row ) {
      ...

使用准备好的声明:

$stmt = $mysqli->prepare('SELECT * FROM Users WHERE UserName LIKE ?');
if ( !$stmt ) {
    yourErrorHandler($mysqli->error); // or $mysqli->error_list
}
else if ( !$stmt->bind_param('s', $_POST['username']) ) {
    yourErrorHandler($stmt->error); // or $stmt->error_list
}
else if ( !$stmt->execute() ) {
    yourErrorHandler($stmt->error); // or $stmt->error_list
}
else {
    $result = $stmt->get_result();
    // as of php 5.4 mysqli_result implements Traversable, so you can use it with foreach
    foreach( $result as $row ) {
      ...

这些例子只说明应该做什么(错误处理),而不是如何去做。or die输出HTML时,不应使用生产代码,否则(至少)会生成无效的HTML。此外,数据库错误消息不应该显示给非管理员用户,因为它泄露了太多信息


当您的查询中有错误导致错误时,会显示此错误消息。它将在使用时显现出来:

  • mysql_fetch_array/mysqli_fetch_array()
  • mysql_fetch_assoc()/mysqli_fetch_assoc()
  • mysql_num_rows()/mysqli_num_rows()

注意:如果没有行受到查询的影响,则不会显示此错误。只有具有无效语法的查询才会生成此错误。

故障排除步骤

  • 确保您的开发服务器配置为显示所有错误。你可以通过把它放在你的文件的顶部或者你的配置文件中来做到这一点:error_reporting(-1);。如果你有任何语法错误,这会将它们指向你。
  • 使用mysql_error()mysql_error()会报告MySQL在执行查询时遇到的任何错误。

    示例用法:

    mysql_connect($host, $username, $password) or die("cannot connect"); 
    mysql_select_db($db_name) or die("cannot select DB");
    
    $sql = "SELECT * FROM table_name";
    $result = mysql_query($sql);
    
    if (false === $result) {
        echo mysql_error();
    }
  • 从MySQL命令行或像phpMyAdmin这样的工具运行查询。如果你的查询语法错误,这会告诉你它是什么。
  • 确保你的报价是正确的。缺少关于查询或值的引用会导致查询失败。
  • 确保你逃脱了你的价值。查询中的引号可能会导致查询失败(并且还会让您打开SQL注入)。使用mysql_real_escape_string()逃脱你的输入。
  • 确保你没有混合mysqli_*mysql_*功能。它们不是一回事,也不能一起使用。(如果你打算选择其中一个,mysqli_*请参阅下面的原因。)

其他技巧

mysql_*函数不应该用于新代码。他们不再被维护,社区已经开始了贬值过程。相反,您应该了解准备好的声明并使用PDOMySQLi。如果你不能决定,这篇文章将有助于选择。如果你在意学习,这里有很好的PDO教程


这里发生的错误是由于使用单引号(')。你可以把你的查询像这样:

mysql_query("
SELECT * FROM Users 
WHERE UserName 
LIKE '".mysql_real_escape_string ($username)."'
");

mysql_real_escape_string用于预防SQL注入。尽管我们应该使用MySQLi或PDO_MYSQL扩展来升级PHP版本(PHP 5.5.0及更高版本),但对于旧版本mysql_real_escape_string将会有所斩获。


正如scompt.com解释的那样,查询可能会失败。使用此代码获取查询的错误或正确的结果:

$username = $_POST['username'];
$password = $_POST['password'];

$result = mysql_query("
SELECT * FROM Users 
WHERE UserName LIKE '".mysql_real_escape_string($username)."'
");

if($result)
{
    while($row = mysql_fetch_array($result))
    {
        echo $row['FirstName'];
    }
} else {
    echo 'Invalid query: ' . mysql_error() . "\n";
    echo 'Whole query: ' . $query; 
}

请参阅文档以mysql_query()获取更多信息。

实际的错误是单引号,因此该变量$username未被解析。但是你应该真的用它mysql_real_escape_string($username)来避免SQL注入。

Tags:,

添加评论

友情链接:蝴蝶教程