【问题标题】:nested insert in mysql for taggingmysql中的嵌套插入用于标记
【发布时间】:2009-01-26 15:04:48
【问题描述】:

我想用一条 sql 语句为博文添加标签。

假设我的表格如下所示:

tags
+-------+-----------+
| tagid | tag       |
+-------+-----------+
|     1 | news      | 
|     2 | top-story | 
+-------+-----------+

tag2post
+----+--------+-------+
| id | postid | tagid |     
+----+--------+-------+
|  0 |    322 |     1 |
+----+--------+-------+

我要解决的问题是插入一个新标签检索它的id,然后将这个新的id插入到关系表中 > 在单个 sql 语句中。

INSERT INTO tag2post (postid, tagid)
VALUES
(
    332, # the post
    IF (
        (SELECT tagid FROM tags WHERE tag = 'new_tag'),
        (SELECT tagid FROM tags WHERE tag = 'new_tag'),
         # here is where i'd like to insert 
         # the new_tag and return it's id
        'i am lost here'
    )
)

【问题讨论】:

    标签: mysql tags tagging


    【解决方案1】:

    您不能将其作为单个插入来执行,因为插入是原子的 - 也就是说,在语句完成之前不会确定 ID。

    将这两个语句包装在一个事务中,您将获得您的 ID 和原子性。

    【讨论】:

    • 最近的 mysql 版本可以做存储过程,所以我想说这是一个完美的地方:InsertOrCreateTag(@TagName),返回标签 ID。
    【解决方案2】:

    我认为你必须打破它。一种方法是将UNIQUE 约束添加到tag 并按以下步骤操作:

    INSERT IGNORE INTO tags (tag) VALUE ('new_tag')
    

    然后

    INSERT INTO tag2post (postid, tagid)
    VALUES
    (
        332, # the post
        (SELECT tagid FROM tags WHERE tag = 'new_tag')
    )
    

    INSERT IGNORE 但是可能无法很好地扩展。所以另一种选择是做SELECT,如果id不存在,INSERT,那么如果另一个线程/进程/服务修改了你的SELECT和现在之间的表,请务必在此处捕获异常。在INSERT 你做LAST_INSERT_ID() 并且他抓住你重复最初的SELECT..

    不太好,但如果需要并发性,则需要这样做。事务不会缓解问题,如果您对tag 没有UNIQUE 约束,您最终可能会得到重复的INSERTs。

    【讨论】:

      【解决方案3】:

      不要使用自动递增的 ID 列,而是使用 GUID 列。然后,您可以在运行语句之前生成 GUID 并立即执行所有操作。

      即使是Jeff Atwood likes this approach,也不会因为使用 32 字符字符串而不是整数而显着降低速度。

      另外,为了防止标签重复,您应该使用标签名称的 MD5 和作为标签 ID。

      【讨论】:

      • +1。如果即使杰夫阿特伍德也喜欢它,那一定是有福的方式。 :-D
      • ehhh ...您将tagid替换为md5(tagid,tag)?不是有什么奇怪的递归可以打破宇宙吗?
      • 不,您将 tagid 替换为 md5(tag)。由于表中没有其他数据,并且由于重复使用行对查询很有效,因此没有理由添加额外的 ID 列。
      【解决方案4】:

      你可以试试这个,如果它无法选择它,有效地执行插入,然后从插入的行中检索 LAST_INSERT_ID(),但我严重怀疑它会起作用。

      INSERT INTO tag2post (postid, tagid)
      VALUES
      (
          332, # the post
          IF (
              (SELECT tagid FROM tags WHERE tag = 'new_tag'),
              (SELECT tagid FROM tags WHERE tag = 'new_tag'),
              IF (
                  (INSERT INTO tags (tag) VALUES ('new_tag')),
                  LAST_INSERT_ID(),
                  LAST_INSERT_ID()
              )
          )
      )
      

      【讨论】:

        【解决方案5】:

        如果您使用非自动增量字段并进行自己的增量计算,您可以在插入字段之前确定 id 是什么,并手动指定新的 id。

        然后你可以为每个 tag2post 条目构建一个语句字符串,使用这些 ;s 分隔的 id,你可以将它发送到 msyql 执行。

        【讨论】:

          猜你喜欢
          • 2021-02-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-08-23
          • 2018-12-29
          • 2018-06-19
          • 2016-04-18
          • 2017-10-29
          相关资源
          最近更新 更多