我想使用一个预准备语句,其中传入的参数用于ORDER BY
和LIMIT
子句,如下所示:
$sql = 'SELECT * FROM table ORDER BY :sort :dir LIMIT :start, :results';
$stmt = $dbh->prepare($sql);
$stmt->execute(array(
'sort' => $_GET['sort'],
'dir' => $_GET['dir'],
'start' => $_GET['start'],
'results' => $_GET['results'],
)
);
但是$stmt->fetchAll(PDO::FETCH_ASSOC);
没有返回任何内容。
有人可以指出我在做什么是错的吗?可以吗?如果没有,我应该参考哪些条款的完整列表可以使用参数?
答案 0 :(得分:20)
使用后:
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
我收到了消息:
未捕获的异常'PDOException' 消息'SQLSTATE [42000]:语法错误 或访问违规:1064你有一个 SQL语法错误;检查 与您的MySQL对应的手册 用于正确语法的服务器版本 在第1行“0”,“10”附近使用
因此,当您使用数组执行时,它会将您的输入视为字符串,这对LIMIT来说不是一个好主意
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM table ORDER BY :sort :dir LIMIT :start, :results";
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':start', $_GET['start'], PDO::PARAM_INT);
$stmt->bindParam(':results', $_GET['results'], PDO::PARAM_INT);
$stmt->bindParam(':sort', $_GET['sort']);
$stmt->bindParam(':dir', $_GET['dir']);
$stmt->execute();
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
print_r($data);
答案 1 :(得分:5)
准备语句允许DBMS在实际执行所提供参数的查询之前为查询生成查询计划。更改ORDER BY
的字段需要不同的查询计划,因为以不同方式对数据进行排序可能会极大地影响DBMS可能选择获取数据的方式:例如,某些索引可能在一种情况下有用但在另一种情况下则不然。因此,ORDER BY
字段应构成传递给prepare()
方法的SQL字符串的一部分,而不是绑定到execute()
之前的查询。
对于LIMIT
子句,不清楚其参数是否会影响查询计划,因此可能会在以后绑定,可能取决于您的DBMS。根据{{3}},应该允许。
答案 2 :(得分:3)
您无法绑定参数以指定语言关键字或字段名称 - 它必须替换文字。因此,我认为您的限价值很好,但您的订单却没有。最好手动替换字符串中的sort和dir。逃避它们但不使用数据库工具这样做,因为它们不是字符串文字。基本上确保不存在特殊字符。
答案 3 :(得分:2)
虽然这个问题相当陈旧,但我认为它可能仍然有意义。对我来说,它是在我
后工作的PDO::PARAM_INT
结合使用intval()
代码的相关部分如下所示:
$stmt->bindParam(':start', intval($_GET['start']), PDO::PARAM_INT);
$stmt->bindParam(':number', intval($_GET['number']), PDO::PARAM_INT);
不使用intval()
我还收到错误语法错误或访问冲突:1064您的SQL语法出错;检查与您的MySQL服务器版本相对应的手册,以便在' 0' 0',10'附近使用正确的语法。第1行