26
CREATE TABLE foo (
   dt     AS DATE NOT NULL,
   type   AS TEXT NOT NULL,
   CONSTRAINT unique_dt_type UNIQUE(dt,type) -- check constraint(?)
)

当仅存在特定条件时,试图思考正确的语法以创建唯一约束时,会出现脑残。

给定,type可以有值A-F,每个日期只能有一个A,但可以有多个B-F。好表的例子:

2010-01-02 | 'A'  -- only one
2010-01-02 | 'B'  -- can have multiple
2010-01-02 | 'B'
2010-01-02 | 'B'
2010-01-02 | 'C'  -- can have multiple
2013-01-02 | 'A'  -- only one
2010-01-02 | 'B'  -- can have multiple
2010-01-02 | 'B'
2013-01-02 | 'F'  -- can have multiple
2013-01-02 | 'F'

尝试阅读检查/唯一语法,但没有任何示例。 CHECK接近但仅将其限制在一个范围内,并未与UNIQUE场景结合使用。也试过搜索,但我的搜索技能要么达不到标准,要么没有任何类似的问题。

4

2 回答 2

37

PostgreSQL 可以通过其“部分索引”功能满足您的需求。实际上,这是通过在 create index 语句中添加 where 子句来实现的。

样本:

CREATE INDEX my_partial_ix ON my_sample_table (my_sample_field)
WHERE (my_sample_field = 'rows to index');

看看这里: http ://www.postgresql.org/docs/current/interactive/indexes-partial.html

特别注意该部分Example 11-3. Setting up a Partial Unique Index。它提供了一个与您声明的目标非常吻合的示例。

CREATE UNIQUE INDEX my_partial_ix ON my_sample_table (my_sample_field)
WHERE NOT (my_sample_field = 'duplicates ok');
于 2013-04-08T21:04:41.047 回答
1

使用触发器:

CREATE OR REPLACE FUNCTION "CheckConstraint"()
  RETURNS trigger AS
$BODY$declare
already_exists boolean; 
begin

if new.foo_type='A' then
select count(*) >0  from foo where foo_type='A' and dt=new.dt INTO already_exists;
if already_exists then 
raise exception 'date % already have an A', new.dt;
end if;
end if;

return new;
end;$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
于 2013-04-08T21:13:31.767 回答