【问题标题】:Syntax error with simple mysql transaction简单 mysql 事务的语法错误
【发布时间】:2015-09-12 20:12:58
【问题描述】:

我似乎无法弄清楚问题所在。我对事务相当陌生,看来我需要一个来插入下一个自动递增的 ID。

这是查询:

START TRANSACTION;
INSERT INTO posts (title, text, user, club, time) 
VALUES ('$title', '$text', '$name', '$club', '$time');
INSERT INTO post_likes (user, post) 
VALUES ('$name', LAST_INSERT_ID());
COMMIT;

在 INSERT INTO 帖子之前,语法错误让我无法接受。

【问题讨论】:

  • PDO 一次只支持发出一条查询语句。 START/END TRANSACTION 事件每个都算作一个语句,它会报告一个语法错误。使用$pdo->beginTransaction()$pdo->commit()php.net/manual/en/pdo.begintransaction.php,然后将每个 INSERT 语句作为单独的查询发出。
  • 这应该是答案! +1 @MichaelBerkowski
  • @TimeBigot 您能否发布执行此操作的上下文 PHP/PDO 代码?这将有助于我们做出适当的更正,而无需对您尝试使用它的方式做出假设。
  • 做到了!谢谢!如果我以后发布任何其他问题,请记住那个迈克尔。我在这里有点新。
  • 嘿@MichaelBerkowski,您介意发表您的评论作为答案吗?

标签: mysql pdo transactions


【解决方案1】:

PDO 的 query()prepare() 方法仅支持每次执行单个 SQL 语句,但通过调用 START TRANSACTION/COMMIT 以及指向 INSERT 附近的错误语法的错误消息,我们必须假设您正在尝试执行所有这些声明一次。这是行不通的,因为 PDO 不会在执行前将它们分隔在 ; 分隔符上。

PDO 提供 API 方法来处理代码中的事务,而不需要通过 PDO::beginTransaction()PDO::commit() 执行 SQL 语句。所以你必须将两个INSERT语句分开,并将它们包装在事务方法中,调用query()prepare()/execute()两次。

// Assuming your PDO connection is $pdo...
$pdo->beginTransaction();
$pdo->query("INSERT INTO posts (title, text, user, club, time)  VALUES ('$title', '$text', '$name', '$club', '$time')");
$pdo->query("INSERT INTO post_likes (user, post)  VALUES ('$name', LAST_INSERT_ID())");
$pdo->commit();

现在,没有看到您的原始 PDO 代码,我假设您当前如何直接使用变量执行它。 我们可以做出重大改进

PDO 对预准备语句有出色的支持,可提供强大的 SQL 注入保护。让我们使用命名参数来切换两个query()prepare()/execute() 的调用。此外,如果您愿意,您可以用$pdo->lastInsertId() 替换 MySQL 的原生 LAST_INSERT_ID()

$pdo->beginTransaction();

// Prepare the first statement
$stmt = $pdo->prepare('INSERT INTO posts (title, text, user, club, time) VALUES (:title, :text, :user, :club, :time)');
// Execute the statement with an array of bound values
$stmt->execute(array(':title' => $title, ':text' => $text, ':user' => $user, ':club' => $club, ':time' => $time));

// Prepare & execute the second one
$stmt = $pdo->prepare('INSERT INTO post_likes (user, post)  VALUES (:name, :post)');
$stmt->execute(array(':name' => $name, ':post' => $pdo->lastInsertId()));

// Commit it
$pdo->commit();

【讨论】:

    【解决方案2】:

    引用时间和用户带反引号,为保留字:

    START TRANSACTION;
    INSERT INTO posts (title, text, `user`, club, `time`) VALUES ('$title', '$text', '$name', '$club', '$time');
    INSERT INTO post_likes (user, post) VALUES ('$name', LAST_INSERT_ID());
    COMMIT; 
    

    如果启用 ANSI SQL 模式,您也可以使用 "(双引号)。

    See here

    【讨论】:

    • 不。 TIME 未保留 (dev.mysql.com/doc/refman/5.5/en/keywords.html) - 这是 PDO 不支持多个语句的问题。
    • 页面显示保留的关键字标有 (R)。 TIME 是作为函数名的关键字,但不是需要引用的保留关键字。
    • USER 也不是保留字。
    • 问题是错误发生在INSERT INTO,而不是usertime
    • 直到今天才知道保留字有什么大不了的。生病一定要把它们换掉。谢谢。
    猜你喜欢
    • 2012-11-05
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-19
    • 2017-03-18
    • 2013-11-28
    相关资源
    最近更新 更多