INSERT INTO A
SELECT * FROM B WHERE timestamp > (SELECT max(timestamp) FROM A);
或者,写不同的话:
WITH selection AS
(SELECT * FROM B WHERE timestamp > (SELECT max(timestamp) FROM A))
INSERT INTO A SELECT * FROM selection;
如果这些查询同时运行多次,是否有可能导致A中的行重复?
Postgres如何处理这些查询?是一个还是多个?
如果它是多个查询(找到max(timestamp)[1],选择[2]然后插入[3]),我可以想象这将导致重复的行。
如果正确,将其包装在BEGIN / END(事务)中会有所帮助吗?
答案 0 :(得分:2)
是的,这可能导致重复的值。
从语句开始的时间点开始,单个语句就可以看到所有表中数据的一致视图。
将单个语句包装到事务中并不会改变(无论所涉及的子查询数量如何,单个语句始终作为原子语句执行)。
该语句将永远不会看到其他事务中未提交的数据(这是为什么您最终可能会有重复值的根本原因)。
唯一的避免重复值的安全方法是在该列上创建唯一约束(或索引)。在这种情况下,如果该值已经存在,则INSERT将导致错误。
如果要避免该错误,请使用insert ... on conflict
答案 1 :(得分:0)
这取决于数据库中设置的隔离级别。 来自postgres documentation
默认情况下,此设置为可重复读取,这意味着每个查询将基于事务首次尝试读取数据的时间获取输出。如果在任何一个写入之前读取了2个查询,那么您将在这些表中获得重复的数据。
如果要避免重复输入,则有一些选择。