在postgresql中触发日期

时间:2018-01-31 07:45:45

标签: postgresql triggers

我正在阅读很多文章如何创建触发器,但我真的不知道如何根据日期创建触发器。

我想添加一个触发器: 1.如果在特定日期的分钟总和高于50,则在添加或更新之前进行检查。

所以在示例实体中:

CREATE TABLE employees(
   id int serial primary key,
   minutes int NOT NULL,
   date date NOT NULL
);

这是db中的典型数据:

(1, 40, '2018-01-1')
(2, 30, '2018-01-2')
(3, 20, '2018-01-3')
(4, 10, '2018-01-4')

现在如果我添加:

(6, 20, '2018-01-1')
(7, 40, '2018-01-2')
(8, 20, '2018-01-3')
(9, 20, '2018-01-4')

最终结果将是:

(1, 40, '2018-01-1')
(2, 30, '2018-01-2')
(3, 20, '2018-01-3')
(4, 10, '2018-01-4')
(8, 20, '2018-01-3')
(9, 20, '2018-01-4')

id为6和7被省略(未添加,因为它们高于50)

我真的很感激帮助:)

更新:在@Laurenz Albe的帮助下,我创建了函数和触发器,如下所示:

        CREATE FUNCTION func_check_minutes() RETURNS trigger AS
        $$
        BEGIN
        IF (SELECT sum(minutes) + NEW.minutes FROM employees WHERE date = NEW.date) > 50
        THEN RETURN NULL;
        END IF;
        END;
        $$
        LANGUAGE 'plpgsql';

        CREATE TRIGGER tr_check_minutes
        BEFORE INSERT ON employees
        FOR EACH ROW
        EXECUTE PROCEDURE func_check_minutes();

但是这个解决方案没有明确的原因就失败了。

2 个答案:

答案 0 :(得分:1)

这种触发器的核心部分是:

IF (SELECT sum(minutes) + NEW.minutes
    FROM employees
    WHERE date = NEW.date) > 50
THEN
   <throw an error or return NULL>
END IF;

但是你应该知道存在可能导致违反条件的竞争条件:

如果来自两个插入的触发器同时运行,则每个插件都不会看到另一个事务的影响,并且两者都可以报告成功,而两个事务提交后的最终结果可能超出限制。

解决这个问题的唯一方法就是使用SERIALIZABLE次交易。

答案 1 :(得分:1)

由于你没有提到失败的原因,我假设没有任何东西被写入表格。您必须在RETURN NEW

之后添加END IF

我更新了触发器

CREATE FUNCTION func_check_minutes() RETURNS trigger AS
        $$
        BEGIN
        IF (SELECT sum(minutes) + NEW.minutes FROM employees WHERE date = NEW.date) > 50
        THEN RETURN NULL;
        END IF;

        RETURN NEW;

        END;
        $$
        LANGUAGE 'plpgsql';

        CREATE TRIGGER tr_check_minutes
        BEFORE INSERT ON employees
        FOR EACH ROW
        EXECUTE PROCEDURE func_check_minutes();