PHP PDO and query with SELECT COUNT(*)
我在这里有一个非常奇怪的问题 – 这是 PDO 不能返回 num_rows 与 MySQL 结合使用的一个小解决方法。
我可以通过 phpmyadmin 将此查询直接提供给数据库:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
SELECT COUNT(*) AS COUNT
FROM (( (SELECT ‘Key’ AS tradeOrigin, CONCAT(skti.tier, ‘ ‘, skty.type) AS trade, CONCAT(‘Amount: ‘, t.sourceKeyAmount) AS tradeInfo, ‘Platinum’ AS tradeToOrigin, t.destinationPlatinum AS tradeTo, ” AS tradeToInfo, u.ingame AS seller, DAYSPASSED(added) AS daysPassed, DATEDIFF(NOW(), added) AS sortingSince FROM trades t JOIN users u ON t.sourceItem = 1 AND t.destinationItem = 1 AND t.userId = u.userId AND t.sourceModId = 18 JOIN keytiers skti ON t.sourceKeyTierId = skti.keyTierId JOIN keytypes skty ON t.sourceKeyTypeId = skty.keyTypeId) UNION ALL (SELECT ‘Mod’ AS tradeOrigin, sm.name AS trade, CONCAT(‘Level: ‘, IF(t.sourceModLevel = 0, ‘Unranked’, t.sourceModLevel)) AS tradeInfo, ‘Platinum’ AS tradeToOrigin, t.destinationPlatinum AS tradeTo, ” AS tradeToInfo, u.ingame AS seller, DAYSPASSED(added) AS daysPassed, DATEDIFF(NOW(), added) AS sortingSince FROM trades t JOIN users u ON t.sourceItem = 2 AND t.destinationItem = 1 AND t.userId = u.userId AND t.sourceModId = 18 JOIN mods sm ON t.sourceModId = sm.modId)) AS derived) |
它将按预期返回一行,列 count 和值 1。
但是当它需要通过我的框架时会出错。
执行代码:
“;
$numrows = $dbh->num_rows($sql, $dataArray);
} 捕捉(PDOException $ex){
// 回声 $ex;
错误($前);
}
//…
[/cc]
输出:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
(SELECT ‘Key’ AS tradeOrigin,
CONCAT(skti.tier, ‘ ‘, skty.type) AS trade, CONCAT(‘Amount: ‘, t.sourceKeyAmount) AS tradeInfo, ‘Platinum’ AS tradeToOrigin, t.destinationPlatinum AS tradeTo, ” AS tradeToInfo, u.ingame AS seller, DAYSPASSED(added) AS daysPassed, DATEDIFF(NOW(), added) AS sortingSince FROM trades t JOIN users u ON t.sourceItem = 1 AND t.destinationItem = 1 AND t.userId = u.userId AND t.sourceModId = :modId JOIN keytiers skti ON t.sourceKeyTierId = skti.keyTierId JOIN keytypes skty ON t.sourceKeyTypeId = skty.keyTypeId) UNION ALL (SELECT ‘Mod’ AS tradeOrigin, sm.name AS trade, CONCAT(‘Level: ‘, IF(t.sourceModLevel = 0, ‘Unranked’, t.sourceModLevel)) AS tradeInfo, ‘Platinum’ AS tradeToOrigin, t.destinationPlatinum AS tradeTo, ” AS tradeToInfo, u.ingame AS seller, DAYSPASSED(added) AS daysPassed, DATEDIFF(NOW(), added) AS sortingSince FROM trades t JOIN users u ON t.sourceItem = 2 AND t.destinationItem = 1 AND t.userId = u.userId AND t.sourceModId = :modId JOIN mods sm ON t.sourceModId = sm.modId) |
1
2 3 4 |
这进入(注意:$this->dbh 是 PDO 实例):
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/**
* Returns the number of rows that this query has. * * @param type $query The input query * @param type $values The values * @return type Number of rows */ public function num_rows($query, $values) { $newquery =“SELECT COUNT(*) AS count FROM (({$query}) AS derived)”; echo $newquery; $statement = $this->query($newquery, $values); $i = $statement->fetch(); echo“[cc lang=”php“]”; print_r($i); echo“ |
“;
返回$i->count;
}
[/cc]
它回响:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
SELECT COUNT(*) AS COUNT
FROM (( (SELECT ‘Key’ AS tradeOrigin, CONCAT(skti.tier, ‘ ‘, skty.type) AS trade, CONCAT(‘Amount: ‘, t.sourceKeyAmount) AS tradeInfo, ‘Platinum’ AS tradeToOrigin, t.destinationPlatinum AS tradeTo, ” AS tradeToInfo, u.ingame AS seller, DAYSPASSED(added) AS daysPassed, DATEDIFF(NOW(), added) AS sortingSince FROM trades t JOIN users u ON t.sourceItem = 1 AND t.destinationItem = 1 AND t.userId = u.userId AND t.sourceModId = :modId JOIN keytiers skti ON t.sourceKeyTierId = skti.keyTierId JOIN keytypes skty ON t.sourceKeyTypeId = skty.keyTypeId) UNION ALL (SELECT ‘Mod’ AS tradeOrigin, sm.name AS trade, CONCAT(‘Level: ‘, IF(t.sourceModLevel = 0, ‘Unranked’, t.sourceModLevel)) AS tradeInfo, ‘Platinum’ AS tradeToOrigin, t.destinationPlatinum AS tradeTo, ” AS tradeToInfo, u.ingame AS seller, DAYSPASSED(added) AS daysPassed, DATEDIFF(NOW(), added) AS sortingSince FROM trades t JOIN users u ON t.sourceItem = 2 AND t.destinationItem = 1 AND t.userId = u.userId AND t.sourceModId = :modId JOIN mods sm ON t.sourceModId = sm.modId)) AS derived) |
1
2 3 4 |
调用:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
/**
* Can be called to create a query. Use either unnamed or named placeholders for the prepared statements. * * Example: $dbh->query(“INSERT INTO table (data1, data2) VALUES(?, ?)”, array($data1, $data2)); * * @param type $query The input query, including unnamed or named placeholders * @param type $values The input values. If it’s not an array, then it will be an one-element array * @return type The statement constructed by this query */ public function query($query, $values = array()) { if (!is_array($values)) { $values = array($values); } $statement = $this->dbh->prepare($query); $statement->setFetchMode(PDO::FETCH_OBJ); if (is_assoc($values)) { foreach ($values as $key => $value) { $statement->bindValue($key, $value); } } else { $i = 1; foreach ($values as $value) { $statement->bindValue($i++, $value); } } $statement->execute(); return $statement; } |
query 方法在过去已被证明有效,而且奇怪的是,num_rows 确实适用于其他一些正确返回 6 作为计数的任意查询。
我真的被困在这里,不知道发生了什么,请帮帮我。
更新:
显然是一个设置将我引入了这个问题:$this->dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);.
但是我仍然想知道它为什么会导致问题,因为我不能只是禁用它,因为我将它用于 LIMIT 子句,否则会失败(关于这个问题的大量 SO 帖子)。帖子示例如下:如何在 LIMIT 子句中应用 bindValue 方法?
- @halfer 添加了我过去遇到的一个。
- @Downvoter:愿意解释一下吗?
- @halfer 关闭一个题外话的问题怎么样,该问题明确要求修复代码,而不是安慰操作员?
- 如果它用英语描述代码中发生的事情,则表明对正在解决的问题的理解很少,因此不仅仅是”修复我的代码”或就此无关主题。
1
|
$statement->bindValue($key, $value);
|
你试过用 $statement->bindParam 代替吗?
因为结果不同,Sql本身没有问题,但问题要么出在values上,要么出在bind上。
- 那在过去造成了更多的问题并且不是我想要的,我想绑定值,这个语句本身应该不会引起任何问题。
根据评论中的讨论,您现在似乎掌握了足够的信息:您的 PDO 设置正在阻止您的绑定工作。
您说您正在使用该设置来使 LIMIT 工作 – 我猜想专门绑定到 LIMIT。您通常不能这样做,因为绑定仅用于参数值(即在 WHERE 子句中),而 LIMIT 子句不被视为参数。你能用另一种方式重写绑定的 LIMIT 查询吗?
最后,根据评论,确保您使用的任何别名都是小写的,并且不是保留字。您可能可以不区分大小写地使用这些,但无论如何都有代码约定是好的!
- 两种方式(绑定和 execute() 或只是 execute($data) 我相信从(php.net/manual/en/pdostatement.execute.php)完全相同,也对其进行了测试并且输出没有变化。
- 啊,是的 – 我看到 $this->query 并认为这是指 PDO 方法。那是你自己的方法。
- 好的,所以尝试将 18 值硬连接到查询中 – 听起来这不是问题,但仍然值得检查。
- $this->dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 似乎是问题的原因,没有它计数工作,但是这是限制 PDO 工作的解决方法。
- 我不知道那个设置,但这可能很有用。我不知道您需要更改任何 PDO 设置才能使 LIMIT 工作。
- 我最终用 LIMIT 这样做了。无论如何,这部分都无法进行 SQL 注入(没有用户输入),但我仍然没有看到我原来的问题,但它肯定与模拟准备有关。
来源:https://www.codenong.com/20857662/