php - 当字段名称和值包含单引号时,PDO 插入失败 (42000/1064)

标签 php pdo prepared-statement

当 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:没有变化。

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

最佳答案

带引号的列名对于 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 中的错误是否已修复。还可以尝试使用位置参数(使用 ? 占位符)进行测试,看看是否可以解决问题。

关于php - 当字段名称和值包含单引号时,PDO 插入失败 (42000/1064),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49539667/

相关文章:

php - mysqli_fetch_array while 循环列

php - 在 select 语句中选择一个值

php - MYSQL UPDATE 字段具有另一个字段的值*并且*在 foreach 循环内的准备好的语句中使用 REPLACE

MySQL 如何使用变量创建准备语句?

php - 从变量中提取第一个数字

php - 什么是命名空间?

php - 循环$_POST

php - 带冒号的查询 ( :) in the search variable using pdo

php - PDO准备语句 'where'问题

java - SQL更新方程变量