问题描述
|
我已经进行了研究,并决定在查询中使用准备好的语句,我只想问我是否应该知道有关将普通mysqli查询切换到准备好的语句的好坏。
而且我不理解逻辑,为什么不需要转义坏字符?
解决方法
仍然需要转义坏字符,但是库会为绑定的所有参数自动完成转义。它只是稍微方便些,并且可以防止程序员忘记清理值。
但是,请注意,这种自动性仅限于参数!
以下查询是安全的,因为
bind_param()
负责转义:
$code = $_GET[\"code\"];
$name= $_GET[\"name\"];
$percentage= $_GET[\"percentage\"];
$stmt = $mysqli->prepare(\"INSERT INTO items VALUES (?,?,?)\");
$stmt->bind_param(\'iss\',code,$name,$percentage);
$stmt->execute();
以下查询是不安全的,因为您直接放入查询中的任何内容都不会自动转义:
$tablename = $_GET[\"prefix\"].\"_items\";
$code = $_GET[\"code\"];
$name= $_GET[\"name\"];
$percentage= $_GET[\"percentage\"];
---- UNSAFE! ----
$stmt = $mysqli->prepare(\"INSERT INTO `$tablename` VALUES (?,$code,$percentage);
$stmt->execute();
也就是说,无论如何都不应使用本示例中所示的动态表名称。但是重点是:即使有参数化查询,也要小心!
我能想到的唯一缺点是,您再也看不到最终查询用于调试(因为它仅在服务器端组装)。
,至少有两个优点:
您不必处理转义值:它是自动完成的(当然,当使用绑定参数时)
该语句发送到SQL服务器,仅准备一次;然后可以执行多次-这对于提高性能非常有用(即使多次执行该语句也只能解析一次)
,如果您使用带占位符的预准备语句(未命名为“ 3”或命名为“ 4”),则在其中插入的值将自动加引号。
预准备的语句由dbms-engine预编译。因此,查询仅被解析一次,并在以后的调用中仅将占位符替换为值。
,大多数人的确会将准备好的声明与占位符混淆。
使用占位符的一般想法确实很棒,而准备好的语句只是占位符功能有限的子集。
占位符很棒,因为:
它们更安全,因为它们会进行所有正确的格式化(而不是愚蠢的“转义”!)
它们易于使用,因为它们会自动进行所有正确的格式化。
它们很方便,因为它们仅对直接输入查询的值(而不对源变量)进行所有正确的格式化。
至于每个人都在谈论的性能问题,大多数情况下,准备好的语句比常规查询要慢。但是,在两种情况下差异都不明显。