【问题标题】:UPSERT Postgres 9.5UPSERT Postgres 9.5
【发布时间】:2016-10-01 19:49:10
【问题描述】:

我在 CentOS 6 上使用 Postgres 9.5。 我有下表(DDL)。

CREATE TABLE core_table.user_list(
  user_id SMALLSERIAL DEFAULT nextval('core_table.user_list_user_id_seq'::regclass) NOT NULL,
  user_name VARCHAR(50) NOT NULL,
  full_name VARCHAR(255),
  role_id INTEGER DEFAULT 1,
  is_accessible INTEGER DEFAULT 1,
  remarks VARCHAR(255),
  password VARCHAR(50),
  customer_schema VARCHAR(50),
  core_schema VARCHAR(50),
  CONSTRAINT user_list_pkey PRIMARY KEY(user_id, user_name),
  CONSTRAINT user_list_user_id_key UNIQUE(user_id)
) 
WITH (oids = false);

现有 4 行数据。

Row 1:
user_id: 1
user_name: kelly
full_name: kelly petz
role_id: 1
is_accessible: 1
remarks: <null>
password: test123
customer_schema: kelly_db1
core_schema: kelly_db1

Row 2:
user_id: 2
user_name: kelly
full_name: kelly petz
role_id: 1
is_accessible: 1
remarks: <null>
password: test123
customer_schema: petz_db1
core_schema: kelly_db1

Row 3:
user_id: 3
user_name: sam
full_name: sam howiz
role_id: 1
is_accessible: 1
remarks: <null>
password: test456
customer_schema: kelly_db1
core_schema: kelly_db1

Row 4:
user_id: 4
user_name: jon
full_name: jon lam
role_id: 1
is_accessible: 1
remarks: <null>
password: test789
customer_schema: lam_db1
core_schema: lam_db1

我在尝试执行以下 UPSERT 时遇到错误。

INSERT INTO core_table.user_list 
(user_name, full_name, remarks, password, customer_schema, core_schema, role_id, is_accessible) 
VALUES 
('kelly', 'kelly petz', 'The Boss', 'test123', 'snoppy_db1', 'snoppy_db1', 1, 1) 
ON CONFLICT (user_name) 
DO UPDATE SET 
    password = 'test123', 
    remarks = 'The Boss';

错误是“错误:没有符合 ON CONFLICT 规范的唯一或排除约束”。

有人可以为我指出我的错误以及如何解决它吗?

【问题讨论】:

  • 对不起,我忘了提及我想要实现的目标。基本上,我想检查用户和 customer_schema 是否存在于记录中。如果存在,它会更新密码和备注字段。否则它会添加一条新记录。

标签: postgresql upsert


【解决方案1】:

如果您对user_name 列没有任何约束,则不会发生冲突,on conflict (user_name) 没有任何意义。

您需要在 user_name 列上设置某种唯一性约束。

例如

CREATE UNIQUE INDEX user_list_name_index on  user_list (user_name);

编辑以下评论:

看起来你想要这个表架构:

CREATE TABLE core_table.user_list(
  user_id SMALLSERIAL DEFAULT nextval('core_table.user_list_user_id_seq'::regclass) NOT NULL,
  user_name VARCHAR(50) NOT NULL,
  full_name VARCHAR(255),
  role_id INTEGER DEFAULT 1,
  is_accessible INTEGER DEFAULT 1,
  remarks VARCHAR(255),
  password VARCHAR(50),
  customer_schema VARCHAR(50),
  core_schema VARCHAR(50),
  CONSTRAINT user_list_pkey PRIMARY KEY(user_id, user_name),
  CONSTRAINT user_list_user_id_key UNIQUE(user_id),
  CONSTRAINT user_list_name_schema PRIMARY KEY(user_name, customer_schema),
) 
WITH (oids = false);

然后是这个on conflict 子句:

INSERT INTO core_table.user_list 
(user_name, full_name, remarks, password, customer_schema, core_schema, role_id, is_accessible) 
VALUES 
('kelly', 'kelly petz', 'The Boss', 'test123', 'snoppy_db1', 'snoppy_db1', 1, 1) 
ON CONFLICT (user_list_name_schema) 
DO UPDATE SET 
    password = 'test123', 
    remarks = 'The Boss';

【讨论】:

  • 感谢您的快速响应。重点是 user_name 和 customer_schema。不能存在同一对。
  • @ChristopherLim 然后在你的表创建中添加这个约束,命名它,并在你的on conflict子句中用这个约束的名称替换user_name
  • 谢谢。现在我知道了。感谢您的帮助 Mureinik 和 Denys。当我读到这个帖子时,stackoverflow.com/questions/36799104/… 我明白你的意思了。
【解决方案2】:

on conflict 子句在违反唯一约束时被调用。在给定的表中,user_name 不是唯一的(user_iduser_name 的组合是)。

如果您想使用这样的子句,您必须以某种方式使 user_name 唯一,例如,通过添加约束:

ALTER TABLE user_list ADD CONSTRAINT user_name_unique UNIQUE (user_name);

【讨论】:

  • 感谢您的快速响应。重点是 user_name 和 customer_schema。不能存在同一对。
  • @ChristopherLim 所以你需要对组合有一个独特的约束,并让on conflict 子句也与之相关,而不仅仅是user_name
  • 谢谢。现在我知道了。感谢您的帮助 Mureinik 和 Denys。当我读到这个帖子时,stackoverflow.com/questions/36799104/… 我明白你的意思了。
猜你喜欢
  • 2017-07-30
  • 1970-01-01
  • 2017-11-22
  • 1970-01-01
  • 2016-04-18
  • 1970-01-01
  • 2021-12-14
  • 2018-09-10
  • 2016-12-25
相关资源
最近更新 更多