私はupsertする必要があるテーブルがあります。行がすでに存在する場合は、行を更新して返したいと思います。行がまだ存在しない場合は、行を挿入して返す必要があります。私は以下のクエリを使用して、行を挿入時に取得しますが、更新時には取得しません。upsertから返された行が必要です
Table "main.message_account_seen"
Column | Type | Modifiers
----------------+--------------------------+-------------------------------------------------------------------
id | integer | not null default nextval('message_account_seen_id_seq'::regclass)
field_config_id | integer | not null
edit_stamp | timestamp with time zone | not null default now()
audit_stamp | timestamp with time zone |
message_id | integer | not null
account_id | integer |
ここにSQLがあります。
with upsert as (
update message_account_seen set (message_id, account_id, field_config_id) = (1, 60, 980)
where message_id = 1 and account_id = 60 and field_config_id = 980 returning *
)
insert into message_account_seen (message_id, account_id, field_config_id)
select 1, 60, 980
where not exists (select message_id, account_id, field_config_id from upsert) returning *;
私はpostgres関数を実行できません。通常のSQLクエリで処理する必要があります。また、テーブルの行の一意性に関する制約はありません。それ以外の場合はon conflict
を使用します。しかし、私はこの質問を破棄し、必要に応じて他のものと一緒に行くつもりです。
これらは、クエリを実行してから再度実行したときの結果です。挿入または最初の実行で、行が返されることがわかります。しかし、その後のクエリの実行では、返された0行が返されます。私は、edit_stampが時間の経過と共に増加するため、それが機能していることを知っています。それはいいことだ。
# with upsert as (
update message_account_seen set (message_id, account_id, field_config_id) = (1, 60, 980)
where message_id = 1 and account_id = 60 and field_config_id = 980 returning *
)
insert into message_account_seen (message_id, account_id, field_config_id)
select 1, 60, 980
where not exists (select message_id, account_id, field_config_id from upsert) returning *;
id | field_config_id | edit_stamp | audit_stamp | message_id | account_id
--+-----------------+--------------------------------+-------------+------------+------------
38 | 980 | 09/27/2016 11:43:22.153908 MDT | | 1 | 60
(1 row)
INSERT 0 1
# with upsert as (
update message_account_seen set (message_id, account_id, field_config_id) = (1, 60, 980)
where message_id = 1 and account_id = 60 and field_config_id = 980 returning *
)
insert into message_account_seen (message_id, account_id, field_config_id)
select 1, 60, 980
where not exists (select message_id, account_id, field_config_id from upsert) returning *;
id | field_config_id | edit_stamp | audit_stamp | message_id | account_id
----+-----------------+------------+-------------+------------+------------
(0 rows)
INSERT 0 0
どのバージョンのpostgresを使用していますか?また、 '(message_id、account_id、field_config_id)の組み合わせは一意で正しいと思われます。 – redneb
バージョンは9.5.3で、組み合わせは一意ですが、固有の制約はなく、現時点では追加できません。それは物事をより簡単にするでしょう。 – thepriebe
ユニークなインデックスがあれば、簡単に考えることができます。また、更新のケースをどのようにしたいかは不明です。現在、コード内に3列に既に値が割り当てられているので、これは効果がありません。 – redneb