PDO 参数化查询的工作方式

Posted

技术标签:

【中文标题】PDO 参数化查询的工作方式【英文标题】:The way PDO parametrized query works 【发布时间】:2011-04-13 05:37:36 【问题描述】:

请仔细阅读问题。 “我的代码不起作用!!!”这不是通常的愚蠢行为问题。

当我运行此代码时出现预期错误

try 
  $sth = $dbh->prepare("SELECT id FROM users WHERE name INN(?,?) ");
  $sth->execute(array("I'm","d'Artagnan"));
 catch (PDOException $e) 
    echo $e->getMessage();

我收到此错误消息

您的 SQL 语法有错误...在第 1 行的 'INN('I\'m','d\'Artagnan')' 附近

但多年来我一直认为查询和数据是分开发送到服务器的,并且不会相互干扰。因此我有一些问题(尽管我怀疑有人得到答案......)

    它从哪里得到如此熟悉的字符串表示 - 引用和转义?是专门报告错误还是实际查询的一部分? 实际效果如何?它是否用数据替换占位符? 有没有办法获取整个查询,而不仅仅是一点点,用于调试目的?

更新

mysqli 会按预期执行:它会抛出错误说 near 'INN(?,?)'

【问题讨论】:

@DrColossos 有答案,@Cassy 有解释。 【参考方案1】:

尝试添加

$dbh->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );

;)

【讨论】:

宾果游戏!我正要写另一个更新,正是关于这个主题,指向这个手册页上的第二段php.net/manual/en/ref.pdo-mysql.php,并询问是否有办法测试什么模式处于打开状态。刚刚测试了你的代码,它工作。错误消息中没有转义字符串【参考方案2】:

我不确定所有细节,但我会尽力回答。

    引用发生在数据库端。数据库转义并清理它接收到的所有值(参见项目符号 2),以便正确解释它。 抛出错误的那一刻,数据库(在本例中为 MySQL)打印出它尝试运行的查询。如果它只是显示准备好的部分,这将不会有太大帮助。

    不,它没有。在准备时,查询在服务器端编译。当使用值执行查询时,仅传输值。这与直接在数据库上调用 PREPARE 和 EXECUTE 几乎相同。

    这取决于您使用的数据库。例如,MySQL 可以将所有查询记录到日志文件中(检查 my.cnf 设置)。但是你也可以在 PHP 端使用debugDumpParams()。

我希望这有点帮助。

【讨论】:

感谢您的明智回应。我不能把 1 和 2 绑在一起。这是否意味着最后它是相同的引用/转义但只是在服务器端进行的? +1 用于回答实际问题,而不是专注于 IN/INN 的事情。因为第一句话解释了语法错误是故意的 @Col。弹片:对于数据库 1 和 2 是两个不同的命令。第一个“注册”一个查询(如果您愿意,可以比喻为一个函数),第二个将参数传递给它。在这种方法中,数据库确切地知道它可以/必须/应该引用查询的哪一部分。它无法对组合查询执行此操作。 我明白了。准备好后我想它不再是查询,而是成为一组带参数的命令,因此无需转义。 哦,伙计。 mysqli 按预期执行 - 错误消息中的 ??s

以上是关于PDO 参数化查询的工作方式的主要内容,如果未能解决你的问题,请参考以下文章

将参数传递给查询时,Php PDO 无法正常工作?

PDO 参数化与非参数化查询速度

参数化 PDO 查询和“LIMIT”子句 - 不起作用 [重复]

如何正确使用 PDO 对象进行参数化 SELECT 查询

如何在 PHP 中为动态查询构建参数化 PDO 语句?

在带有 PDO 的 PHP 中,如何检查最终的 SQL 参数化查询? [复制]