I have the following table:
create table foobar ( account_id bigint not null, timestamp timestamp not null, balance_one numeric not null, balance_two numeric not null, primary key (timestamp, account_id), );
Currently, I’m inserting thousands of records into this table at once using the following statement:
insert into foobar(account_id, timestamp, balance_one, balance_two) VALUES (?, ?, ?, ?), (?, ?, ?, ?), ETC... on conflict DO NOTHING;
I want to add a constraint to the insert statement, stopping new records being inserted if new.balance_one == old.balance_one AND new.balance_two == old.balance_two
where old
= the most recent (timestamp) record where account_id = new.account_id.
How do I do this? Insert performance is also a concern.
Advertisement
Answer
Perhaps you should take a look at ON INSERT
triggers. You could create a function :
CREATE OR REPLACE FUNCTION check_insert() RETURNS TRIGGER AS $$ DECLARE rec foobar; BEGIN SELECT balance_one,balance_two FROM foobar INTO rec.balance_one,rec.balance_two WHERE account_id = NEW.account_id ORDER BY timestamp DESC LIMIT 1; IF rec.balance_one = NEW.balance_one AND rec.balance_two = NEW.balance_two THEN RETURN OLD; -- this will silently ignore the insert for the current record ELSE RETURN NEW; END IF; END; $$ LANGUAGE plpgsql;
… and attach it to your table
CREATE TRIGGER trg_check_balances BEFORE INSERT ON foobar FOR EACH ROW EXECUTE PROCEDURE check_insert();
Demo: db<>fiddle
Note: This approach will fail if you try to insert two records with the same acount_id
in the same transaction, as all records in the transaction will get the same timestamp
and your primary key will be violated.