【问题标题】:PHP PDO: SQL query not returning expected resultPHP PDO:SQL 查询未返回预期结果
【发布时间】:2025-12-18 06:35:01
【问题描述】:

我在 PHP 中有一个函数(见底部),它查询 MySQL 数据库。 当我使用以下值时:

  • $map => 1,
  • $limit => 10,
  • $from => 0,
  • $to => CURRENT_TIMESTAMP

用SQL语句:

SELECT user,
       scoreVal AS score,
       UNIX_TIMESTAMP(timestamp) AS timestamp 
  FROM Score 
 WHERE timestamp >= :from 
   AND timestamp <= :to 
   AND map = :map 
 ORDER BY scoreVal DESC, timestamp ASC 
 LIMIT :limit

在 phpMyAdmin 中,我得到以下结果:

但是 PHP PDO 返回一个空数组。

到目前为止我的调试尝试:

  • 我已将他准备好的 SQL 查询替换为静态值而不是占位符 - 返回正确
  • 分别尝试每个占位符,用经过测试的硬编码值替换其余的 - 不返回任何内容
  • 我没有将变量传递给占位符,而是在 execute(Array()) 部分传递固定常量。 - 不返回任何内容。
  • 我在打开 mySQL 查询日志后还发现,PHP 客户端连接,但随后退出,没有发送任何查询。

据此,我认为这是函数中占位符的问题,但是我一直无法找到它们失败的原因。这很可能发生在 PHP 端,因为 MySQL 没有向错误文件抛出错误。

这是我正在使用的函数,其中传入了变量:

  • $map => 1,
  • $limit => 10,
  • $from => 0,
  • $to => 0

功能:

/**
 * Gets the highscore list for the map in that timespan
 * @param  integer $map   Id of map for which to fetch the highscore
 * @param  integer $limit Maximum no. of records to fetch
 * @param  integer $from  Timestamp from when to find rank
 * @param  integer $to    Timestamp up to when to find rank
 * @return array   Array of highscores arranged by rank for the map in the format [{"user"=>$user,"score"=>score,"timestamp" => timestamp}]
 */
function get_highscore_list($map,$limit,$from,$to){
    $sql = "SELECT user,scoreVal AS score,UNIX_TIMESTAMP(timestamp) AS timestamp FROM Score WHERE timestamp >= :from AND timestamp <= :to AND map = :map ORDER BY scoreVal DESC, timestamp ASC LIMIT :limit";
    if ($to==intval(0)){
        $max =1;
        $sql = str_replace(":to","NOW()",$sql,$max);
    }
    try{
    $conn = request_connection();
    $stmt = $conn->prepare($sql);
    $stmt->execute(array(':map'=>$map,':from'=>$from,':limit'=>$limit));
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
    }catch(PDOException $e){
        $_POST["exception"]=$e;
        continue;
    }
    return $result;
}

编辑


MySQL表的格式:


我已经尝试输出 $conn->errorInfo();,但是由于没有抛出错误,我返回了一个值数组: [00000,null,null]


request_connection 函数只返回这个函数的结果,它适用于我所有的其他语句。

/**
 * Creates a new PDO connection to the database specified in the configuration file
 * @author Ignacy Debicki
 * @return PDO A new open PDO connection to the database
 */
function create_connection(){
    try {
        $config = parse_ini_file('caDB.ini');
        $conn = new PDO('mysql' . ':host=' . $config['dbHost'] . ';dbname=' . $config['db'],$config['dbPHPUser'], $config['dbPHPPass']);
        date_default_timezone_set($config['dbTimezone']);
        return $conn;
    } catch(PDOException $e){
        throw new Exception("Failed to initiate connection",102,$e);
    }   
}

谢谢

【问题讨论】:

  • timestamp的数据类型是什么?
  • @RodolfoAndrade 查看更新的问题
  • 我已删除对您问题的回答。我假设您在表中使用 UNIX 时间戳 (INT),而不是 timestamp 列。
  • 我也尝试过删除语句的 LIMIT 部分。仍然没有返回预期的结果。无论哪种方式,我还使用了一个参数化的 LIMIT 子句,它可以正常工作
  • echo '&lt;pre&gt;'.print_r($conn-&gt;errorInfo(), TRUE).'&lt;/pre&gt;'; 应该有帮助...

标签: php mysql pdo


【解决方案1】:

经过几个小时的尝试,我终于找到了解决方案。

我在创建连接时遗漏了两个重要声明:

$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

开启错误报告(参见https://*.com/a/8776392/2891273)。

一旦我打开它,就很容易发现我的问题,这是由于覆盖了 :to 参数如果 $to 为 0,$conn-&gt;execute() 语句中传递的参数数量与数量不匹配sql查询中的参数。

我的解决方案是对每个参数使用$conn-&gt;bindValue(),使用 if 语句检查是否绑定到 :to 参数。以下是我的解决方案:

function get_highscore_list($map,$limit,$from,$to){
    $sql='SELECT user, scoreVal AS score, UNIX_TIMESTAMP(timestamp) AS timestamp FROM Score WHERE map = :map AND timestamp >= :from AND timestamp <= :to ORDER BY scoreVal DESC, timestamp ASC LIMIT :limit';
    if ($to==0){
        $sql = str_replace(":to",'CURRENT_TIMESTAMP()',$sql);
    }
    $conn = request_connection();
    $stmt = $conn->prepare($sql);
    $stmt->bindValue(':map',$map,PDO::PARAM_INT);
    $stmt->bindValue(':from',$from,PDO::PARAM_INT);
    if ($to!=0){
        $stmt->bindValue(':to',$to,PDO::PARAM_INT);
    }
    $stmt->bindValue(':limit',$limit,PDO::PARAM_INT);
    $stmt->execute();
    $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
    return $result;
}

【讨论】:

  • 所以,这样做我发现“sql_mode=only_full_group_by”和谷歌的 CloudSQL 混合不好。我可以在我的客户端中更改它,但在我的代码中,它仍然会引发错误。多亏了这些属性才发现。再见遗留代码,第二代 Cloud SQL 对它来说太严格了。