3

所以我一直在使用准备好的语句和一些项目,它是与 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();

?>
4

3 回答 3

2

查看以下文档mysqli_stmt::prepare

标记仅在 SQL 语句中的某些位置是合法的。例如,它们可以在 INSERT 语句的 VALUES() 列表中使用(以指定行的列值),或者在与 WHERE 子句中的列进行比较以指定比较值时。

基本上,查询的任何结构都不允许成为绑定参数。这种方式只能发送数据。

PDO 的准备好的语句以相同的方式有效地工作。但是,在您的情况下,PDO 有点愚蠢,因为它在“模拟准备”模式下运行(这是默认设置,但您应该将其关闭以充分利用 PDO)。它基本上自己完成所有替换,而不是将查询和数据分别发送到服务器。它看到数据是一个字符串,并认为“啊哈,一个字符串:我需要在这个周围加上引号”。因此,您最终会得到格式错误的查询。

解决方案不是使用绑定参数构建查询的结构部分。要么用连接替换它们,要么(这更好)为不同的设置提供替代查询字符串。这是最安全的方式:任何涉及串联的事情都是不安全的秘诀。

哦,然后关闭 PDO 仿真准备!

于 2012-10-03T19:26:42.593 回答
1

您想要 string interpolate $sortby,而不是将其绑定为转义和引用的 SQL 文字。

(但请注意不要插入不受信任的 SQL 片段!)

参数绑定用于将文字值替换为查询,我们通常指的是纯数字或字符串。参数不适用于 SQL 标识符(如表或列名),也不适用于语法元素。

PDO 被解释$sortby为文字字符串,这就是您要求它执行的操作:

SELECT ... WHERE image_active='y' 'literal string substituted here' ...

您肯定会使用该查询生成语法错误。

有点令人困惑的是,MySQL确实允许 LIMIT 子句的参数占位符。这很方便,但对于那些熟悉其他 RDBMS 的人来说却是令人惊讶的。

于 2012-10-03T19:27:10.553 回答
1

使用 PDO,您不应在 WHERE 子句或 ON 子句之外使用准备好的语句绑定变量替换。如果你这样做了——任何字符串——都会被引用(正如他们应该的那样)。虽然 $offset 整数绑定可能有效,但您不应该这样做。您应该只用字符串替换该值(在将其与有效值的白名单数组进行比较之后)。

  $sql = "SELECT img_id, img_name, submit_date FROM tbl_images WHERE img_active='y' $sortby LIMIT $offset, 9";
于 2012-10-03T19:19:49.133 回答