所以我一直在使用预处理语句和一些项目,这是与MySQL数据库交互的一种非常好的干净方式,但今天我遇到了一些奇怪的问题。
我准备好的声明已经开始在sql语句中添加额外的'并且在我的生活中我不知道为什么......
所以这是代码:
<?php
$sortby="ORDER BY submit_date DESC";
$offset = 3;
$sql = "SELECT img_id, img_name, submit_date FROM tbl_images WHERE img_active='y' :sortby LIMIT :offset, 9";
$stmt = $this->_db->prepare($sql);
$stmt->bindParam(":sortby", $sortby, PDO::PARAM_STR);
$stmt->bindParam(":offset", $offset, PDO::PARAM_INT);
$stmt->execute();
?>
所以上面没有返回任何内容,所以查看数据库日志,这就是查询的样子
SELECT img_id, img_name, submit_date FROM tbl_images WHERE img_active='y' 'ORDER BY submit_date DESC' LIMIT 3, 9
似乎在“ORDER BY submit_date DESC”周围添加了一些额外的'',但是还没有绕过偏移?
任何人都可以发现问题,因为它让我发疯:)
提前谢谢!
解决方案,感谢发布的那些人,你是对的,我把田地分成了几个部分,就像一个魅力。代码解决方案如下:
<?php
$sortfield="submit_date";
$sortway="DESC"
$offset = 3;
$sql = "SELECT img_id, img_name, submit_date FROM tbl_images WHERE img_active='y' ORDER BY :sortfield :sortway LIMIT :offset, 9";
$stmt = $this->_db->prepare($sql);
$stmt->bindParam(":sortfield", $sortfield, PDO::PARAM_STR);
$stmt->bindParam(":sortway", $sortway, PDO::PARAM_STR);
$stmt->bindParam(":offset", $offset, PDO::PARAM_INT);
$stmt->execute();
?>
答案 0 :(得分:2)
查看mysqli_stmt::prepare
的文档:
标记仅在SQL语句的某些位置是合法的。例如,允许它们在INSERT语句的VALUES()列表中(指定行的列值),或与WHERE子句中的列进行比较以指定比较值。
基本上,查询的任何结构都不允许是绑定参数。只能以这种方式发送数据。
PDO准备好的陈述以同样的方式有效。但是,在你的情况下,PDO有点愚蠢,因为它在“模拟准备”模式下运行(这是默认模式,但你应该将其关闭以从PDO中获得最大收益)。它基本上完成所有替换,而不是分别将查询和数据发送到服务器。它看到数据是一个字符串,并认为“aha,一个字符串:我需要在此处加上引号。”因此,您最终会得到格式错误的查询。
解决方案不是使用绑定参数构建查询的结构部分。要么用串联替换它们,要么(并且这更好)为不同的设置提供替代查询字符串。这是最安全的方式:任何涉及连接的事情都是不安全因素。
哦,转向PDO模拟准备就绪!
答案 1 :(得分:1)
使用PDO,您不应在WHERE子句或ON子句之外使用预准备语句绑定变量替换。如果你这样做 - 任何字符串 - 将被引用(他们应该)。虽然$ offset整数绑定可能有效,但您不应该这样做。您应该使用字符串替换该值(将其与有效值的白名单数组进行比较)。
$sql = "SELECT img_id, img_name, submit_date FROM tbl_images WHERE img_active='y' $sortby LIMIT $offset, 9";
答案 2 :(得分:1)
您希望字符串插入$sortby
,而不是将其绑定为转义和引用的SQL文字。
(但注意不要插入不受信任的SQL片段!)
参数绑定用于将文字值替换为查询,我们通常指的是普通数字或字符串。参数不适用于SQL标识符(如表名或列名),也不适用于语法元素。
PDO将$sortby
解释为文字字符串,这是您要求它执行的操作:
SELECT ... WHERE image_active='y' 'literal string substituted here' ...
您肯定会在该查询中生成语法错误。
令人困惑的是,MySQL 确实允许占位符用于LIMIT子句的参数。这非常方便,但熟悉其他RDBMS的人会感到惊讶。