标签: upsert

在 PostgreSQL 中实现 UPSERT 的惯用方式

我已经阅读了UPSERTPostgreSQL 中的不同实现,但所有这些解决方案都相对较旧或相对奇特(例如,使用可写 CTE)。

而且我根本不是 psql 专家,无法立即找出这些解决方案是否过时,因为它们被很好地推荐,或者它们(好吧,几乎所有这些都是)只是不适合生产使用的玩具示例。

在 PostgreSQL 中实现 UPSERT 的最线程安全的方法是什么?

postgresql plpgsql upsert

41
推荐指数
2
解决办法
5万
查看次数

如何使用单个查询插入或更新?

我有一个表测试,其中包含主键和自动递增的列 id 和名称。当且仅当没有记录时,我想插入一条新记录。例如

输入是 id=30122 和 name =john

如果有 ID 为 30122 的记录,那么我将 name 列更新为 john,如果没有记录,那么我将插入一条新记录。

我可以使用 2 个查询,例如

select * from test where id=30122
Run Code Online (Sandbox Code Playgroud)

如果它有一些记录,那么我可以使用 update test set name='john' where id=3012

或者如果它没有记录,那么我可以使用

insert into test(name) values('john')
Run Code Online (Sandbox Code Playgroud)

但我想使用单个查询?

有人可以告诉它是否可能吗?

sql-server merge upsert

38
推荐指数
2
解决办法
27万
查看次数

UPSERT 与 ON CONFLICT 使用 UPDATE 部分中的源表中的值

鉴于:

CREATE TABLE A (
PK_A INT8 NOT NULL,
A INT8,
PRIMARY KEY (PK_A)
);

CREATE TABLE B (
PK_B INT8 NOT NULL,
B INT8,
PRIMARY KEY (PK_B)
);
Run Code Online (Sandbox Code Playgroud)

这个查询:

insert into table_b (pk_b, b) 
select pk_a,a from table_a 
on conflict (b) do update set b=a;
Run Code Online (Sandbox Code Playgroud)

导致以下错误:

ERROR:  column "a" does not exist
LINE 1: ...elect pk_a,a from table_a on conflict (b) do update set b=a;
                                                                 ^
HINT:  There is a column named "a" in table "*SELECT*", but it cannot …
Run Code Online (Sandbox Code Playgroud)

postgresql upsert postgresql-9.5

27
推荐指数
2
解决办法
8万
查看次数

如何在 upsert 中获取冲突行的 ID?

我有一个tag包含 2 列的表:id(uuid) 和name(text)。我现在想在表中插入一个新标签,但如果该标签已经存在,我只想获取id现有记录的 。

我以为我可以ON CONFLICT DO NOTHING结合使用RETURNING "id"

INSERT INTO
    "tag" ("name")
VALUES( 'foo' )
ON CONFLICT DO NOTHING
RETURNING "id";
Run Code Online (Sandbox Code Playgroud)

但是,如果名称为“foo”的标签已经存在,则会返回一个空的结果集。

然后我将查询更改为使用 noopDO UPDATE子句:

INSERT INTO
    "tag" ("name")
VALUES( 'foo' )
ON CONFLICT ("name") DO UPDATE SET "name" = 'foo'
RETURNING "id";
Run Code Online (Sandbox Code Playgroud)

这按预期工作,但有点令人困惑,因为我只是将名称设置为已经存在的值。

这是解决这个问题的方法还是我缺少更简单的方法?

postgresql upsert postgresql-9.5

22
推荐指数
1
解决办法
1万
查看次数

将元素插入表格时,“列引用不明确”

我使用 PostgreSQL 作为我的数据库。我需要在数据库中创建一个条目,如果它已经存在,只需更新其字段,但只有在未设置时才应更新其中一个字段。

我已经使用了这个问题的信息:https : //stackoverflow.com/questions/13305878/dont-update-column-if-update-value-is-null,它与我所拥有的非常相关。

我尝试使用此查询,但是当我运行它时,它会出错Column reference 'affiliate_code' is ambiguous

INSERT INTO accounts (id, token, affiliate_code)
VALUES (value1, value2, value3)
ON CONFLICT (id) DO
UPDATE SET token = value2,
  affiliate_code = COALESCE(affiliate_code, value3);
Run Code Online (Sandbox Code Playgroud)

(当然,实际值会被替换)。

如果我替换affiliate_code = COALESCE(affiliate_code, value3)affiliate_code = value3,一切正常,但不是我想要的方式。

我怎样才能使这项工作?

这是我的表的定义方式:

CREATE TABLE accounts (
  id VARCHAR NOT NULL UNIQUE,
  token VARCHAR NOT NULL,
  affiliate_code VARCHAR
);
Run Code Online (Sandbox Code Playgroud)

postgresql upsert coalesce

21
推荐指数
2
解决办法
2万
查看次数

带有 NULL 值的 PostgreSQL UPSERT 问题

我在 Postgres 9.5 中使用新的 UPSERT 功能时遇到问题

我有一个表,用于从另一个表聚合数据。复合键由 20 列组成,其中 10 列可以为空。下面我创建了我遇到的问题的较小版本,特别是 NULL 值。

CREATE TABLE public.test_upsert (
upsert_id serial,
name character varying(32) NOT NULL,
status integer NOT NULL,
test_field text,
identifier character varying(255),
count integer,
CONSTRAINT upsert_id_pkey PRIMARY KEY (upsert_id),
CONSTRAINT test_upsert_name_status_test_field_key UNIQUE (name, status, test_field)
);
Run Code Online (Sandbox Code Playgroud)

