如何在Postgresql中创建一个列常量

时间:2014-08-11 07:50:16

标签: postgresql constraints constants

create table test(
  t_id SERIAL primary key,
  t_date CONSTANT date default CURRENT_DATE
);
ERROR:  syntax error at or near "date"
LINE 3:   t_date CONSTANT date default CURRENT_DATE
                      ^
********** Error **********

ERROR: syntax error at or near "date"
SQL state: 42601

2 个答案:

答案 0 :(得分:2)

对于默认值,您可以使用函数

CREATE TABLE test(
    t_id SERIAL primary key,
    t_date date DEFAULT now()
);

关于constant,我从未使用过,甚至其他SQL(!),只在PL / SQL上下文中...

如果您需要“无更新”约束,则可以使用触发器。例如:

CREATE FUNCTION correct_update() RETURNS trigger AS $$ 
    BEGIN
    NEW.t_date=OLD.t_date;
    RETURN NEW; 
    END
$$ LANGUAGE plpgsql;

CREATE TRIGGER no_date_update
  BEFORE BEFORE UPDATE ON test
  FOR EACH ROW
  WHEN (OLD.t_date IS DISTINCT FROM NEW.t_date)
  EXECUTE PROCEDURE correct_update();

对于完整的控件,你还需要触发INSERT事件,(并且不再需要默认值,因为插入触发器会这样做):

create table test(
    t_id SERIAL primary key,
    t_date date  -- a default will be redundant
);

CREATE FUNCTION correct_date() RETURNS trigger AS $$ 
    BEGIN
      IF TG_OP = 'INSERT' THEN
         NEW.t_date=now();         -- default value
      ELSIF TG_OP = 'UPDATE' THEN  -- optional AND OLD.t_date != NEW.t_date
         NEW.t_date=OLD.t_date;    -- "constant" behaviour
      END IF;
      RETURN NEW;
    END
$$ LANGUAGE plpgsql;

CREATE TRIGGER constant_date
  BEFORE INSERT OR UPDATE ON test
  FOR EACH ROW
  EXECUTE PROCEDURE correct_date();

OLD.t_date != NEW.t_date比较是可选的,因为它不会影响性能......但是使用它是一种很好的做法。另一种方法是通过WHEN检查触发器,但只有更新触发器可以使用OLD ...所以,同一correct_date()函数的最佳创建触发器(没有旧的) /新比较):

CREATE TRIGGER constant_date_ins
  BEFORE INSERT  ON test
  FOR EACH ROW
  EXECUTE PROCEDURE correct_date();
CREATE TRIGGER constant_date_upd
  BEFORE UPDATE ON test
  FOR EACH ROW
  WHEN (OLD.t_date IS DISTINCT FROM NEW.t_date)
  EXECUTE PROCEDURE correct_date();

在场景中进行语境化

正如上面在问题中所评论的那样,缺乏语境化,例如。解释“为什么你认为这应该有效以及它应该做什么”。

场景-1:db-master需要阻止粗心的程序员

我们可以想象一个像CakePHP这样的框架,其中包含一个“created”字段和一个数据库master,它希望这个字段具有“常量行为”,防止粗心的程序员影响这个“预期的约束”。

在anwser中使用了这种情况。

场景-2:项目决策是按错误警告

这是@IgorRomanchenko的建议......

 ... now here as a Wiki, you can EDIT and add new solution/example ...

答案 1 :(得分:-1)

您需要check约束

create table test(
  t_id SERIAL primary key,
  t_date date default CURRENT_DATE check(t_date = current_date)
);

insert into test(t_date) values (default);
INSERT 0 1

insert into test(t_date) values ('2014-01-01');
ERROR:  new row for relation "test" violates check constraint "test_t_date_check"
DETAIL:  Failing row contains (2, 2014-01-01).

或者可能是foreign key约束,它允许多个可能的值,并且可以在不更改表格架构的情况下进行更新

create table date_constraint (
    date_constraint date primary key
);
insert into date_constraint (date_constraint) values (current_date);

create table test(
  t_id SERIAL primary key,
  t_date date
    default CURRENT_DATE
    references date_constraint(date_constraint)
);

insert into test(t_date) values (default);
INSERT 0 1

insert into test(t_date) values ('2014-01-01');
ERROR:  insert or update on table "test" violates foreign key constraint "test_t_date_fkey"
DETAIL:  Key (t_date)=(2014-01-01) is not present in table "date_constraint".

http://www.postgresql.org/docs/current/static/ddl-constraints.html