在PostgreSQL中使用触发器的非null约束

时间:2016-06-22 09:29:52

标签: postgresql triggers

我有一个包含两个可选列的表。 在表中插入行时,两列中的一列不应为空。

我找到了MySQL的这个解决方案:

CREATE TABLE foo (
  FieldA INT,
  FieldB INT
);

DELIMITER //
CREATE TRIGGER InsertFieldABNotNull BEFORE INSERT ON foo
FOR EACH ROW BEGIN
  IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN
    SIGNAL SQLSTATE '45000'
    SET MESSAGE_TEXT = '\'FieldA\' and \'FieldB\' cannot both be null';
  END IF;
END//
CREATE TRIGGER UpdateFieldABNotNull BEFORE UPDATE ON foo
FOR EACH ROW BEGIN
  IF (NEW.FieldA IS NULL AND NEW.FieldB IS NULL) THEN
    SIGNAL SQLSTATE '45000'
    SET MESSAGE_TEXT = '\'FieldA\' and \'FieldB\' cannot both be null';
  END IF;
END//
DELIMITER ;

INSERT INTO foo (FieldA, FieldB) VALUES (NULL, 10); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (10, NULL); -- OK
INSERT INTO foo (FieldA, FieldB) VALUES (NULL, NULL); -- gives error
UPDATE foo SET FieldA = NULL; -- gives error

如何为PostgreSQL翻译它?

1 个答案:

答案 0 :(得分:1)

您可以简单地使用表约束:

CREATE TABLE foo (
  FieldA INT,
  FieldB INT,
  CHECK (NOT (FieldA IS NULL AND FieldB IS NULL)));

通过这种方式,您无法插入或修改两个值为NULL的元组。

teststar=# INSERT INTO foo (FieldA, FieldB) VALUES (NULL, 10);
INSERT 0 1
teststar=# INSERT INTO foo (FieldA, FieldB) VALUES (10, NULL);
INSERT 0 1
teststar=# INSERT INTO foo (FieldA, FieldB) VALUES (NULL, NULL);
ERROR:  new row for relation "foo" violates check constraint "foo_check"
DETAIL:  Failing row contains (null, null).
teststar=# UPDATE foo SET FieldA = NULL; 
ERROR:  new row for relation "foo" violates check constraint "foo_check"
DETAIL:  Failing row contains (null, null).
teststar=#