好吧,我还是不太懂。我一直在阅读,为了正确地逃避您的MySQL查询,您需要使用mysqli_prepare()
和mysqli_bind_param()
。
我尝试使用此设置,坦率地说,它有点笨拙。当我不需要再次引用变量时,我就不会通过引用传递变量了,只需要更多行代码来完成相同的任务。
我想我不知道它们之间有什么区别:
<?php
$sql = new \MySQLi(...);
$result = $sql->query('
UPDATE `table`
SET
`field` = "'.$sql->real_escape_string($_REQUEST[$field]).'";
');
?>
和
<?php
$sql = new \MySQLi(...);
$stmt = $sql->prepare('
UPDATE `table`
SET
`field` = ?;
');
$value = $_REQUEST[$field];
$stmt->bind_param('s', $value);
$stmt->execute();
$result = $stmt->get_result();
unset($value);
?>
除了更多代码。
我的意思是,他们是否实现了这一点,以便人们在查询中发送之前不会忘记转义值?还是以某种方式更快?
或者当我打算重复使用相同的查询时(因为mysqli_stmt
可以重复使用)并在其他情况下使用传统方法,我应该使用此方法吗?
答案 0 :(得分:3)
您正在阅读的内容,您需要使用 mysqli_prepare()
和 mysqli_bind_param()
函数来“正确转义MySQL查询”是错误的。
确实如果你使用 mysqli_prepare()
和 mysqli_bind_param()
,你就不需要(也不应该)“逃避”作为绑定参数提供的值。所以,从这个意义上说,你正在阅读的内容中有一些道理。
只有当不安全的变量包含在SQL文本(查询的实际文本)中时,才需要“正确地转义”变量,通常是将变量包装在 mysqli_real_escape_string()
函数调用。
(我们注意到可以使用预准备语句,而仍然在SQL文本中包含未转义的变量,而不是将变量值作为bind_parameters传递。这有点打败了使用预准备语句的目的,但重点是,无论哪种方式,您都可以编写易受攻击的代码。
MySQL现在支持“服务器端”预处理语句(如果在连接中启用了该选项),这是重复执行相同SQL文本的性能优化(在某些情况下)。 (这在其他数据库中得到了长期支持,例如Oracle,其中使用预处理语句已经是一种熟悉的模式,例如,永远都是如此。)
问:他们是否实施了[预备语句],以便人们在查询中发送之前不会忘记转义值?
答:基于不使用预准备语句时易受SQL注入攻击的代码示例数量,尽管有关于mysql_real_escape_string()
函数的文档,但您认为这肯定是足够的原因。
我认为一个很大的好处是,当我们阅读代码时,我们可以看到一个SQL语句作为单个字符串文字,而不是一堆变量的连接,带引号和点以及对mysql_real_escape_string的调用,这不是对于简单的查询来说太糟糕了,但是查询更复杂,这太过于繁琐了。 ?
占位符的使用使得一个更容易理解的SQL语句,...是的,我需要查看其他代码行来确定在那里填充的值。 (我认为名为参数:fee, :fi, :fo, :fum
的Oracle样式优于位置?, ?, ?, ?
表示法。)但是使用STATIC SQL文本才是真正的好处。
问:或者它的速度有多快?
正如我之前提到的,使用服务器端预处理语句在性能方面可以是有利的。它并不总是更快,但是对于重复执行相同的语句,唯一的区别是文字值(如在重复插入中),它可以提供性能提升。
问:或者当我打算重复使用相同的查询时(因为mysqli_stmt可以重复使用)并且在其他情况下使用传统方法,我应该使用此方法吗?
这取决于你。我更喜欢使用STATIC SQL文本。但这确实来自于使用Oracle的悠久历史,并且使用与MySQL相同的模式非常适合。 (虽然,来自Perl使用DBI接口,Java使用JDBC和MyBATIS,或其他ORM(Hibernate,Glassfish JPA等)
遵循相同的模式在PHP中感觉很自然; mysqli_和PDO的引入是奥术(和滥用)mysql_接口的一个受欢迎的缓解。
可以按照任一模式编写好的代码。但我挑战你提前考虑,更复杂的SQL语句,以及是否选择使用 mysqli_real_escape_string()
并将动态字符串连接在一起,而不是使用静态SQL文本和绑定参数,可能会进行读取和解密,实际执行的SQL对于发现自己维护未编写代码的灵魂来说更复杂。
我认为研究表明,代码读取的次数比编写代码多十倍,这就是为什么我们努力生成可读,易懂的代码,即使这意味着需要更多的代码行。 (当每个语句都在做一个可识别的事情时,我通常比在一个复杂的语句中阅读混杂的连接函数调用更容易理解。
答案 1 :(得分:2)
我认为后一种方法本身本身比鼓励逻辑分离更不是问题。使用预准备语句,SQL查询独立于我们使用的值。这意味着,例如,当我们返回并更改我们的查询时,我们不必将一堆不同的值连接到字符串,并且可能冒险忘记转义我们的输入。使代码更易于维护!
答案 2 :(得分:2)
我发现有一些主要的好处是写得很好:
另一方面,如果查询仅执行一次,则服务器端预处理语句可能会因为额外的服务器往返而变慢。实施限制也可能导致性能损失:某些版本的MySQL没有缓存准备好的查询结果,而某些DBMS(如PostgreSQL)在执行期间不执行额外的查询优化。
答案 3 :(得分:0)
我想在PHP 5.4.0中添加mysqli_bind_param() has been removed 。您应该使用mysqli_stmt_bind_param()