postgresql - 冲突时(UUid,date_trunc ('day',时间戳))

标签 postgresql

在下面的代码中,效果很好,我想去掉“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/

相关文章:

postgresql - Postgres : Match comma separated tags column value with pre-defined array

postgresql - 如何以智能方式拆分字符串?

sql - 为每种类型生成唯一的序列 ID

java - Tomcat容器中c3p0依赖放在哪里

ruby-on-rails - 如何加速 Rails 5 上的 View 渲染?

python - 跨线程共享 Django 事务

postgresql - 使用 activerecord + postgres 获取 hstore 列的平均值

postgresql - Postgres - 将数据从一个表批量传输到另一个表

postgresql - ubuntu 中 postgresql 的 pg_log 目录?

postgresql - 如何在 PgAdmin、sql 中使用顺序和组更改行顺序?