这里一个非常常见的问题是如何进行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语法的替代品,随着时间的推移,它已经成长为一些无关的细节.我正在研究明确的答案.
这些技术对于"插入如果不存在,否则什么都不做"也很有用,即"插入...复制键忽略".
有几种方法:first_or_create_by
,find_or_create_by
等,其原理是:
显然,这些方法的并发调用可能使两个线程都找不到他们想要的东西,并且在步骤3中,一个人意外地失败.
似乎更好的解决方案是,
create_or_find
那是:
那么在什么情况下我想使用Rails内置的东西而不是我自己的东西(看似更可靠)create_or_find
?