假设我有一个带有列的复合pk的简单模式。 e.g
pk1:string
pk2:int
日期:时间戳
我正在从其他地方读取大约50个批次的数据,并希望存储它。我从中拉出的数据源是一个滑动窗口,所以我将从我已经插入的数据源接收数据,所以我不能盲目插入,否则我得到pk约束违规。
我想以合理的方式将新项目作为批处理插入,但也知道我为实际记录目的实际插入了多少新项目。
答案 0 :(得分:1)
执行插入
对于postgresql版本9.5+,可以使用以下内容:
insert ... on conflict do nothing
示例:
INSERT INTO users (id, user_name, email)
VALUES (1, 'hal', 'hal@hal.hal')
ON CONFLICT DO NOTHING
对于最近的早期版本(自9+以来,我认为),可以从原始值和&amp ;;创建CTE。然后从那里插入:
WITH batch (id, user_name, email) AS (
VALUES
(1, 'hal', 'hal@hal.hal'),
(2, 'sal', 'sal@sal.sal')
)
INSERT INTO users (id, user_name, email) (
SELECT id, user_name, email
FROM batch
WHERE batch.id NOT IN (SELECT id FROM users)
)
或者,不是使用CTE,而是在处理每个批处理后截断的临时表中暂存值。
另请注意,如果使用CTE方法,可能需要显式地将字符串转换为适当的数据类型。
第三种选择是使用存储过程实现这一点。触发。这比其他两个更复杂,但可以使用早期版本的postgresql。
<强>登录强>
这两种方法都应报告插入的行数,但日志记录必须由数据库客户端执行。
e.g。在Python
中,库psycopg2
用于与postgresql交互,而psycopg2游标对象具有属性rowcount
。我敢肯定,其他语言/框架编写的其他设计良好的库将以某种方式实现相同的功能。记录插入的行数必须从与数据库交互的程序部分完成。
但是,如果在同一个数据库中需要插入多少行的日志,那么upsert&amp;可以通过单个触发器+存储过程执行日志记录。
最后,由于这是upsert
的一个特例,通过在堆栈溢出或其他站点上搜索postgresql upsert
可以找到更多信息。我从postgresql wiki中发现了以下内容:
https://wiki.postgresql.org/wiki/UPSERT#PostgreSQL_.28today.29