SQL 参数化现在是一个热门话题,并且有充分的理由,但除了体面地转义之外,它真的有什么作用吗?
我可以想象一个参数化引擎只是在将数据插入查询字符串之前确保数据被适当地转义,但这真的是它的全部吗?在连接中做一些不同的事情会更有意义,例如:
> Sent data. Formatting: length + space + payload
< Received data
-----
> 69 SELECT * FROM `users` WHERE `username` LIKE ? AND `creation_date` > ?
< Ok. Send parameter 1.
> 4 joe%
< Ok. Send parameter 2.
> 1 0
< Ok. Query result: [...]
这种方式可以简单地消除 SQL 注入的问题,因此您不必通过转义来避免它们。我能想到参数化如何工作的唯一另一种方法是转义参数:
// $params would usually be an argument, not in the code like this
$params = ['joe%', 0];
// Escape the values
foreach ($params as $key=>$value)
$params[$key] = mysql_real_escape_string($value);
// Foreach questionmark in the $query_string (another argument of the function),
// replace it with the escaped value.
$n = 0;
while ($pos = strpos($query_string, "?") !== false && $n < count($params)) {
// If it's numeric, don't use quotes around it.
$param = is_numeric($params[$n]) ? $params[$n] : "'" . $params[$n] . "'";
// Update the query string with the replaced question mark
$query_string = substr($query_string, 0, $pos) //or $pos-1? It's pseudocode...
. $param
. substr($query_string, $pos + 1);
$n++;
如果是后者,我暂时不会将我的站点切换到参数化。我可以看到它没有任何优势,这只是另一个强变量与弱变量类型的讨论。强类型化可能会在编译时捕获更多错误,但它并没有真正使任何难以做到的事情成为可能——与此参数化相同。(如果我错了,请纠正我!)
更新:
- 我知道这将取决于 SQL 服务器(也取决于客户端,但我假设客户端使用了最好的技术),但我主要考虑的是 MySQL。不过,关于其他数据库的答案也很受欢迎。
- 据我了解答案,参数化确实不仅仅只是转义数据。它实际上是以参数化的方式发送到服务器的,因此变量是分开的,而不是作为单个查询字符串。
- 这也使服务器能够存储和重用具有不同参数的查询,从而提供更好的性能。
我得到了一切吗?我仍然好奇的一件事是 MySQL 是否具有这些功能,以及是否自动完成查询重用(或者如果没有,如何做到这一点)。
另外,请在有人阅读此更新时发表评论。我不确定它是否会影响问题或什么......
谢谢!