根据需要运行此查询(首先插入,然后插入只会增加计数):

INSERT INTO test_upsert as tu(name,status,test_field,identifier, count) 
VALUES ('shaun',1,'test value','ident', 1)
ON CONFLICT (name,status,test_field) DO UPDATE set count = tu.count + 1 
where tu.name = 'shaun' AND tu.status = 1 AND tu.test_field = …
Run Code Online (Sandbox Code Playgroud)

postgresql null upsert unique-constraint postgresql-9.5

20
推荐指数
2
解决办法
2万
查看次数

多个冲突目标

我在列ab. 我需要这样的东西:

insert into my_table (a, b) values (1, 2), (1, 2)
on conflict (a) do update set c = 'a_violation'
on conflict (b) do update set c = 'b_violation'
Run Code Online (Sandbox Code Playgroud)

所以一般我想根据冲突目标进行不同的更新 - 不支持上面的语法(只支持一个on conflict语句)。有没有其他方法可以做到这一点?

postgresql duplication upsert postgresql-10

16
推荐指数
1
解决办法
1万
查看次数

UPSERT - 有没有更好的替代 MERGE 或 @@rowcount 的方法?

不知道大家有没有遇到过类似UPSERT这个概念的T-SQL命令?使用选项 (1) 或 (2) 执行 INSERT|UPDATE 操作似乎过于复杂且容易出错。

客观的

确保所需的记录(在本例中为 employee_id 1)是最新的,而不必实质上编写相同的查询两次。

语境

  • 表名:员工
  • 员工id:有主键,身份属性设置为true

选项

  1. 执行 SQL UPDATE... 检查 @@rowcount = 0 和 @@error = 0 ... 如果需要,执行 SQL INSERT

    • 缺点:您实际上必须两次编写相同的查询,一次作为插入,一次作为更新
    • con: more code = more time typing
    • con: more code = more room for error

/sf/ask/77470221/ "Update using @@rowcount"

  1. execute a SQL MERGE
    • con: you effectively have to write the same query twice, once as an insert, once as an update
    • con: more code = more time typing
    • con: …

sql-server-2008 upsert

15
推荐指数
1
解决办法
3万
查看次数

并发事务导致竞争条件对插入具有唯一约束

我有一个 Web 服务(http api),它允许用户安静地创建资源。在身份验证和验证之后,我将数据传递给 Postgres 函数,并允许它检查授权并在数据库中创建记录。

我今天发现了一个错误,即在同一秒内发出了两个 http 请求,导致使用相同的数据两次调用此函数。函数内部有一个子句,它在表上进行选择以查看值是否存在,如果存在,则获取 ID 并在下一个操作中使用该 ID,如果不存在,则插入数据,获取返回 ID,然后在下一个操作中使用它。下面是一个简单的例子。

select id into articleId from articles where title = 'my new blog';
if articleId is null then
    insert into articles (title, content) values (_title, _content)
    returning id into articleId;
end if;
-- Continue, using articleId to represent the article for next operations...
Run Code Online (Sandbox Code Playgroud)

正如您可能猜到的那样,我对数据进行了幻读,其中两个事务都进入了if articleId is null then块并试图插入到表中。一个成功了,另一个失败了,因为一个领域的独特限制。

我已经环顾四周,看看如何抵御这种情况,并找到了一些不同的选择,但由于某些原因,它们似乎都不适合我们的需求,我正在努力寻找任何替代方案。

  1. insert ... on conflict do nothing/update...我首先查看了on conflict看起来不错的选项,但是唯一的选项是do nothing不返回导致冲突的记录的 ID,并且do update不会工作,因为它会导致触发器在实际数据时被触发没有改变。在某些情况下,这不是问题,但在许多情况下,这可能会使会话用户会话无效,这是我们无法做到的。 …

postgresql concurrency transaction plpgsql upsert

14
推荐指数
2
解决办法
1万
查看次数

使用xml参数插入多个数据时如何避免使用Merge查询?

我正在尝试使用一组值更新表。数组中的每一项都包含与 SQL Server 数据库表中的行匹配的信息。如果该行已存在于表中,我们将使用给定数组中的信息更新该行。否则,我们在表中插入一个新行。我已经基本上描述了 upsert。

现在,我试图在采用 XML 参数的存储过程中实现这一点。我使用 XML 而不是表值参数的原因是,执行后者时,我必须在 SQL 中创建自定义类型并将此类型与存储过程相关联。如果我以后更改了存储过程或数据库架构中的某些内容,则必须重做存储过程和自定义类型。我想避免这种情况。此外,TVP 相对于 XML 的优势对我的情况没有用,因为我的数据数组大小永远不会超过 1000。这意味着我不能使用这里提出的解决方案:How to insert multiple records using XML in SQL server 2008

此外,这里的类似讨论(UPSERT - 是否有更好的替代 MERGE 或 @@rowcount?)与我所问的不同,因为我试图将行插入到表中。

我希望我可以简单地使用以下一组查询来更新 xml 中的值。但这行不通。当输入是单行时,这种方法应该有效。

begin tran
   update table with (serializable) set select * from xml_param
   where key = @key

   if @@rowcount = 0
   begin
      insert table (key, ...) values (@key,..)
   end
commit tran
Run Code Online (Sandbox Code Playgroud)

下一个替代方法是使用详尽的 IF EXISTS 或其以下形式的变体之一。但是,我以次优效率为由拒绝了这一点:

IF (SELECT COUNT ... ) > 0 …
Run Code Online (Sandbox Code Playgroud)

xml sql-server stored-procedures t-sql upsert

11
推荐指数
1
解决办法
1万
查看次数