【问题标题】:PostgreSQL UPSERT (INSERT ... ON CONFLICT UPDATE) failsPostgreSQL UPSERT (INSERT ... ON CONFLICT UPDATE) 失败
【发布时间】:2021-06-07 15:40:07
【问题描述】:

我的 postgresql 数据库中有一行要更新。

=> SELECT * FROM reading_group_reading_session
WHERE group_id = 439 
  AND group_type = 'focus_group' 
  AND reg_user_id = 28056 
  AND device_id = ''
  AND reading_date = '2021-06-03';
  id   | group_id | group_type  | reg_user_id | device_id | reading_date | seconds_reading | num_syncs 
-------+----------+-------------+-------------+-----------+--------------+-----------------+-----------
 35532 |      439 | focus_group |       28056 |           | 2021-06-03   |            3310 |         4
(1 row)

Time: 1.820 ms
=> 

我的代码生成此 SQL 语句以插入 else 更新已更改的字段:

=> INSERT INTO
[more] - >   INSERT INTO reading_group_reading_session
  (group_id,group_type,reg_user_id,device_id,reading_date,seconds_reading)
VALUES
  (439,'focus_group',28056,'','2021-06-03',3320)
ON CONFLICT
  (group_id, group_type, reg_user_id, device_id, reading_date)
DO UPDATE SET
    seconds_reading = 3320;
ERROR:  23502: null value in column "num_syncs" violates not-null constraint
DETAIL:  Failing row contains (115399, 439, focus_group, 28056, , 2021-06-03, 3320, null).
SCHEMA NAME:  public
TABLE NAME:  reading_group_reading_session
COLUMN NAME:  num_syncs
LOCATION:  ExecConstraints, execMain.c:1700
Time: 3.017 ms
=> 

我不明白的是,我可以选择这一行,并且它以非 NULL num_syncs 存在。但是 UPSERT 失败了,因为它没有(重新)设置 num_syncs(值 4 不变)。

有人知道我错过了什么吗?

Fwiw,表定义是这样的:

                                  Table "public.reading_group_reading_session"
     Column      |      Type       |                                 Modifiers                                  
-----------------+-----------------+----------------------------------------------------------------------------
 id              | integer         | not null default nextval('reading_group_reading_session_id_seq'::regclass)
 group_id        | integer         | not null
 group_type      | group_type_name | 
 reg_user_id     | integer         | not null
 device_id       | text            | 
 reading_date    | date            | 
 seconds_reading | integer         | not null
 num_syncs       | integer         | not null
Indexes:
    "reading_group_reading_session_pkey" PRIMARY KEY, btree (id)
    "reading_group_reading_session_idx_dgid" UNIQUE, btree (group_id, group_type, reg_user_id, device_id, reading_date)
Check constraints:
    "reading_group_reading_session_group_id_check" CHECK (group_id > 0)
    "reading_group_reading_session_minutes_reading_check" CHECK (seconds_reading >= 0)
    "reading_group_reading_session_num_syncs_check" CHECK (num_syncs >= 0)
    "reading_group_reading_session_reg_user_id_check" CHECK (reg_user_id >= 0)

=>

【问题讨论】:

    标签: sql postgresql postgresql-9.5 upsert


    【解决方案1】:

    首先检查NOT NULL 约束。这是有道理的,因为他们必须满足INSERT 才能成功。

    如果您确定已经存在匹配行,请使用常规 UPDATE。

    另一种方法可能是使用CHECK (colname IS NOT NULL) 约束而不是NOT NULL。

    【讨论】:

    • 啊,有道理。如果需要,我的逻辑会创建一个有效的 INSERT,但由于它没有,它不必担心丢失的列。所以我需要更新逻辑来决定客户端是插入还是更新。
    • 我认为INSERT ... ON CONFLICT 比在客户端执行逻辑要好。它通过并发插入保护您免受竞争条件的影响。
    猜你喜欢
    • 2016-07-21
    • 2023-02-04
    • 2018-08-02
    • 1970-01-01
    • 2017-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-17
    相关资源
    最近更新 更多