我在我的应用程序中使用PDO。但是当我在包含LIMIT
的查询中使用预准备语句时,我遇到了问题。有什么问题?
代码:
$start = 0;
$rows = 20;
$sql = "SELECT * FROM tbl_news ORDER BY date DESC LIMIT ?, ?";
$q = $db->prepare($sql);
$q->execute(array($start , $rows));
错误:
查看与您的MySQL服务器版本对应的手册,以便在“0”,“20”附近使用正确的语法
答案 0 :(得分:10)
关于帖子LIMIT keyword on MySQL with prepared statement,下面的代码可以解决我的问题。
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
感谢ÁlvaroG。Vicario 和 Maerlyn
答案 1 :(得分:6)
你可以这样做:
$sql = SELECT * FROM tbl_news ORDER BY date DESC LIMIT :start, :rows";
$q = $db->prepare($sql);
$q->bindParam(':start', $start, PDO::PARAM_INT);
$q->bindParam(':rows',$rows, PDO::PARAM_INT);
答案 2 :(得分:4)
它是一个known bug,它在5.5.6中从内存中修复。
从文章: LIMIT不允许在任何上下文中使用变量。 它的参数必须是整数常量。
进一步编辑:(对此事存在争议) 用户变量是预准备语句中LIMIT子句的可接受参数,预处理语句的SQL语法可用于存储过程。
第三编辑: 这个link解释说这些应该与准备好的陈述一起使用。
答案 3 :(得分:2)
我偶然发现了同样的问题。对我来说,使用我自己的语句类(扩展PDOStatement
)和我自己的execute()
方法修复它。
这是班级:
class MyPDOStatement extends PDOStatement {
public function execute($input_parameters = null) {
if (is_array($input_parameters)) {
$i = 1;
foreach ($input_parameters as $p) {
// default to string datatype
$parameterType = PDO::PARAM_STR;
// now let's see if there is something more appropriate
if (is_bool($p)) {
$parameterType = PDO::PARAM_BOOL;
} elseif (is_null($p)) {
$parameterType = PDO::PARAM_NULL;
} elseif (is_int($p)) {
$parameterType = PDO::PARAM_INT;
}
// parameters passed to execute() are input-only parameters, so use
// bindValue()
$this->bindValue($i, $p, $parameterType);
$i++;
}
}
return parent::execute();
}
}
要告诉PDO使用此语句类而不是默认类,请执行以下操作:
$db = new PDO(...);
$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('MyPDOStatement'));
现在问题中的代码将起作用:
$start = 0;
$rows = 20;
$sql = "SELECT * FROM tbl_news ORDER BY date DESC LIMIT ?, ?";
$q = $db->prepare($sql);
$q->execute(array($start , $rows));
你唯一需要做的就是绑定到语句的变量具有正确的类型integer。如果你有一个数字字符串,例如从$_GET
数组中,您可以执行以下操作:
if (isset($_GET['start']) && is_numeric($_GET['start'])
&& is_int($_GET['start'] + 0) {
$start = (int) $_GET['start'];
}
如果对于最后一件事情有一个更简单的方法,我不会感到害羞,但至少它对我来说很好。
答案 4 :(得分:-1)
date
是一个保留字,你必须用back-ticks
答案 5 :(得分:-1)
$sql = "SELECT * FROM tbl_news ORDER BY `date` DESC LIMIT ?, ?";