From 9a3d2277cb30de55872683b26fa08aadba73a9e8 Mon Sep 17 00:00:00 2001 From: jbranchaud Date: Thu, 26 May 2022 15:44:53 -0600 Subject: [PATCH] Add Idempotent Inserts as a Postgres TIL --- README.md | 3 ++- postgres/idempotent-inserts.md | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 postgres/idempotent-inserts.md diff --git a/README.md b/README.md index 837623b..b26313f 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ pairing with smart people at Hashrocket. For a steady stream of TILs, [sign up for my newsletter](https://crafty-builder-6996.ck.page/e169c61186). -_1204 TILs and counting..._ +_1205 TILs and counting..._ --- @@ -609,6 +609,7 @@ _1204 TILs and counting..._ - [Get The Size Of An Index](postgres/get-the-size-of-an-index.md) - [Getting A Slice Of An Array](postgres/getting-a-slice-of-an-array.md) - [Group By The Result Of A Function Call](postgres/group-by-the-result-of-a-function-call.md) +- [Idempotent Inserts](postgres/idempotent-inserts.md) - [Include All Queries In The Log File](postgres/include-all-queries-in-the-log-file.md) - [Insert A Bunch Of Records With Generate Series](postgres/insert-a-bunch-of-records-with-generate-series.md) - [Insert Just The Defaults](postgres/insert-just-the-defaults.md) diff --git a/postgres/idempotent-inserts.md b/postgres/idempotent-inserts.md new file mode 100644 index 0000000..fdcbd49 --- /dev/null +++ b/postgres/idempotent-inserts.md @@ -0,0 +1,29 @@ +# Idempotent Inserts + +I'm writing a bunch of records from one table to another using +[`insert`](https://www.postgresql.org/docs/current/sql-insert.html). This is +part of a process to swap out a massive table with an identical version that +has a fraction of the records. + +I want to copy a subset of rows from the primary table to the replacement table +that meet certain criteria. This query should be re-runnable and idempotent. +That way I can run it, investage the replacement table, and then run it again +before swapping out the tables. This helps ensure I don't miss anything. + +Such an idempotent query can be written with the help of the `on conflict` +clause. + +```sql +insert into replacement_table +select * from original_table +where created_at > (now() - '3 months'::interval) +on conflict do nothing; +``` + +If I run that multiple times, it skips over any records that would otherwise +cause a conflict. The unique primary key column is usually what determines a +conflicting record. + +Without the `on conflict do nothing`, trying to run this `insert` multiple +times will fail on subsequent runs when it tries to re-insert rows with primary +keys it has already inserted.