以下是否有效?
WITH upd AS (
UPDATE main_stat t
SET counter = s.counter
FROM tmp_stat s
WHERE t.date = s.date
AND t.site_id = s.site_id
AND t.ip = s.ip
AND t.block_id = s.block_id
RETURNING s.date, s.site_id, s.ip, s.block_id, s.counter
)
INSERT INTO main_stat
SELECT s.mydate, s.site_id, s.ip, s.block_id, s.counter
FROM tmp_stat s
LEFT JOIN upd ON (upd.date = s.date and upd.site_id = s.site_id and upd.ip = s.ip and upd.block_id = s.block_id)
WHERE upd.date IS NULL
;
更新:
看起来这仅适用于9.1或更新版本。
仅仅使用某人的建议WHERE (t.date, t.site_id, t.ip, t.block_id) = (s.date, s.site_id, s.ip, s.block_id)
似乎会带来更好的性能。
WITH upd AS (
UPDATE main_stat t
SET counter = s.counter
FROM tmp_stat s
WHERE (t.date, t.site_id, t.ip, t.block_id) = (s.date, s.site_id, s.ip, s.block_id)
RETURNING s.date, s.site_id, s.ip, s.block_id
)
INSERT INTO main_stat
SELECT s.date, s.site_id, s.ip, s.block_id, s.counter
FROM tmp_stat s
LEFT JOIN upd
ON (upd.date = s.date
AND upd.site_id = s.site_id
AND upd.ip = s.ip
AND upd.block_id = s.block_id)
WHERE upd.date IS NULL
;
这里发生了什么是我们正在使用CTE做更新与CTE返回更新行的标识列。
INSERT然后使用更新的行信息来过滤tmp_stat以仅插入新的记录。
Dimitri Fontaine在此blog条目中涵盖了一些并发警告。
关于CTEs的更多信息可以在Postgresql documentation中找到。
在这里看到:http://stackoverflow.com/q/1109061/330315 – 2013-03-20 07:39:45
而看到文档:http://docs.oracle.com/cd/B28359_01/server。 111/b28286/statements_9016.htm#i2081218 – 2013-03-20 08:17:37
a_horse_with_no_name我希望看到一个从表到多的插入/更新的例子。我不想循环500K行,我希望有更快的方法来做到这一点。 – varan 2013-03-20 14:47:46