【发布时间】:2019-09-15 05:17:58
【问题描述】:
我的博客有以下表格:
表 tags 包含列 tag_id (A.I.) 和 tag
表post_tags 具有列post_id 和tag_id。它描述了哪些标签属于哪些帖子。
我正在尝试进行一些 SQL 查询,将给定的tag 绑定到post_tags 中的给定post_id,但如果tag 在tags 中不存在,它会首先在那里创建它。
$query =
SQL
DELIMITER //
BEGIN NOT ATOMIC
IF NOT EXISTS (SELECT `tags`.`tag` FROM `tags` WHERE `tag` = :tagname) THEN
INSERT INTO `tags` (`tag_id`, `tag`) VALUES (NULL, :tagname);
END IF;
END //
DELIMITER ;
INSERT INTO post_tags (post_id, tag_id) SELECT :postid, tags.tag_id FROM tags WHERE tags.tag = :tagname;
然后我有以下 PHP 代码来执行这个过程:
// all $db variables are given, known and correct.
$pdoconn = new PDO("mysql:host=$dbhost;dbname=$db", $dbuser, $dbpass);
$pdoconn -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$taginsert = $pdoconn -> prepare($query);
$id = 0; // The post_id. This is given, known and correct.
$tags = array(); // Array of strings (the tags)
foreach ($tags as $tag){
try{
$taginsert -> bindValue(":tagname", $tag, PDO::PARAM_STR);
$taginsert -> bindValue(":postid", $id, PDO::PARAM_INT);
$taginsert -> execute();
} catch(PDOException $e){
$message = $e->getMessage();
var_dump($message);
}
}
$taginsert -> close();
这应该足够简单。事实上,当替换实际值的占位符并从 phpMyAdmin 中执行原始查询时,它可以工作!但是当我执行 pdo php 代码时,它只是转储了这个错误:
string(284) "SQLSTATE[42000]: 语法错误或访问冲突:1064 您的 SQL 语法有错误;请查看与您的 MariaDB 服务器版本相对应的手册,了解在 'DELIMITER // 附近使用的正确语法如果不存在则开始非原子(从
tags' at line 1"中选择tags.tag不用说这个神秘的错误信息对我没有用。
我正在使用 php 7.3 和 10.1.30-MariaDB-1~xenial
【问题讨论】:
-
尝试删除分隔符,因为它只需要命令行。此外,PDO 一次只能处理 1 个查询语句,因此您必须将其分解为两个单独的查询。
-
我不是 100% 确定 MariaDB,但我不相信 MySQL 在存储过程和函数定义。在过去,当需要它并且允许连接时,我能够制作“临时”存储过程来做我需要的事情,然后再删除它们。 (3 个查询:create proc、exec proc、drop proc)
-
@aynber 解决了错误,但也给出了一个新的:(11 确实是它卡住的帖子) SQLSTATE[42000]:语法错误或访问冲突:1064 你有一个错误你的 SQL 语法;检查与您的 MariaDB 服务器版本相对应的手册,以在第 7 行的 'INSERT
post_tags(post_id,tag_id) SELECT 11,tags.tag_idFROMtags' 附近使用正确的语法。所以,是的,我会分手的。 -
我认为整个任务可以用一个语句来完成。请参阅 IODKU 和 LAST_INSERT_ID()。
标签: php mysql if-statement pdo mariadb