【问题标题】:Postgres Insert/Update query not working as expectedPostgres 插入/更新查询未按预期工作
【发布时间】:2016-03-24 02:43:43
【问题描述】:

这是我正在尝试编写的查询的简化版本。它旨在将一行保存为变量combine,然后UPDATE media_hashtags 表(如果存在特定条目),否则插入该条目。

    WITH 
      combine AS (
        SELECT * FROM hashtags WHERE hashtag_text='HOPPA'
      )
    UPDATE media_hashtags SET hashtag_id = (SELECT id FROM combine) WHERE user_id = 58 AND media_id=161;
      INSERT INTO media_hashtags (media_id, user_id, hashtag_id)
    SELECT 161, 58, (SELECT id FROM combine)
    WHERE NOT EXISTS (
      SELECT * FROM media_hashtags
      WHERE (
        user_id = 58 AND
        media_id = 161
      )
    )

    RETURNING *

但是,我得到了这个错误:

ERROR:  relation "combine" does not exist
LINE 8:      SELECT 161, 58, (SELECT id FROM combine)

有趣的是,如果我只使用UPDATEINSERT 命令进行查询,那么它会按预期执行。仅当我同时执行这两项操作时才会发生错误。关于问题是什么以及解决方法的任何想法?

【问题讨论】:

  • 这里似乎有两个单独的查询(查找分号)。很自然,第二个看不到第一个的combine
  • 这是有道理的。我想我可以重新编写组合,但这会很冗长。有没有更好的方法来解决这个问题?

标签: postgresql sql-update sql-insert


【解决方案1】:

您有两个查询,第一个查询在 UPDATE 语句之后以 ; 结尾。以下INSERT 不再看到 CTE,因为它是一个新语句。

如果您想将其作为单个语句运行,您需要将 UPDATE 移动到它自己的 CTE 中:

WITH combine AS (
    SELECT id 
    FROM hashtags 
    WHERE hashtag_text='HOPPA'
), changed AS (
  UPDATE media_hashtags 
     SET hashtag_id = (SELECT id FROM combine) 
  WHERE user_id = 58 
    AND media_id=161
)  
INSERT INTO media_hashtags (media_id, user_id, hashtag_id)
SELECT 161, 58, (SELECT id FROM combine)
WHERE NOT EXISTS (
  SELECT * FROM media_hashtags
  WHERE (
    user_id = 58 AND
    media_id = 161
  )
)
RETURNING *;

您还应该只在初始 CTE 中选择您需要的列。后续语句仅使用来自 combine 的单个列这一事实不会被推送到第一个查询中,因此 Postgres 可能无法尽可能高效地查询 hashtags


如果您使用的是 Postgres 9.5,您可以使用 on conflict 子句为 insert 语句简化语句:

INSERT INTO media_hashtags (media_id, user_id, hashtag_id)
SELECT 161, 58, id
FROM hashtags 
WHERE hashtag_text='HOPPA'
ON CONFLICT (media_id, user_id) DO UPDATE 
  SET hashtag_id = excluded.hashtag_id;

这需要media_hashtags(media_id, user_id) 上的唯一索引

【讨论】:

    【解决方案2】:

    您可以使用临时表来存储来自主题标签的数据,然后进行插入和更新操作。

    方法如下:

    DROP TABLE IF EXISTS temp_hashtags;
    CREATE TEMP TABLE temp_hashtags AS
    SELECT * FROM hashtags WHERE hashtag_text='HOPPA';
    
    UPDATE media_hashtags 
        SET hashtag_id = (SELECT id FROM temp_hashtags) 
    WHERE user_id = 58 AND media_id=161;
    
    INSERT INTO media_hashtags (media_id, user_id, hashtag_id)
    SELECT 161, 58, (SELECT id FROM temp_hashtags)
    WHERE NOT EXISTS (
            SELECT * FROM media_hashtags
            WHERE user_id = 58 AND media_id = 161
            );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-13
      • 1970-01-01
      • 2015-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多