SQLSTATE[42S22]: 未找到列:1054 未知列 PhP PDO MariaDB10

SQLSTATE[42S22]: Column not found: 1054 Unknown column PhP PDO MariaDB10

我发现自己在 PDO 中处于一个非常奇怪的境地。从 PhP 调用时不想执行查询,但从 HeidiSQL 调用时它会执行。

错误在标题中。

SQL 从语句 debugDumpParams 查询:

SELECT s_id AS id,
 s_title AS title,
 genre.g_name AS genreName,
 accounts.ac_public_name AS producerName,
 s_price AS price, 
 DATE_FORMAT(s_last_modified_date, '%d/%m/%Y %H:%i:%s') AS lastModifiedDate, 
 DATE_FORMAT(s_added_date, '%d/%m/%Y %H:%i:%s') AS addedDate,
 s_downloads AS downloads,
 s_sales AS sales,
 s_rating AS rating, 
 s_status AS STATUS
FROM song
JOIN accounts ON accounts.ac_id = song.s_producer
JOIN genre ON genre.g_id = song.s_genre
WHERE 1=1 AND genre.g_id = '1'
ORDER BY s_status ASC, s_added_date DESC
LIMIT 0, 5;

接下来是我在查询字符串中添加 genre.g_id = :id 的部分

 if(isset($filterData["genreId"]) && $filterData["genreId"] !== ""){
    $queryString .= " AND genre.g_id = :genreId";
 }

还有我绑定的地方

 if(isset($filterData["genreId"]) && $filterData["genreId"] !== ""){
    $genreParam = $filterData["genreId"];
    $stmt->bindParam('genreId', $genreParam);
 }

在这两种情况下 $filterData["genreId"] 都已设置并且它有一个值,因此 if 没有问题。如果 $filterData["genreId"] 为空或未设置,则查询不会有问题。

并且错误:SQLSTATE[42S22]:未找到列:1054 Unknown column \'genre.g_id\' in \'where clause\'

但是等等,还有更多。 如果我用 genre.g_id2 而不是 genre.g_id,它会是这样的:

 if(isset($filterData["genreId"]) && $filterData["genreId"] !== ""){
    $queryString .= " AND genre.g_id2 = :genreId";
 }

现在它甚至达不到$stmt->debugDumpParams(); 它给出的只是这个错误: SQLSTATE[42S22]: Column not found: 1054 Unknown column \'genre.g_id2\' in \'where clause\ ,没有像以前那样的查询。

列 100% 存在于 table 中。此查询的类似问题:

SELECT s_id AS id,
 s_title AS title,
 genre.g_name AS genreName,
 accounts.ac_public_name AS producerName,
 s_price AS price, 
 DATE_FORMAT(s_last_modified_date, '%d/%m/%Y %H:%i:%s') AS lastModifiedDate, 
 DATE_FORMAT(s_added_date, '%d/%m/%Y %H:%i:%s') AS addedDate,
 s_downloads AS downloads,
 s_sales AS sales,
 s_rating AS rating, 
 s_status AS STATUS
FROM song
JOIN accounts ON accounts.ac_id = song.s_producer
JOIN genre ON genre.g_id = song.s_genre
WHERE 1=1 AND accounts.ac_id = '999999'
ORDER BY s_status ASC, s_added_date DESC
LIMIT 0, 5;

似乎问题仅出在 table 中的列 table song JOIN 中。

下一个查询完美运行。

SELECT s_id AS id,
 s_title AS title,
 genre.g_name AS genreName,
 accounts.ac_public_name AS producerName,
 s_price AS price, 
 DATE_FORMAT(s_last_modified_date, '%d/%m/%Y %H:%i:%s') AS lastModifiedDate, 
 DATE_FORMAT(s_added_date, '%d/%m/%Y %H:%i:%s') AS addedDate,
 s_downloads AS downloads,
 s_sales AS sales,
 s_rating AS rating, 
 s_status AS STATUS
