标签: upsert

如何将值传递给不是列的 ON CONFLICT 子句?

基本上,我试图在 postgresql 中的单个命令中进行多次插入,其中我ON CONFLICT有一个 per-insert 参数。

这是查询(格式为psycopg2):

INSERT INTO
    web_pages
    (url, starturl, netloc, distance, is_text, 
     priority, type, addtime, state)
VALUES
    (%(url)s, %(starturl)s, %(netloc)s, %(distance)s, %(is_text)s, 
      %(priority)s, %(type)s, %(addtime)s, %(state)s)
ON CONFLICT (url) DO
    UPDATE
        SET
            state           = EXCLUDED.state,
            starturl        = EXCLUDED.starturl,
            netloc          = EXCLUDED.netloc,
            is_text         = EXCLUDED.is_text,
            distance        = LEAST(EXCLUDED.distance, web_pages.distance),
            priority        = GREATEST(EXCLUDED.priority, web_pages.priority),
            addtime         = LEAST(EXCLUDED.addtime, web_pages.addtime)
        WHERE
        (
                web_pages.ignoreuntiltime < %(ignoreuntiltime)s
            AND
                web_pages.url = EXCLUDED.url
            AND
                (web_pages.state = 'complete' OR web_pages.state = 'error') …
Run Code Online (Sandbox Code Playgroud)

postgresql upsert postgresql-9.6

6
推荐指数
1
解决办法
5697
查看次数

PostgreSQL/Psycopg2 upsert 语法更新列

当出现 id 冲突时,我想让 Psycopg2 更新col1、col2和col3。

在我的 Python 代码中,我目前的插入 SQL 为:

insert_sql = '''INSERT INTO {t} (id,col1,col2,col3)
        VALUES (%s,%s,NULLIF(%s, 'nan'), NULLIF(%s, 'nan'))
        ON CONFLICT (id)
        DO NOTHING;'''
Run Code Online (Sandbox Code Playgroud)

基本上我想设置而不是什么都不做:

(col1,col2,col3) = (%s,NULLIF(%s, 'nan'), NULLIF(%s, 'nan'))

忽略插入 ID 并更新 col1、col2 和 col3。问题是%s使用 Psycopg2 在 Python 中传递元组变量:

cur.execute(insert_sql.format(t='my_table'),(int(id),new_col1,new_col2,new_col3))
Run Code Online (Sandbox Code Playgroud)

用于引用%s对应于 col1、col2 和 col3 以更新 ON CONFLICT的语法是什么?

postgresql insert python upsert

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

用于仅更新 UPSERT 中更改的行的语法简写

我有一个查询,当一个键冲突时,只有在其他列之一发生更改时才会向上插入 Postgres(以避免不必要的插入和返回的行,但实际上没有任何更改):

INSERT INTO public.test_upsert (some_id, a, b, note) 
VALUES 
  ('c', 1, true, 'asdf')
ON CONFLICT (some_id)
DO UPDATE SET 
  a = excluded.a, 
  b = excluded.b, 
  note = excluded.note 
WHERE
  test_upsert.a IS DISTINCT FROM excluded.a OR 
  test_upsert.b IS DISTINCT FROM excluded.b OR
  test_upsert.note IS DISTINCT FROM excluded.note
RETURNING *;
Run Code Online (Sandbox Code Playgroud)

我的问题是:这个有简写吗?我基本上想在插入的任何列与现有列不同时插入新记录更新行。单独写出每一列会变得非常冗长,尽管它更明确。

postgresql syntax update upsert

6
推荐指数
1
解决办法
580
查看次数

插入和更新的单独存储过程?

我在 Microsoft SQL Server 中有一个表。有时需要更新,有时需要插入。我可以写2个存储过程:

InsertNewPerson
UpdatePertsonById
Run Code Online (Sandbox Code Playgroud)

但我正在考虑编写 1 个存储过程而不是 ( SetPerson),这两个过程都可以(如果有ID,则是update操作,否则insert)。

我应该创建一个存储过程(只需要维护一个)还是应该创建两个不同的存储过程?

sql-server-2008 sql-server stored-procedures physical-design upsert

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

Postgres 批量更新插入性能

我正在对一个包含 3000 万行的表进行批量 UPSERT。该表只有两列(varchar 作为主键和整数)。首先将输入数据导入到临时表中,然后执行批量更新插入(使用 INSERT ... ON CONFLICT DO UPDATE 语句)。批量大小为 4000。

我的问题是 - 您能给我哪些性能建议?当表较小时(5-1000万条记录),性能就足够好了。对于 3000 万行,这还不够好,单批 4000 条记录持续 2 到 30 秒。

当然,我几乎没有并行执行此导入的服务,因此我使用咨询锁来同步它们(一次仅执行一个批量更新插入)。我是否应该删除咨询锁以并行执行更新插入?然后我将不得不处理死锁(并使用较小的批量大小来减少死锁机会?)。

我可以采取哪些措施来提高批量更新插入的性能?

这是我的大表:

CREATE TABLE my_big_table (
  sender VARCHAR(30) PRIMARY KEY,
  count  INTEGER NOT NULL DEFAULT 0
)
WITH (
  fillfactor = 80,
  autovacuum_vacuum_scale_factor = 0,
  autovacuum_vacuum_threshold = 40000
);
Run Code Online (Sandbox Code Playgroud)

这是 UPSERT 查询:

INSERT INTO my_big_table AS MBT (sender, count)
    SELECT destination, count(*) as received_count
    FROM my_temp_table
    GROUP BY destination
ON CONFLICT (sender) DO UPDATE
    SET …
Run Code Online (Sandbox Code Playgroud)

postgresql performance update upsert postgresql-performance

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

不同 ID 上的 PostgreSQL 序列化失败

可序列化隔离模式可用于避免更新插入相等 id 时的竞争条件。因此,create table u(uid int primary key, name text);如果我们运行两个相似的事务 T1 和 T2:

begin isolation level serializable;
select * from u where uid = 1;
Run Code Online (Sandbox Code Playgroud)

然后继续 T1 和 T2:

insert into u (uid, name) values (1, 'A');
Run Code Online (Sandbox Code Playgroud)

commit;只有第一个成功,而另一个抛出序列化失败之后。

这是该模式的一个非常巧妙的功能,可以处理复杂交易中的独特密钥违规,而不是诉诸特定的“黑客” insert ... on conflict。然而,即使 uid 不同,例如uid = 2和uid = 3,事务 T1 和 T2仍然无法提交。

怎么可能?据说他们创建了不同的谓词 SIReadlocks 并select使用索引扫描。窍门在哪里?

postgresql isolation-level serialization upsert

5
推荐指数
1
解决办法
970
查看次数

是否可以在 PostgreSQL 中使用单个语句更新插入到自引用表中?

如果我有一张桌子A,就像这样:

A {
 id SERIAL
 title TEXT
 ...
 parentId INT references A.id via a foreign key constraint
}
Run Code Online (Sandbox Code Playgroud)

我正在从源表中提取数据 - A_SOURCE- 没有parentId列的地方。取而代之的是一parentTitle列。所以源表看起来像这样:

A_SOURCE {
  title TEXT
  parentTitle TEXT
}
Run Code Online (Sandbox Code Playgroud)

我开始编写一个 upsert 语句以A通过从表中选择插入到表中,A_SOURCE然后才意识到我无法轻松地parentTitle将源中的列解析parentId为目标中的 a。

由于我无法确定在处理子项时是否已插入父项,因此连接或子查询可能不会返回任何结果。

我的 upsert 语句看起来像这样:

with source as (
  select
   title
   parentTitle
  from A_SOURCE 
)

insert into A
select
title
... I don't think I can resolve to parentId here?
from source
on …
Run Code Online (Sandbox Code Playgroud)

postgresql upsert self-join

5
推荐指数
1
解决办法
292
查看次数

无法将“ON CONFLICT”与 postgres 可更新视图和部分索引一起使用

我有一个可更新的视图,指向具有部分索引的基础表。它看起来像这样

CREATE TABLE if not exists foo (
    a INT,
    b INT,
    x INT,
    y INT,
    z BOOLEAN,
    CONSTRAINT x_or_y CHECK (
      (z and x is not null and y is null)
      or 
      (not z and x is null and y is not null)
    )
);
CREATE UNIQUE INDEX ux ON foo (x, a) WHERE z=TRUE;
CREATE UNIQUE INDEX uy ON foo (y, a) WHERE z=FALSE;
CREATE OR REPLACE VIEW  foo_view AS 
    SELECT * FROM foo;
Run Code Online (Sandbox Code Playgroud)

也就是说,对于每一行,如果为 true,y则必须为 …

postgresql view upsert

5
推荐指数
1
解决办法
875
查看次数

这三个版本的 TSQL 片段有什么区别?

版本1

DECLARE @key INTEGER = 33, @val INTEGER = 44;
BEGIN TRANSACTION;
INSERT dbo.t([key], val)
  SELECT @key, @val
  WHERE NOT EXISTS
  (
    SELECT 1 FROM dbo.t WITH (UPDLOCK, SERIALIZABLE)
      WHERE [key] = @key
  );
IF @@ROWCOUNT = 0
BEGIN
  UPDATE dbo.t SET val = @val WHERE [key] = @key;
END
COMMIT TRANSACTION;
Run Code Online (Sandbox Code Playgroud)

版本2

DECLARE @key INTEGER = 33, @val INTEGER = 44;
BEGIN TRANSACTION;
INSERT dbo.t WITH (UPDLOCK, SERIALIZABLE) ([key], val)
  SELECT @key, @val
  WHERE NOT EXISTS
  (
    SELECT 1 …
Run Code Online (Sandbox Code Playgroud)

sql-server hints upsert design-pattern

5
推荐指数
1
解决办法
288
查看次数

如何在 SQL Server 中执行 UPSERT,返回预先更新的值?

所有语法都是有效的 PostgreSQL 作为 UPSERT 的示例,它返回字段的旧值和新值。比方说,我有一个表foo用(1,A)...(5,E)。

CREATE TEMP TABLE foo
AS
  SELECT id, chr(id+64)
  FROM generate_series(1,5) AS t(id);
CREATE UNIQUE INDEX ON foo(id);

 id | chr 
----+-----
 1  | A
 2  | B
 3  | C
 4  | D
 5  | E
(5 rows)
Run Code Online (Sandbox Code Playgroud)

现在,假设我想要 UPSERT 6 行。一些碰撞,一些新的行。

SELECT id, chr(id+74)
FROM generate_series(3,8) AS t(id);
 id | chr 
----+-----
  3 | M
  4 | N
  5 | O
  6 | P
  7 | Q
  8 | R …
Run Code Online (Sandbox Code Playgroud)

sql-server insert update upsert

4
推荐指数
1
解决办法
1505
查看次数