php PDO UPDATE语句:哪个更安全?

时间:2012-08-18 07:41:21

标签: php mysql pdo

我正在学习PDO,并发现确保我的语句正常工作很棘手。我有一个PHP函数,只需将数字1添加到总数中即可更新我的数据库。

    function add_rating($place_id,$rating_id) {

    //make $db accessible inside the function
    global $db;

    // query v1
    $sql = "UPDATE places_ratings SET ? +1 WHERE place_id=?";
    $q = $db->prepare($sql);
    $q->execute(array($rating_id,$place_id));   

}

我试过这个变种,我都无法开始工作。我不知道我是否使用了错误的问号。我关注的是this guide,还有previous SO question。最后我尝试了第一次使用的不同方法,所以我很想重复使用它,因为它看起来也简单得多。

    function add_rating($place_id,$rating_id) {

    //make $db accessible inside the function
    global $db;

    // query v2
    $query = "UPDATE places_ratings SET $rating_id = ($rating_id +1) WHERE place_id = $place_id";
    $update = $db->query($query);

}

我的问题是:哪个陈述更好/更安全?其次,第一个带问号的版本我做错了什么?感谢...

3 个答案:

答案 0 :(得分:2)

准备好的陈述就像将变量复制到一段文本中一样。准备好的语句在查询逻辑和查询应该处理的之间分开。他们在那里,所以你能够告诉你的数据库“你应该这样做”,让数据库理解它,然后给它应该做的事情。逻辑本身不可变,它需要在第一次完成。

因此,您只能使用占位符来表示值。您的查询需要阅读UPDATE ... SET FIELD = VALUE WHERE FIELD = VALUEFIELD部分需要在声明中,VALUE部分可以使用占位符。看起来您的$rating_id变量是变量字段名称。首先,这是个坏主意。如果可能,您不应该使字段名称变量。但是如果必须,您不能为它们使用预准备语句占位符。相反,你必须这样做:

$rating_id = 'field_name';
$query = "UPDATE places_ratings SET `$rating_id` = `$rating_id` + 1 WHERE `place_id` = ?";
$stmt = $db->prepare($query);
$stmt->execute(array($place_id));

由您决定$rating_id是否安全且包含已知的白名单值。不要让用户以任何方式为其提供价值。

答案 1 :(得分:1)

请了解prepared statements是什么。而且你也可以使用tutorial,它不会促进不良做法和易受攻击的代码。

正确创建和使用的预准备语句将始终比连接查询字符串更安全,因为预处理语句单独发送查询逻辑和数据。

此外,如果您使用的是PDO,那么通常使用bindParam()方法优先于将execute()方法中的值直接作为数组传递。这是因为,当在execute()中传递值时,值将绑定为PDO::PARAM_STR,即使DB列需要和整数。

P.S。 在代码中停止使用 global !!

答案 2 :(得分:1)

在第一个示例中,一般准备好的语句更安全,因为它们不受SQL注入的影响。

您的示例不起作用,因为您无法在预准备语句中使用?参数指定字段名称。即使你的SQL仍然可能出错,这也会扩展到

 UPDATE places_ratings SET whatever +1 WHERE place_id=?

无效。

如果您的$rating_id是在代码中生成的而不是从用户输入中获取的,那么您可以将这两种方法结合起来。