postgreSQL 中的重复约束使用(使用 GIST 和/或 EXCLUDE)
Duplication constraint in postgreSQL using (using GIST and or EXCLUDE)
如何使用以下规则编写约束(table 级别唯一,使用 GIST 和/或 EXCLUDE )来执行重复记录验证:
- 输入的from_date和to_date值不应相等或不在范围内,并且
- Employee_id应该不相等,和
验证后,错误消息应该是 return 说 'Duplicate Entry'。
这是在 postgreSQL.
注意:我是 postgreSQL 的新手(曾在 MS SQL 服务器和 MySQL 工作)。
提前致谢。
正如@Laurenz Albe 所说,使用约束听起来不可能。您可以实施 trigger function
或 rule
代替:
触发函数:
CREATE OR REPLACE FUNCTION test_insert_table()
RETURNS trigger LANGUAGE plpgsql IMMUTABLE AS
$$
BEGIN
IF NEW.status = 'pending'
AND EXISTS
( SELECT 1
FROM your_table
WHERE Employee_id = NEW.Employee_id
AND range @> daterange(NEW.from_date, NEW.to_date)
)
THEN
RAISE EXCEPTION 'Duplicate Entry' ;
RETURN NULL ;
ELSE
RETURN NEW ;
END IF ;
END ;
$$
CREATE OR REPLACE TRIGGER test_insert_table
BEFORE INSERT ON your_table
FOR EACH ROW EXECUTE FUNCTION test_insert_table() ;
规则:
CREATE OR REPLACE RULE test_insert AS
ON INSERT TO your_table
WHERE NEW.status = 'pending'
AND EXISTS
( SELECT 1
FROM your_table
WHERE Employee_id = NEW.Employee_id
AND range @> daterange(NEW.from_date, NEW.to_date)
)
DO INSTEAD NOTHING ;
如何使用以下规则编写约束(table 级别唯一,使用 GIST 和/或 EXCLUDE )来执行重复记录验证:
- 输入的from_date和to_date值不应相等或不在范围内,并且
- Employee_id应该不相等,和
验证后,错误消息应该是 return 说 'Duplicate Entry'。 这是在 postgreSQL.
注意:我是 postgreSQL 的新手(曾在 MS SQL 服务器和 MySQL 工作)。
提前致谢。
正如@Laurenz Albe 所说,使用约束听起来不可能。您可以实施 trigger function
或 rule
代替:
触发函数:
CREATE OR REPLACE FUNCTION test_insert_table()
RETURNS trigger LANGUAGE plpgsql IMMUTABLE AS
$$
BEGIN
IF NEW.status = 'pending'
AND EXISTS
( SELECT 1
FROM your_table
WHERE Employee_id = NEW.Employee_id
AND range @> daterange(NEW.from_date, NEW.to_date)
)
THEN
RAISE EXCEPTION 'Duplicate Entry' ;
RETURN NULL ;
ELSE
RETURN NEW ;
END IF ;
END ;
$$
CREATE OR REPLACE TRIGGER test_insert_table
BEFORE INSERT ON your_table
FOR EACH ROW EXECUTE FUNCTION test_insert_table() ;
规则:
CREATE OR REPLACE RULE test_insert AS
ON INSERT TO your_table
WHERE NEW.status = 'pending'
AND EXISTS
( SELECT 1
FROM your_table
WHERE Employee_id = NEW.Employee_id
AND range @> daterange(NEW.from_date, NEW.to_date)
)
DO INSTEAD NOTHING ;