Reputation: 1171
I'm working with a postgresql 14 database where I have access to data through a view schema, and inserts and updates are performed with triggers. There is a unique constraint on the storage table, and I was wondering if there is a way to do upserts in this case?
This replicates the problem in a (much) smaller database:
schema:
CREATE SCHEMA storage;
-- unreachable storage schema
CREATE TABLE storage.data (
id SERIAL PRIMARY KEY,
a INTEGER,
b INTEGER,
c INTEGER,
CONSTRAINT pair UNIQUE(a, b)
);
-- reachable access schema
CREATE SCHEMA access;
CREATE VIEW access.data AS
SELECT id, a, b, c FROM storage.data;
-- data insertion trigger for the access view
CREATE FUNCTION data_insert()
RETURNS TRIGGER AS $data_insert$
BEGIN
INSERT INTO storage.data (a, b, c)
VALUES (NEW.a, NEW.b, NEW.c);
RETURN NEW;
END;
$data_insert$ LANGUAGE plpgsql;
CREATE TRIGGER data_insert_trigger
INSTEAD OF INSERT ON access.data
FOR EACH ROW EXECUTE PROCEDURE data_insert();
-- data update trigger for the access view
CREATE FUNCTION data_update()
RETURNS TRIGGER AS $data_update$
BEGIN
UPDATE storage.data SET
a = NEW.a,
b = NEW.b,
c = NEW.c
WHERE id = OLD.id;
RETURN NEW;
END;
$data_update$ LANGUAGE plpgsql;
CREATE TRIGGER data_update_trigger
INSTEAD OF UPDATE ON access.data
FOR EACH ROW EXECUTE PROCEDURE data_update();
What I would like to do is:
# INSERT INTO access.data(a,b,c) VALUES (1,2,3);
INSERT 0 1
# INSERT INTO access.data(a,b,c) VALUES (1,2,4)
ON CONFLICT ON CONSTRAINT pair
DO UPDATE SET c=EXCLUDED.c;
ERROR: constraint "pair" for table "data" does not exist
Is there any way to do an upsert query in this situation, or should I settle for doing a select followed by insert or update?
EDIT: I can not modify the schemas or add functions, I can only make queries to the access schema.
Upvotes: 0
Views: 101
Reputation: 1778
Have you tried something like this?
CREATE FUNCTION data_insert()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $data_insert$
BEGIN
INSERT INTO storage.data (a, b, c)
VALUES ( NEW.a, NEW.b, NEW.c )
ON CONFLICT DO UPDATE
a = EXCLUDED.a
, b = EXCLUDED.b
, c = EXCLUDED.c
;
RETURN NEW;
END;
$data_insert$;
Upvotes: 2