数据库
首页 > 数据库> > mysql – SQL参数化:这是如何在幕后工作的?

mysql – SQL参数化:这是如何在幕后工作的?

作者:互联网

SQL参数化现在是一个热门话题,对于a good reason而言,除了正确地逃避之外它真的做了什么吗?

我可以想象一个参数化引擎只是在将数据插入查询字符串之前确保数据被正常转义,但这真的是它的全部功能吗?在连接中做一些不同的事情会更有意义,例如:像这样:

> 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是否具有这些功能,以及是否自动完成查询重用(如果没有,可以如何完成).

此外,请在有人阅读此更新时发表评论.我不确定它是否会碰到这个问题……

谢谢!

解决方法:

我确信您的命令和参数的处理方式会有所不同,具体取决于特定的数据库引擎和客户端库.

但是,根据SQL Server的经验,我可以告诉您,使用ADO.NET发送命令时会保留参数.他们没有被纳入声明.例如,如果您使用SQL事件探查器,您将看到一个远程过程调用,如:

exec sp_executesql N'INSERT INTO Test (Col1) VALUES (@p0)',N'@p0 nvarchar(4000)',@p0=N'p1'

请记住,除了防止SQL注入之外,参数化还有其他好处.例如,查询引擎更有可能为参数化查询重用查询计划,因为该语句始终相同(只是参数值更改).

响应更新:
查询参数化是如此常见,我希望MySQL(实际上是任何数据库引擎)能够类似地处理它.

基于MySQL协议文档,看起来使用COM_PREPARECOM_EXECUTE数据包处理预处理语句,这些数据包支持二进制格式的单独参数.目前尚不清楚是否准备好所有参数化语句,但看起来没有准备好的语句由COM_QUERY处理,没有提及参数支持.

有疑问时:测试.如果您真的想知道通过线路发送了什么,请使用Wireshark等网络协议分析器查看数据包.

无论内部如何处理它以及它当前可能或不可能为给定引擎提供的任何优化,都可以从不使用参数中获得很少(没有?).

标签:mysql,sql,parameterized
来源: https://codeday.me/bug/20190716/1480416.html