【问题标题】:PDO insert fails when field name and value contains single quote (42000/1064)当字段名称和值包含单引号时,PDO 插入失败 (42000/1064)
【发布时间】:2018-03-28 16:25:16
【问题描述】:

当一个 PDO for MySQL 准备好的语句有:

  • 参数(v = ''
  • 名称包含单引号 (f'f) 的字段
  • VALUES 部分带有参数,后跟一个值 单引号 ('')

然后它失败并出现异常:

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':v,'')' at line 1

一些代码重现:

function query($sql) {
   $pdo = new PDO('mysql:host=...', 'u', 'p', [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ]);
   $pdo->prepare($sql)->execute(['v' => '']);
}

query("INSERT INTO `t` (`f'f`,`f`) VALUES ('',:v)"); // ok
query("INSERT INTO `t` (`f`,`f'f`) VALUES ('',:v)"); // ok
query("INSERT INTO `t` (`f'f`,`f`) VALUES (:v,'')"); // exception
query("INSERT INTO `t` (`f`,`f'f`) VALUES (:v,'')"); // exception

query("INSERT INTO `t` (`f'f`,`f`) VALUES (null,:v)"); // ok
query("INSERT INTO `t` (`f`,`f'f`) VALUES (null,:v)"); // ok
query("INSERT INTO `t` (`f'f`,`f`) VALUES (:v,null)"); // ok
query("INSERT INTO `t` (`f`,`f'f`) VALUES (:v,null)"); // ok

PHP 版本 5.5.9-1ubuntu4.24,mysqlnd 5.0.11

这是一个错误还是我遗漏了什么?


更新:

在 PHP 版本 7.1.15-1、mysqlnd 5.0.12 上试过:没有变化。

尝试使用位置参数:没有变化。

【问题讨论】:

    标签: php pdo prepared-statement


    【解决方案1】:

    引用的列名对 MySQL 来说不是问题。我可以使用 MySQL 客户端成功测试(根本没有 PHP):

    mysql> set @v = '';
    
    mysql> set @sql = "INSERT INTO `t` (`f'f`,`f`) VALUES (?,'')";
    
    mysql> create table t (f int, `f'f` int);
    
    mysql> prepare stmt from @sql;
    
    mysql> execute stmt using @v;
    Query OK, 1 row affected, 2 warnings (0.01 sec)
    
    mysql> select * from t;
    +------+------+
    | f    | f'f  |
    +------+------+
    |    0 |    0 |
    +------+------+
    

    错误来自MySQL,它看到命名参数占位符:v是一个问题。 MySQL 本身不支持命名参数占位符,因此 PDO 应该用 ? 替换位置参数。

    因此,如果有错误,它就在 PDO 中。我怀疑 PDO 对列名中的单引号感到困惑,因为它试图解析 SQL 字符串以查找参数占位符。

    我建议您在使用 PDO 时不要使用包含单引号的列名。

    PHP 5.5 已经很老了,一直是out of support for almost two years(我在 2018 年 3 月写这篇文章)。这些天来,至少应该使用 PHP 7.1。

    我建议您使用 PHP 7.1 重复测试,看看 PDO 中的错误是否已修复。还可以尝试使用位置参数(使用? 占位符)进行测试,看看它是否能解决问题。

    【讨论】:

    • 根据您的建议更新了问题,没有任何变化。所以我想这是一个 PDO 问题。
    猜你喜欢
    • 2017-01-07
    • 2014-11-26
    • 1970-01-01
    • 2014-04-04
    • 2012-07-23
    • 2010-12-27
    • 2011-01-01
    • 2011-05-31
    相关资源
    最近更新 更多