Как применить «расширенное» ограничение на основе запросов? - PullRequest
3 голосов
/ 08 июня 2011

Я не могу найти способ применить расширенное ограничение на основе запросов.

Например, с помощью следующей фиктивной схемы, как я могу обеспечить, чтобы общий процент ежедневных действий Боба не превышал 100%?

Я уже изучил ограничения триггера , но я не думаю, что они собираются делать то, что я хочу (отменить INSERT / UPDATE, если удовлетворены некоторые критерии).

Спасибо за чтение моего вопроса и любую помощь, которую вы можете предложить.

create table employee (
    id serial PRIMARY KEY,
    name varchar(100) NOT NULL
);

create table work_day (
    employee_id integer references employee(id) NOT NULL,
    percentage integer NOT NULL CHECK (percentage > 0 and percentage <= 100),
    activity varchar(100) NOT NULL
);

INSERT INTO employee (name) VALUES ('bob');

-- Bob spends 50% of the day slacking, 20% eating and 30% working (total = 100%)
INSERT INTO work_day (employee_id, percentage, activity) VALUES (1, 50, 'slacking'); 
INSERT INTO work_day (employee_id, percentage, activity) VALUES (1, 20, 'eating');
INSERT INTO work_day (employee_id, percentage, activity) VALUES (1, 30, 'working');

-- This should be invalid!!! 100% of Bob's time has already been allocated
INSERT INTO work_day (employee_id, percentage, activity) VALUES (1, 10, 'invalid');

Ответы [ 2 ]

4 голосов
/ 08 июня 2011

Я проверил этот код, и он работает:

CREATE OR REPLACE FUNCTION check_work_day_percentage() RETURNS trigger AS $$
    BEGIN
        IF coalesce((select sum(percentage) 
                    from work_day
                    where employee_id = NEW.employee_id
                    and activity != NEW.activity), 0) 
                + coalesce(NEW.percentage, 0) > 100 THEN
            RAISE EXCEPTION 'Employee % exceeds 100 percent', NEW.employee_id;
        END IF;
        RETURN NEW;
    END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER work_day_trigger 
BEFORE INSERT OR UPDATE ON work_day
FOR EACH ROW EXECUTE PROCEDURE check_work_day_percentage();

К вашему сведению, ограничение таблицы не сделает этого: согласно документам ,

В настоящее время выражения CHECK не могут не содержат подзапросов и не относятся к переменные, кроме столбцов текущий ряд.

0 голосов
/ 08 июня 2011

Триггер ограничения на основе pl / pgsql - это то, что вам нужно. sum () вещь, и проверьте, находится ли она в пределах определенных границ. Если нет, вызовет исключение , и оператор будет отменен.

В качестве альтернативы, используйте обычный триггер для сохранения / обновления общей активности в таблице сотрудников и наложения ограничений на последнюю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...