在下面的代码中,这很有效,我想摆脱“mday”'并且在ON CONFLICT / ON CONSTRAINT中仅使用时间戳的日期部分但尚未找到解决方法。 HAd将我的希望寄托在一个排除约束EXCLUDE(fid WITH =,date_trunc(' day',ts)WITH =)但是这不起作用。
BEGIN;
DROP TABLE IF EXISTS flow;
CREATE TABLE flow (
fid UUid NOT NULL,
fvol REAL[],
ts TIMESTAMP WITH TIME ZONE NOT NULL,
mday DATE NOT NULL,
UNIQUE (fid, mday)
);
COMMIT;
INSERT INTO flow (fid, fvol, ts, mday)
VALUES (
'b55e9fbe-daea-4142-8843-5e5cf757b778', '{7}',
'2019-06-26T19:12:00Z01', '2019-06-26'
)
ON CONFLICT (fid, mday)
DO UPDATE
SET fvol = flow.fvol || EXCLUDED.fvol, ts = EXCLUDED.ts;
答案 0 :(得分:1)
您无法在表达式上创建唯一约束(例如unique (fid, (ts::date))
,也无法使用它创建唯一索引(这对于ON CONFLICT
就足够了。)
唯一索引将被拒绝:
错误:索引表达式中的函数必须标记为IMMUTABLE
这是因为(对于Postgres的一些内部原因),将时间戳转换为DATE
并不是明确的。但是你可以通过创建一个不可变的函数来解决这个问题。
create function my_to_date(p_ts timestamp with time zone)
returns date
as $$
select p_ts::date;
$$
language sql
immutable; --<< this makes the function usable in an index
完成后,您可以在表达式上创建唯一索引:
create unique index ix_unique_day on flow (fid, my_to_date(ts));
请注意,您无法使用该索引创建唯一的约束,但出于您的目的,这无关紧要。
唯一索引的表达式可用于ON CONFLICT
部分:
INSERT INTO flow
(fid, fvol, ts)
VALUES
('b55e9fbe-daea-4142-8843-5e5cf757b778', '{7}', '2019-06-26T19:12:00Z01')
ON CONFLICT (fid, my_to_date(ts))
DO UPDATE
SET fvol = flow.fvol || EXCLUDED.fvol, ts = EXCLUDED.ts;