在下面的代码中,效果很好,我想去掉“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;
最佳答案
您不能在表达式上创建唯一约束(例如 unique (fid, (ts::date))
并且您也不能用它创建唯一索引(这将是对于 ON CONFLICT
来说足够了。
唯一索引将被拒绝:
ERROR: functions in index expression must be marked 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;
关于postgresql - 冲突时(UUid,date_trunc ('day',时间戳)),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48397257/