在一个mySQL查询中更新几个post_meta数据

时间:2012-04-22 15:47:16

标签: mysql

我想对WordPress网站(wp_postmeta表)中帖子的元数据执行一些更新。 已知的good'ol函数update_post_meta()正在执行该作业,并且还将检查并且如果密钥不存在,则将添加它。 但是,此功能一次只能处理一个帖子。 我想节省昂贵的数据库调用,并使用一个查询更新几个字段以用于不同的帖子ID。

通常,我可以使用my UPDATE查询与CASE进行切换,并根据meta_value分配每个post_id,例如in this example,并更新一些值表中的不同行。 但是,对于某些帖子而言,meta_key尚未存在,因此需要INSERT而不是更新。好吧,如果不使用update_post_meta(),我应该以某种方式检查。 我尝试使用INSERT .... ON DUPLICATE UPDATEsyntax)和REPLACEsyntax),但它仅适用于唯一或定义为主键的列,因此它不会在这种情况下无济于事。

我是否有办法或想法如何拥有“插入值,如果已经存在此post_id的meta_key则更新”,并为几个不同的post_id执行此操作(但是一直使用相同的meta_key),并使用一个单个mySQL查询?

由于 (*我也在WordPress的答案中问过这个问题,并在这里问过)

1 个答案:

答案 0 :(得分:1)

REPLACEINSERT ... ON DUPLICATE KEY UPDATE “仅与唯一或定义为主键的列相关”,而是确定记录是新的还是现有的(因此需要更换/更新)是否存在唯一的密钥冲突。正如MySQL documentation所述:

  

MySQL对REPLACE(和LOAD DATA ... REPLACE)使用以下算法:

     
      
  1. 尝试将新行插入表格

  2.   
  3. 插入失败,因为主键或唯一索引出现重复键错误:

         

    一个。从表中删除具有重复键值

    的冲突行      

    湾再次尝试将新行插入表

  4.   

它描述了INSERT ... ON DUPLICATE KEY UPDATE similarly

因此,如果您的REPLACEINSERT ... ON DUPLICATE KEY UPDATE命令通过当前主键识别更新的记录,则应该按照您的意愿执行。根据{{​​3}},主键是meta_id字段,因此使用SELECT您可以获得现有案例的此标识符,并使用外部联接获取NULL它尚不存在(WordPress documentation):

REPLACE INTO `wp_postmeta` (
      `meta_id`
    , `post_id`
    , `meta_key`
    , `meta_value`
)
    SELECT
          `meta_id`
        , `post_id`
        , "key of interest"
        , "new value" -- assuming all posts to be set the same
    FROM
        `wp_postmeta`
        NATURAL RIGHT JOIN (
           SELECT 1 AS `post_id` -- where 1 is the first post_id
           UNION SELECT 2        -- 2 is the second
           UNION SELECT 3        -- 3 is the third
           -- etc.
        ) AS `temp_table`
    WHERE
        `meta_id` IS NULL OR `meta_key` = "key of interest"
;

如果每个帖子的新元数值不同,您可以在temp_table中添加第二列这样的值:

REPLACE INTO `wp_postmeta` (
      `meta_id`
    , `post_id`
    , `meta_key`
    , `meta_value`
)
    SELECT
          `meta_id`
        , `post_id`
        , "key of interest"
        , `new_value`
    FROM
        `wp_postmeta`
        NATURAL RIGHT JOIN (
           SELECT 1 AS `post_id`, "foo" AS `new_value`
           UNION SELECT 2, "bar"
           UNION SELECT 3, "qux"
           -- etc.
        ) AS `temp_table`
    WHERE
        `meta_id` IS NULL OR `meta_key` = "key of interest"
;