1

我是 Postgres 的新手,正在metrics_reaches使用 pgAdmin III 创建一个表 ( )。

在我的表中,我有一个带有 timezome类型列insertion_timestamp的时间戳。

我想创建一个UNIQUE约束,在其他字段中,只检查日期部分insertion_timestamp而不是时间。

有没有办法做到这一点?这是我的脚本目前的样子(见最后一个CONSTRAINT)。

-- Table: metrics_reaches

-- DROP TABLE metrics_reaches;

CREATE TABLE metrics_reaches
(
  organizations_id integer NOT NULL,
  applications_id integer NOT NULL,
  countries_id integer NOT NULL,
  platforms_id integer NOT NULL,
  ...
  insertion_timestamp timestamp with time zone NOT NULL,
  id serial NOT NULL,
  CONSTRAINT metrics_reaches_pkey PRIMARY KEY (id),
  CONSTRAINT metrics_reaches_applications_id_fkey FOREIGN KEY (applications_id)
      REFERENCES applications (id) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT metrics_reaches_countries_id_fkey FOREIGN KEY (countries_id)
      REFERENCES countries (id) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT metrics_reaches_organizations_id_fkey FOREIGN KEY (organizations_id)
      REFERENCES organizations (id) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT metrics_reaches_platforms_id_fkey FOREIGN KEY (platforms_id)
      REFERENCES platforms (id) MATCH SIMPLE
      ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT metrics_reaches_organizations_id_key UNIQUE (organizations_id, applications_id, countries_id, platforms_id, insertion_timestamp)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE metrics_reaches
  OWNER TO postgres;
4

2 回答 2

1

这确实是对弗兰克答案的评论,但是对于评论框来说太长了。

如果您偏执,则在处理日期转换时需要仔细观察当地时区:

bookings=> SET timezone='GMT';
SET
bookings=> SELECT now() at time zone 'GMT', (now() at time zone 'GMT')::date, now(), now()::date;
         timezone          |  timezone  |             now              |    now     
---------------------------+------------+------------------------------+------------
 2013-05-30 19:36:04.23684 | 2013-05-30 | 2013-05-30 19:36:04.23684+00 | 2013-05-30
(1 row)

bookings=> set timezone='GMT-7';
SET
bookings=> SELECT now() at time zone 'GMT', (now() at time zone 'GMT')::date, now(), now()::date;
          timezone          |  timezone  |              now              |    now     
----------------------------+------------+-------------------------------+------------
 2013-05-30 19:36:13.723558 | 2013-05-30 | 2013-05-31 02:36:13.723558+07 | 2013-05-31

现在,PG 足够聪明,知道这是一个问题,如果您尝试使用日期转换创建约束,那么您应该会看到如下内容:

ERROR:  functions in index expression must be marked IMMUTABLE

如果您在应用“时区”后尝试投射,那么它确实是不可变的,您可以有自己的约束。

当然,另一种选择是将强制转换包装在一个函数中并将该函数标记为不可变。但是,如果您要像那样对系统撒谎,请不要在一年后您的数据库表现异常时抱怨。

于 2013-05-30T19:45:55.577 回答
1

尝试 CAST():

CONSTRAINT metrics_reaches_organizations_id_key UNIQUE (
  organizations_id, 
  applications_id, 
  countries_id, 
  platforms_id, 
  CAST(insertion_timestamp AS date)
)
于 2013-05-30T17:54:25.473 回答