我想将股票价格添加到表格中-但仅当买入或卖出与上一个记录相比有所变化时。 因此,UNIQUE不能真正起作用,因为它不允许同一表中的价格组合多次出现。 我可以考虑在postgres之外解决问题的方法(在实际插入行之前),但我想知道是否有办法设置价格表为我处理此问题。
CREATE TABLE stock(
id SMALLSERIAL PRIMARY KEY,
name VARCHAR(3) UNIQUE NOT NULL
);
CREATE TABLE prices(
id SMALLSERIAL PRIMARY KEY,
created_at TIMESTAMPTZ DEFAULT current_timestamp,
stock_id INTEGER NOT NULL,
buy NUMERIC(15, 6) NOT NULL,
sell NUMERIC(15, 6) NOT NULL,
FOREIGN KEY (stock_id) REFERENCES stock(id),
UNIQUE(stock_id, buy, sell)
);
INSERT INTO stock(name) VALUES('abc');
INSERT INTO prices (stock_id, buy, sell) VALUES (1, 1.5, 1.4)
ON CONFLICT (stock_id, buy, sell) DO NOTHING;
INSERT INTO prices (stock_id, buy, sell) VALUES (1, 1.5, 1.4)
ON CONFLICT (stock_id, buy, sell) DO NOTHING; -- this record should not be added to the table
INSERT INTO prices (stock_id, buy, sell) VALUES (1, 1.6, 1.5)
ON CONFLICT (stock_id, buy, sell) DO NOTHING;
INSERT INTO prices (stock_id, buy, sell) VALUES (1, 1.5, 1.4)
ON CONFLICT (stock_id, buy, sell) DO NOTHING; -- this one should be added to the table
所以在我的示例中,我希望表中有3行而不是2行-应该阻止价格的第二次插入,而不是第四次。
答案 0 :(得分:2)
正如您所写,唯一约束不是解决该问题的合适方法。在这种情况下,触发是一种自然的方法,例如:
create or replace function before_insert_on_prices()
returns trigger language plpgsql as $$
declare
last_rec record;
begin
select buy, sell
from prices
where stock_id = new.stock_id
order by created_at desc
limit 1
into last_rec;
if found and last_rec = (new.buy, new.sell) then
return null;
end if;
return new;
end $$;
create trigger before_insert_on_prices
before insert on prices
for each row execute procedure before_insert_on_prices();
请注意,由于在单个事务中插入的多行在created_at
中具有相同的时间戳,因此只有在将新行插入到单独的事务中时,触发器才能正常工作。但是,我认为这种行为是合乎逻辑的并且可以接受的。