【问题标题】:mysql insert if not exists on joined tables如果连接表上不存在mysql插入
【发布时间】:2013-03-20 09:42:37
【问题描述】:

我的表格如下所示:

表格“帖子”

posts.id = PK, auto-increment
posts.text = varchar
posts.tag_id 1 = int, FK to tags.id
posts.tag_id 2 = int, FK to tags.id
posts.tag_id 3 = int, FK to tags.id

表格“标签”

tags.id = PK, auto-increment
tags.tag = varchar

现在我要插入以下数据:

text: 'lorem ipsum'
tag1: 'music'
tag2: 'pop'
tag3: 'singer'

所以我需要一个查询来检查 tag1/tag2/tag3 是否已经存在于“标签”中,否则插入它们,然后将它们作为外键 +“文本”插入到“帖子”中的新行中。

我查看了 mysql INSERT IF NOT EXISTS,但我只是卡住了,不知道从哪里开始。我知道我可以通过多个查询来处理它,但必须有另一种更轻松的方法来获得相同的结果。

有人有这方面的经验吗?

更新

我的一个朋友提出了这样的建议:

CREATE FUNCTION getTagID(tag VARCHAR('100')) RETURNS int

INSERT INTO posts (text,tag1,tag2,tag3) 
VALUES ('lorem ipsum', getTagID('music'), getTagID('pop'), getTagID('singer'));

当然 getTagId 的实现仍然缺失,但这有意义吗? getTagID 应该选择具有给定标签的 id,如果它不存在,则插入它并返回它。任何帮助表示赞赏。

解决方案

我在 MySql 中创建了一个自定义函数:

DELIMITER ;;

CREATE FUNCTION getTagID(tag VARCHAR(100)) RETURNS BIGINT
BEGIN
  DECLARE tagID BIGINT;
  SET tagID = (SELECT id FROM tags WHERE text = tag);
  IF tagID IS NULL
  THEN
    INSERT INTO tags (text) VALUES (tag);
    SET tagID = (SELECT LAST_INSERT_ID());
  END IF;
  RETURN tagID;
END;;

DELIMITER ;

现在我可以插入这样的帖子:

INSERT INTO posts (text,tag1,tag2,tag3) 
VALUES ('lorem ipsum', getTagID('music'), getTagID('pop'), getTagID('singer'));

使用该函数,仅当标签尚不存在时才插入“标签”并返回现有或新创建标签的 ID。 Yipeee :)

【问题讨论】:

    标签: mysql insert


    【解决方案1】:

    您必须插入帖子,然后插入标签。 SQL 中没有多表插入解决方案。

    您甚至不能从标签上的触发器将帖子文本插入到帖子中,因为插入标签只能携带属于标签的列。

    如果您需要避免标签表中的重复,您可以使用 INSERT IGNORE 或 REPLACE 或 INSERT ... ON DUPLICATE KEY UPDATE。有关详细信息,请参阅我对 "INSERT IGNORE" vs "INSERT ... ON DUPLICATE KEY UPDATE" 的回答。


    请回复您的评论。

    只有让自增机制生成新的id,才能得到生成的PK。如果您让自动增量发生,则保证不会导致重复 PK。

    如果您指定一个 id 并绕过自动增量,则无论如何您都无法获取该 id。但是,如果您在 INSERT 中指定了该值,则无需查询该值——您应该已经拥有它。

    唯一的另一种情况是,如果您有一个非自动递增的辅助唯一键。

    CREATE TABLE foo (id int auto_increment primary key, name varchar(10), unique key (name));
    INSERT INTO foo (name) VALUES ('bill');
    SELECT LAST_INSERT_ID(); -- returns 1
    INSERT INTO foo (name) VALUES ('bill');
    SELECT LAST_INSERT_ID(); -- returns 1
    

    这有点令人困惑,因为最后一个插入 id 来自成功并生成一个 id 的最后一个 INSERT。


    使用INSERT INTO posts (text,tag1,tag2,tag3) 重新更新您的信息。这称为repeating groups。如果你需要四个标签怎么办?如果帖子只有两个标签怎么办?您如何对具有给定标签的帖子进行索引搜索?

    【讨论】:

    • 谢谢!如果我使用 INSERT IGNORE 插入后可以得到 PK 吗?我可以在 1 个事务中的下一个语句中使用它吗?
    • 我在应用服务器端使用 PDO / PHP
    • 在上面添加了另一个想法...似乎没有人关心 ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-14
    • 2011-08-12
    • 1970-01-01
    • 1970-01-01
    • 2011-01-14
    • 2011-08-27
    • 2012-06-09
    相关资源
    最近更新 更多