相关疑难解决方法(0)

如何在PostgreSQL中UPSERT(MERGE,INSERT ...在DUPLICATE UPDATE上)?

这里一个非常常见的问题是如何进行upsert,这是MySQL调用的INSERT ... ON DUPLICATE UPDATE,标准支持作为MERGE操作的一部分.

鉴于PostgreSQL不直接支持它(在第9.5页之前),你是如何做到这一点的?考虑以下:

CREATE TABLE testtable (
    id integer PRIMARY KEY,
    somedata text NOT NULL
);

INSERT INTO testtable (id, somedata) VALUES
(1, 'fred'),
(2, 'bob');
Run Code Online (Sandbox Code Playgroud)

现在,假设你想"UPSERT"的元组(2, 'Joe'),(3, 'Alan'),因此新表的内容是:

(1, 'fred'),
(2, 'Joe'),    -- Changed value of existing tuple
(3, 'Alan')    -- Added new tuple
Run Code Online (Sandbox Code Playgroud)

这是人们在讨论时所谈论的内容upsert.至关重要的是,任何方法在同一个表上存在多个事务时都必须是安全的 - 通过使用显式锁定,或以其他方式抵御由此产生的竞争条件.

关于PostgreSQL中的重复更新,Insert上广泛讨论了这个主题,但这是关于MySQL语法的替代品,随着时间的推移,它已经成长为一些无关的细节.我正在研究明确的答案.

这些技术对于"插入如果不存在,否则什么都不做"也很有用,即"插入...复制键忽略".

postgresql upsert insert-update sql-merge

246
推荐指数
5
解决办法
18万
查看次数

如何在PostgreSQL中使用RETURNING和ON CONFLICT?

我在PostgreSQL 9.5中有以下UPSERT:

INSERT INTO chats ("user", "contact", "name") 
           VALUES ($1, $2, $3), 
                  ($2, $1, NULL) 
ON CONFLICT("user", "contact") DO NOTHING
RETURNING id;
Run Code Online (Sandbox Code Playgroud)

如果没有冲突,则返回如下内容:

----------
    | id |
----------
  1 | 50 |
----------
  2 | 51 |
----------
Run Code Online (Sandbox Code Playgroud)

但如果存在冲突,则不会返回任何行:

----------
    | id |
----------
Run Code Online (Sandbox Code Playgroud)

id如果没有冲突,我想返回新列,或者返回id冲突列的现有列.
可以这样做吗?如果是这样,怎么样?

sql postgresql upsert sql-returning

127
推荐指数
7
解决办法
4万
查看次数

Postgresql Python:忽略重复键异常

我按以下方式使用psycopg2插入项目:

cursor = connection.cursor()
for item in items:
    try:
        cursor.execute(
            "INSERT INTO items (name, description) VALUES (%s, %s)  RETURNING id",
            (item[0], item[1])
        )
        id = cursor.fetchone[0]
        if id is not None:
            cursor.execute(
                "INSERT INTO item_tags (item, tag) VALUES (%s, %s)  RETURNING id",
                (id, 'some_tag')
            )    
    except psycopg2.Error:
        connection.rollback()
        print("PostgreSQL Error: " + e.diag.message_primary)
        continue
    print(item[0])
connection.commit()
Run Code Online (Sandbox Code Playgroud)

显然,当一个项目已经在数据库中时,duplicate key exception就会抛出该项目.有没有办法忽略这个例外?抛出异常时是否会中止整个事务?如果是,那么重写查询的最佳选择是什么,可能使用批量插入?

python sql postgresql psycopg2

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