SQLSTATE[42000]: 语法错误或访问冲突: 1064 您的SQL语法存在错误 — PHP — PDO

86

我查看了所有其他具有相同问题的StackOverflow(和Google)帖子,但似乎都没有解决我的问题。

我正在使用PDO和PHP。

我的代码:

$vals = array(
   ':from'    => $email,
   ':to'      => $recipient,
   ':name'    => $name,
   ':subject' => $subject,
   ':message' = >$message
);
print_r($vals);
try {
   $pdo = new PDOConfig();
   $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
   $sql = "SELECT * FROM messages WHERE `message` LIKE :message";
   $q = $pdo->prepare($sql);
   $q->execute(array(':message' => $vals[':message']));
   $resp = $q->fetchAll();

   foreach ($resp as $row) {
      throw new Exception('Please do not post the same message twice!');
   }

   $sql = "INSERT INTO messages (from, to, name, subject, message) VALUES (:from, :to, :name, :subject, :message)";
   $q = $pdo->prepare($sql);
   $q->execute($vals);
} 
catch(PDOException $e) {
   echo $e->getMessage();
}

第一个 print_r 输出的是

Array ( [:from]    => abc@gmail.com 
        [:to]      => lala@me.com 
        [:name]    => abc 
        [:subject] => abc 
        [:message] => abc )

预期的情况是所有值都不为null

但是它却输出了以下错误信息

SQLSTATE[42000]: 语法错误或访问违规:1064 在您的MySQL服务器版本中使用正确的语法,请参阅手册附带的语法 to use near 'from, to, name, subject, message) VALUES ('abc@gmail.com', 'lala@me.com' at line 1

不知道如何解决。有什么想法吗?


我曾经遇到过同样的问题,只需添加 $stmt->bindParam(1,$var_name); 即可解决我的问题。 - PHPFan
4个回答

138

from是SQL中的关键词。如果没有引用它,您可能无法将其用作列名称。在MySQL中,像列名称这样的东西使用反引号进行引用,即`from`

个人而言,我不会费心;我只会重命名该列。

PS:正如评论中指出的那样,to是另一个SQL关键字,因此也需要引用。方便地,drupal.org的人们维护了一份SQL保留字列表


5
“order”也被保留了。哦!感谢您的帖子 :-) - Mike
“UNLOCK”也是保留关键字(https://dev.mysql.com/doc/refman/5.5/en/keywords.html):-)谢谢,我也遇到了同样的问题。 - Aditya M P
我是通过搜索类似的问题找到这个问答的。他们(楼主)勾选了 from,但之后没有勾选 to。看看他们编辑后发布的错误信息:right syntax to use near 'to,编辑链接为 http://stackoverflow.com/posts/4544051/revisions。回答应该根据此进行编辑。楼主还使用勾选的 from 编辑了他们的问题,我已将问题回滚到原始状态。 - Funk Forty Niner
保留字“link”的链接已更改。请访问https://dev.mysql.com/doc/refman/5.7/en/keywords.html。 - sansknwoledge

41

我遇到了完全相同的错误,但在我的情况下,我在为LIMIT子句绑定值时没有指定类型。我把这个信息放在这里,以防有人因为同样的原因而遇到这个错误。如果不指定类型,LIMIT :limit OFFSET :offset;会导致LIMIT '10' OFFSET '1';,而不是LIMIT 10 OFFSET 1;。下面的内容可以帮助纠正这个问题:

$stmt->bindParam(':limit', intval($limit, 10), \PDO::PARAM_INT);
$stmt->bindParam(':offset', intval($offset, 10), \PDO::PARAM_INT);

10
关闭模拟也有帮助。 - Your Common Sense
1
@你的常识:为什么有帮助?我也遇到了同样的限制值绑定问题,关闭仿真确实有所帮助 :) 但是为什么呢? - CoR
2
@CoR 在他链接的维基中已经很好地解释了。PDO默认将占位符参数视为字符串(启用仿真)。限制变成“... LIMIT '10' OFFSET '1';”,这不是你想要的。如果关闭仿真,MySQL将根据它们的类型处理占位符值。 - uKolka

2
ALTER TABLE `{$installer->getTable('sales/quote_payment')}`
ADD `custom_field_one` VARCHAR( 255 ) NOT NULL,
    ADD `custom_field_two` VARCHAR( 255 ) NOT NULL;

正确添加反引号,即 " ` "。在反引号之间编写您的getTable名称和列名。


那非常好。 - adib16

1

在尝试从多维数组中插入数据库值时,SQL查询中出现了相同的pdo错误:

$sql = "UPDATE test SET field=arr[$s][a] WHERE id = $id";
$sth = $db->prepare($sql);    
$sth->execute();

从 SQL 查询中提取数组 arr[$s][a],使用包含它的变量来替代可以修复问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接