FROM song
JOIN accounts ON accounts.ac_id = song.s_producer
JOIN genre ON genre.g_id = song.s_genre
WHERE 1=1 AND s_status = '0'
ORDER BY s_status ASC, s_added_date DESC
LIMIT 0, 5;

2 天,没有解决方案。我找到的大多数解决方案都是再次检查该列是否真的存在:| 有没有人对这个特定问题有更好的解决方案?

目标是 select g_id 等于我传递给它的值的数据。

我如何创建查询字符串:

 $queryString = "SELECT s_id as id,
                            s_title as title,
                            genre.g_name as genreName,
                            accounts.ac_public_name as producerName,
                            s_price as price, 
                            DATE_FORMAT(s_last_modified_date, '%d/%m/%Y %H:%i:%s') as lastModifiedDate,
                            DATE_FORMAT(s_added_date, '%d/%m/%Y %H:%i:%s')  as addedDate,
                            s_downloads as downloads,
                            s_sales as sales,
                            s_rating as rating,     
                            s_status as status
                            FROM song 
                            JOIN accounts on accounts.ac_id = song.s_producer
                            JOIN genre on genre.g_id = song.s_genre
                            WHERE 1=1 ";

然后在函数中添加这个

 if(isset($filterData["genreId"]) && $filterData["genreId"] !== ""){
    $queryString .= " AND genre.g_id = :genreId";
 }

那我就这样做

$queryString .= " ORDER BY s_status asc, s_added_date desc";
$queryString .= " LIMIT :offset, :limit;";

最后

  $stmt = $dbConnector->getConnection()->prepare($queryString);

这是与问题相关的部分。我不能post整个功能,它真的很长。

这用于根据某些输入或输入组合搜索数据。整个DAOclass真的很大:)

OS: Windows 10, PhP版本:7.2.19, 阿帕奇版本:2.4.35, 玛丽亚数据库版本:10.4 海蒂 SQL: 10.2.0.5599

再编辑:

如果我在第一次声明时在 queryString 中添加列:

$queryString = "SELECT s_id as id,
                            s_title as title,
                            genre.g_name as genreName,
                            accounts.ac_public_name as producerName,
                            s_price as price, 
                            DATE_FORMAT(s_last_modified_date, '%d/%m/%Y %H:%i:%s') as lastModifiedDate,
                            DATE_FORMAT(s_added_date, '%d/%m/%Y %H:%i:%s')  as addedDate,
                            s_downloads as downloads,
                            s_sales as sales,
                            s_rating as rating,     
                            s_status as status
                            FROM song 
                            JOIN accounts on accounts.ac_id = song.s_producer
                            JOIN genre on genre.g_id = song.s_genre
                            WHERE 1=1 AND genre.g_id = :genreId";
        $queryString = $this->filterDataQuery($queryString, $filterData, "songs");
        $queryString .= " ORDER BY s_status asc, s_added_date desc";
        $queryString .= " LIMIT :offset, :limit;";
        $stmt = $dbConnector->getConnection()->prepare($queryString);
        $genreParam = $filterData["genreId"];
        $stmt->bindParam(':genreId', $genreParam);

而不是 $this->filterDataQuery($queryString, $filterData, "songs");当我基于 selected 过滤器构建 queryString 时,它工作得很好。 这是来自浏览器控制台的 select:

SELECT s_id AS id,

 s_title AS title,

 genre.g_name AS genreName,

 accounts.ac_public_name AS producerName,

 s_price AS price, DATE_FORMAT(s_last_modified_date, '%d/%m/%Y %H:%i:%s') AS lastModifiedDate, DATE_FORMAT(s_added_date, '%d/%m/%Y %H:%i:%s') AS addedDate,

 s_downloads AS downloads,

 s_sales AS sales,

 s_rating AS rating, 

 s_status AS STATUS
