试图参数化SQL LIMIT:offset,:display时出现PHP PDO错误?
此查询在phpMyAdmin中返回5个结果:试图参数化SQL LIMIT:offset,:display时出现PHP PDO错误?,php,mysql,pdo,rowcount,Php,Mysql,Pdo,Rowcount,此查询在phpMyAdmin中返回5个结果: SELECT * FROM tbl_product WHERE 1 ORDER BY last_update DESC LIMIT 0,5 在phpMyAdmin中返回count=12(这很好,因为有12条记录): 在我添加两个变量(偏移量、显示量)之前,这个函数工作得很好,但是现在它不工作了,打印出的变量给了我偏移量=0,显示量=5(因此仍然限制0,5) 它不起作用,因为我的dbrowsont(…)方法返回空字符串(愚蠢的PDOStatement
SELECT * FROM tbl_product WHERE 1 ORDER BY last_update DESC LIMIT 0,5
在phpMyAdmin中返回count=12(这很好,因为有12条记录):
在我添加两个变量(偏移量、显示量)之前,这个函数工作得很好,但是现在它不工作了,打印出的变量给了我偏移量=0,显示量=5(因此仍然限制0,5
)
它不起作用,因为我的dbrowsont(…)
方法返回空字符串(愚蠢的PDOStatement::fetchColumn
),所以我将其更改为使用PDO::FETCH_ASSOC
返回计数,并且它返回计数=0
以下是进行行计数的函数:
function dbRowsCount($sql, $data) {
global $db, $query;
$regex = '/^SELECT\s+(?:ALL\s+|DISTINCT\s+)?(?:.*?)\s+FROM\s+(.*)$/is';
if (preg_match($regex, $sql, $output) > 0) {
$query = $db->prepare("SELECT COUNT(*) AS count FROM {$output[1]}");
logErrors("Regex output: "."SELECT COUNT(*) AS count FROM {$output[1]}");
$query->setFetchMode(PDO::FETCH_ASSOC);
if ($data != null) $query->execute($data); else $query->execute();
if (!$query) {
echo "Oops! There was an error: PDOStatement returned false.";
exit;
}
$result = $query->fetch();
return (int)$result["count"];
} else {
logErrors("Regex did not match: ".$sql);
}
return -1;
}
我的错误日志提供程序的以下输出:
正则表达式输出:选择COUNT(*)作为tbl_产品的计数,其中1个订单按上次更新描述限制getProducts(0,5)返回了0行 正如您所看到的,SQL没有出现错误,方法输入变量如预期的那样为0和5 有人知道出了什么问题吗 更新 根据建议,我确实尝试直接执行查询,它返回了正确的结果:
function dbDebugTest() {
global $db;
$stmt = $db->query("SELECT COUNT(*) AS count FROM tbl_product WHERE 1 ORDER BY last_update LIMIT 0,5;");
$result = $stmt->fetch();
$rows = (int)$result["count"];
logErrors("dbDebugTest() returned rows=".$rows);
}
输出:
> dbDebugTest() returned rows=12
> Data: 0,5
根据另一个建议,我改变了=空到==null,并且我还打印了$data数组:
logErrors("Data: ".implode(",",$data));
if ($data !== null) $query->execute($data); else $query->execute();
输出:
> dbDebugTest() returned rows=12
> Data: 0,5
但是,dbRowsCount($sql,$data)仍然会为此查询返回0行强>
更新2
下面的实现建议允许我在绑定值后输出查询,我发现函数将在$query->execute($data)之后停止,因此不会打印输出,尽管自定义类适用于我程序中的每一个其他查询
更新代码:
function dbRowsCount($sql, $data) {
global $db, $query;
$regex = '/^SELECT\s+(?:ALL\s+|DISTINCT\s+)?(?:.*?)\s+FROM\s+(.*)$/is';
if (preg_match($regex, $sql, $output) > 0) {
$query = $db->prepare("SELECT COUNT(*) AS count FROM {$output[1]}");
logErrors("Regex output: "."SELECT COUNT(*) AS count FROM {$output[1]}");
$query->setFetchMode(PDO::FETCH_ASSOC);
logErrors("Data: ".implode(",",$data));
$query->execute($data);
logErrors("queryString:".$query->queryString);
logErrors("_debugQuery():".$query->_debugQuery());
if (!$query) {
echo "Oops! There was an error: PDOStatement returned false.";
exit;
}
$result = $query->fetch();
return (int)$result["count"];
} else {
logErrors("Regex did not match: ".$sql);
}
return -1;
}
输出:
> dbDebugTest() returned rows=12
> Data: 0,5
正则表达式输出:选择COUNT()作为tbl_product_类别的计数,其中id=数据:5
queryString:从tbl_产品_类别中选择COUNT()作为计数,其中id=
_debugQuery():选择COUNT(*)作为tbl_product_类别中的COUNT,其中id= 正则表达式输出:选择COUNT(*)作为tbl_产品的计数,其中1个订单按上次更新描述限制
数据:0,5
//函数已停止,无法输出_debugQuery 更新3 因为我无法让自定义PDOStatement类提供一些输出,所以我想我应该重写
getProducts(…)
类,用命名占位符绑定参数
function getProducts($offset, $display) {
$sql = "SELECT * FROM tbl_product WHERE 1 ORDER BY last_update DESC LIMIT :offset, :display;";
$data = array(':offset'=>$offset, ':display'=>$display);
$rows = dbRowsCount($sql, $data);
logErrors("getProducts(".$offset.",".$display.") returned ".$rows." rows.");
if ($rows > 0) {
dbQuery($sql, $data);
return dbFetchAll();
} else {
return null;
}
}
输出:
正则表达式输出:选择计数(*)作为tbl_产品的计数,其中1个订单按上次更新描述限制:偏移量,:显示数据:0,5
//在$query->execute($data)之后仍然崩溃,因此
logErrors(“getProducts(“.$offset.”…)
没有打印出来
更新4
此dbDebugTest以前用于直接在SQL字符串中声明限制值0,5。现在我已对其进行了更新,以正确绑定参数:
function dbDebugTest($offset, $display) {
logErrors("Beginning dbDebugTest()");
global $db;
$stmt = $db->prepare("SELECT COUNT(*) AS count FROM tbl_product WHERE 1 ORDER BY last_update LIMIT :offset,:display;");
$stmt->bindParam(':offset', $offset, PDO::PARAM_INT);
$stmt->bindParam(':display', $display, PDO::PARAM_INT);
if ($stmt->execute()) {
$result = $stmt->fetch();
$rows = (int)$result["count"];
logErrors("dbDebugTest() returned rows=".$rows);
} else {
logErrors("dbDebugTest() failed!");
}
}
函数崩溃,仅此为输出:
正在开始dbDebugTest()
更新5
根据打开错误的建议(默认情况下它们是关闭的),我这样做了:
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
这本身就使得更新4中的dbDebugTest()能够工作
正在开始dbDebugTest()
dbDebugTest()返回的行数=12
现在在我的Web服务器日志中生成了一个错误:
[警告]mod_fcgid:stderr:PHP致命错误:未捕获的异常“PDOException”,消息为“SQLSTATE[42000]:
语法错误或访问冲突:1064您的SQL语法有错误;
查看与您的MySQL服务器版本对应的手册,了解要使用的正确语法
在第1行的“0”、“5”附近
在/home/linweb09/b/example.com-1050548206/user/my_program/database/dal.php:36中 第36行引用了
dbrowsont(…)
方法,该行是$query->execute($data)
因此,另一种方法getProducts(…)
仍然不起作用,因为它使用了这种绑定数据的方法,参数变成了“0”和“5”(这是一个bug吗?)。有点烦人,但我必须在我的dal.php中创建一个新方法,允许我以更严格的方式绑定参数-使用bindParam
特别感谢@Travesty3和@eggyal的帮助!!非常感谢。您正在测试
$data
是否为NULL
,并使用相等运算符,而不是标识运算符(有关各种比较运算符如何处理NULL
值的更多信息,请参阅)。您需要使用身份测试===
/!==
,或者调用
正如上面提到的@Travesty3,要测试数组是否为空,请使用。根据问题中的更新2,如果执行在
execute
语句后停止,则查询似乎失败。查看后,默认的错误处理设置似乎是PDO::ERRMODE\u SILENT,这将导致您执行的行为我在看
这很可能是由于LIMIT子句中的数字在作为参数传入时被放在单引号中,就像在中发生的那样
该帖子的解决方案是使用该方法将参数指定为整数,因此您可能需要做类似的事情
看起来您还应该使用try-catch块执行查询,以便捕获MySQL错误
bindValue方法:
if ($data !== null)
{
for ($i=0; $i<count($data); $i++)
$query->bindValue($i+1, $data[$i], PDO::PARAM_INT);
$query->execute($data);
}
else
$query->execute();
if($data!==null)
{
对于($i=0;$ibindValue($i+1,$data[$i],PDO::PARAM_INT);
$query->execute($data);
}
其他的
$query->execute();
您是否尝试手动运行查询?如使用$db->query(xxx)
没有任何参数或包装函数?那么它能工作吗?我不明白为什么会被否决?@kuba我没有这样做,因为我直接在phpMyAdmin中尝试了SQL,所以我认为它能工作,但我现在就去试试。@Ozzy:我也不明白否决票(你有我的+1)。你测试过if($data!=null)吗
要查看执行采取的路径,是否应该使用