【问题标题】:What's the internals of a prepared statement like? [closed]准备好的语句的内部结构是什么样的? [关闭]
【发布时间】:2013-11-30 20:08:37
【问题描述】:

bind_params 似乎是这样准备 sql 语句的:

stmt = db.prepare( "select * from table where a=? and b=?" )
stmt.bind_params( 15, "hello" )

所以实际上在 stmt 内部,我们需要有 map/array 或其他东西,最终将映射参数并创建正确的 stmt。在内部执行此操作的最佳方式是什么?我想,加上字符串需要额外的预防措施 - 上面的内容必须像“select * from table where a = 15 and b = \"hello\"”一样映射。

我查看了 SQLite3 和 OCI,他们似乎将这些传递给内部 C 代码。

【问题讨论】:

  • 这样的语句是在 MySQL 服务器上“准备好的”。参数独立于 SQL 发送到服务器,然后在找到相关占位符的任何地方将这些参数用作文字值。因此无需担心转义等问题——因为参数值永远不会针对 SQL 进行评估。
  • 我明白这一点。我正在尝试在客户端准备查询并将其发送到服务器。
  • 我们需要更好地解释您正在尝试做什么来“在客户端准备查询并将其发送到服务器”。 ORM(如 Sequel、ActiveRecord 和 DataMapper)以及 gem(如 MySQL 和 Pg gem)与后端 DBM 的客户端库交互。客户端库都是为了速度而编译的,所以是的,你最终会遇到 C。
  • 处理“准备好的语句”的实际方式取决于 RDBMS 的实现——不要用 MySQL SQLite 标记! - 使用的数据库适配器 - 使用特定绑定进行标记!然而,最终目标是相同的:分离数据和查询的形状,因此我更喜欢术语“参数化查询”。一些适配器/API(通常是较低级别的)允许直接访问“准备好的语句”,这可能表现为服务器资源,而另一些则不允许。

标签: mysql sql ruby sqlite dbi


【解决方案1】:

我正在尝试在客户端准备查询并将其发送到服务器

如果您尝试做听起来像是在尝试做的事情...不要尝试这样做。

这不是准备好的语句(或者至少不是它应该是的)。

您的客户端代码不应尝试将值插入查询字符串以生成“已完成”查询以发送到服务器执行。这是灾难的根源,更不用说虚假的安全感了。

Prepared statements 将带有? 占位符的语句按原样传递到服务器,服务器“准备”语句以供执行......然后客户端将参数发送到服务器(“绑定”参数)执行。这样做,服务器将永远不会混淆“哪一部分是 SQL”和“哪一部分是数据”,从而使 sql 注入变得不可能,并且不必对数据进行转义和清理。

mysql_stmt_bind_param() 用于为传递给mysql_stmt_prepare() 的SQL 语句中的参数标记绑定输入数据。它使用MYSQL_BIND 结构来提供数据。 bind 是MYSQL_BIND 结构数组的地址。客户端库希望该数组为查询中出现的每个 ? 参数标记包含一个元素。

——http://dev.mysql.com/doc/refman/5.6/en/mysql-stmt-bind-param.html

如果您不直接与 C-API 通信,那么您应该调用库中向您公开这些相同功能的方法。

【讨论】:

    猜你喜欢
    • 2023-03-19
    • 1970-01-01
    • 2011-10-01
    • 2012-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-17
    相关资源
    最近更新 更多