FROM song
JOIN accounts ON accounts.ac_id = song.s_producer
JOIN genre ON genre.g_id = song.s_genre
WHERE 1=1 AND genre.g_id = '1'
ORDER BY s_status ASC, s_added_date DESC
LIMIT 0, 5;

这个和第一个不一样吗?因为它是。我瞎了?

在重读你的第一个 post 几十次并在本地测试各种正常的事情而没有出现相同的错误之后,我认为 filterDataQuery() 中的 $stmt 变量持有一个完全不同的查询比 posted 在这里。它只是不包括 table genre,如错误消息中所示。 如果您没有使用该功能,请查看倒数第二个代码块,一切正常(如果我理解正确的话)。

同样根据显示的代码,我不明白你如何调用 filterDataQuery() 将条件添加到查询字符串,并将参数直接绑定到稍后准备的语句对象,因此不是在那里可用(或者不是你期望的那个)。

为了证明我的理论我的完整测试代码,仍然使用this db-fiddle:

ini_set('display_errors', 1);
error_reporting(E_ALL);

$DB_USER = '*****';
$DB_PASS = '*****';
$db = new PDO('mysql:host=localhost;dbname=testing.project', $DB_USER, $DB_PASS);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);

$select = 'SELECT s_id AS id,
 s_title AS title,
 genre.g_name AS genreName,
 accounts.ac_public_name AS producerName,
 s_price AS price, 
 DATE_FORMAT(s_last_modified_date, "%d/%m/%Y %H:%i:%s") AS lastModifiedDate, 
 DATE_FORMAT(s_added_date, "%d/%m/%Y %H:%i:%s") AS addedDate,
 s_downloads AS downloads,
 s_sales AS sales,
 s_rating AS rating, 
 s_status AS STATUS
FROM song
JOIN accounts ON accounts.ac_id = song.s_producer
JOIN genre ON genre.g_id = song.s_genre';
$where = ' WHERE genre.g_id = :genreId';
$order = ' ORDER BY s_status ASC, s_added_date DESC';
$limit = ' LIMIT 0, 5';

// No problemo:
$sql = $select . $where . $order . $limit;
$stmt = $db->prepare($sql);
$genreId = 1;
$stmt->bindParam(':genreId', $genreId);
$stmt->execute();

// Trigger error column not found, $stmt containing an unexpected query:
$select = 'SELECT * FROM `song`';
$sql = $select . $where . $order . $limit;
$stmt = $db->prepare($sql);
$genreId = 1;
$stmt->bindParam(':genreId', $genreId);
$stmt->execute();

首先,我没有将 $stmt 变量传递给 filterDataQuery。我将它传递给 bindParams。 bindParams 函数在完成 filterDataQuery 并添加用于排序依据和限制的字符串之后被调用。

我真的要感谢你,Piemol,你试图帮助我。

在我大学的一位教授建议我这样做后,我检查了 Maria DB 日志,我发现了那里的问题

在同一个控制器中,我调用了两个 DAO 方法,一个接一个,一个带来数据,第二个进行计数。

  $responseMessage = json_encode(AdminDAO::getInstance()->getFilteredSongsList($message));
  $count = AdminDAO::getInstance()->getFilteredSongsListItemsCount($message); // this one was the problem

问题不在获取数据的那个,我发布的那个。问题出在计数的人身上。我没有在那里添加连接:| . Alose 那里没有迹象表明错误来自什么方法,所以我专注于错误的错误(日志中显示的错误)。如果我像在 Java 中那样使用记录器,这样的事情就永远不会发生。

这是来自 MariaDB 日志文件的查询:https://www.heypasteit.com/clip/0IUPWG 第一个是失败的,第二个是有效的。

我非常想念 Java 中的 log4j。

感谢所有试图帮助我的人。

对于那些有这种奇怪问题的人,检查日志,回显,不要关注你在 AJAX 响应日志中看到的第一件事。