Postgres使用其他表插入冲突更新

时间:2016-10-10 02:43:27

标签: sql postgresql

我有以下sql的语法错误,花了一个小时,但无法找到postgres文档的任何答案。

CREATE TABLE transaction (userid SMALLINT, point INT, timestamp TIMESTAMPTZ);
CREATE TABLE point (userid SMALLINT PRIMARY KEY, balance1 INT, balance2 INT);
CREATE TABLE settings (userid SMALLINT, bonus INT);
INSERT INTO settings VALUES (1, 10); -- sample data

WITH trans AS (
  INSERT INTO transaction (userid, point, timestamp) 
  VALUES ($1, $2, NOW()) 
  RETURNING *
)
INSERT INTO point (userid, balance1) 
SELECT userid, point 
FROM trans -- first time
ON CONFLICT (userid) DO UPDATE 
  SET balance1=point.balance1 + excluded.balance1, 
      balance2=point.balance2 + excluded.balance1 + settings.bonus 
FROM settings -- tried USING, not work
WHERE settings.userid=excluded.userid;

我的问题是如何在更新期间不使用FROM而包含额外的表格?我的目标是将所有内容保留为1个查询。

1 个答案:

答案 0 :(得分:1)

我并不完全清楚你要做什么。我理解它的方式是,在settings.bonus启动时更新行时,您尝试使用on conflict中的值。

这可以使用UPDATE部分中的共同相关子查询来完成:

WITH trans (userid, point, timestamp) AS (
  INSERT INTO transaction (userid, point, timestamp) 
  VALUES (1, 1, NOW()) 
  RETURNING *
)
INSERT INTO point (userid, balance1) 
SELECT trans.userid, trans.point 
FROM trans 
ON CONFLICT (userid) DO UPDATE 
  SET balance1 = point.balance1 + excluded.balance1, 
      balance2 = point.balance2 + excluded.balance1 + (select s.bonus 
                                                       from settings s 
                                                       where s.userid = excluded.userid)

但请注意,balance2永远不会以这种方式递增,因为在第一个插入时,null后续更新将尝试向null添加内容但是任何涉及null的表达式null(null + 5为null)。

因此,您需要在第一次插入时插入0,或在执行更新时使用coalesce(),例如

balance2 = coalesce(point.balance2, 0) + excluded.balance1 + (select ...);

如果该用户settings中没有行可能,那么您需要在子查询的结果上应用coalesce()以及:

... excluded.balance1 + coalesce( (select ... ), 0)

另外:您在问题中使用excluded.point这是不正确的。 excluded指的是目标表point,但没有列点 - 您可能意味着:excluded.balance1(因为插入的trans.point将插入的列)< / p>

无关,但是:timestamp是列的可怕名称。一个是因为它是一个关键字,但更重要的是因为它没有记录列的用途。是否意味着&#34;创建于&#34;? &#34;有效期至&#34;? &#34;从&#34;开始? &#34;过时了#34;?完全不同的东西?