согласованность процедуры запуска (до запуска строки) Postgresql - PullRequest
2 голосов
/ 06 апреля 2010

Использование Postgresql.

Я пытаюсь использовать процедуру TRIGGER для проверки целостности INSERT.

Вопрос в том, ......

ли "ДО"INSERT FOR EACH ROW "можете убедиться, что каждая строка для вставки" проверена "и" вставлена ​​"одна за другой?мне нужна дополнительная блокировка таблицы, чтобы выжить после одновременной вставки?

проверка на новую строку1 -> вставка строки1 -> проверка на новую строку 2 -> вставка строки2

--
--

-- unexpired product name is unique.
CREATE TABLE product (
  "name"    VARCHAR(100) NOT NULL,
  "expired" BOOLEAN      NOT NULL
);

CREATE OR REPLACE FUNCTION check_consistency() RETURNS TRIGGER AS $$
  BEGIN
    IF EXISTS (SELECT * FROM product WHERE name=NEW.name AND expired='false') THEN
      RAISE EXCEPTION 'duplicated!!!';              
    END IF;
    RETURN NEW;
  END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_check_consistency
BEFORE INSERT ON product
  FOR EACH ROW EXECUTE PROCEDURE check_consistency();

--
INSERT INTO product VALUES("prod1", true);
INSERT INTO product VALUES("prod1", false);
INSERT INTO product VALUES("prod1", false); // exception!

это нормально

 name | expired
 ==============
 p1   |  true
 p1   |  true
 p1   |  false

Это не нормально

 name | expired
 ==============
 p1   |  true
 p1   |  false
 p1   |  false

или, может быть, я должен спросить, как я могу использовать Trigger для реализации SQL "Primary" или "Unique".

Ответы [ 2 ]

6 голосов
/ 07 апреля 2010

Ваш пример может быть выполнен с уникальным индексом:

CREATE UNIQUE INDEX uq_check_consistency ON product ( name ) WHERE NOT expired;

Это приведет к появлению оператора во второй транзакции, который мог бы вызвать ограничение, блокируя до тех пор, пока первая транзакция не завершится или не откатится.

Отредактировано для добавления :

Чтобы получить аналогичное (или более сложное) безопасное с точки зрения транзакций поведение с триггерами, вы можете создать CONSTRAINT триггер , который откладывается до времени фиксации транзакции. Эти триггерные функции должны быть AFTER триггерами, проверяющими, было ли нарушено ваше ограничение:

CREATE OR REPLACE FUNCTION after_check_consistency() RETURNS TRIGGER AS $$
  BEGIN
    IF (SELECT count(*) FROM product WHERE name=NEW.name AND expired='false') > 1 THEN
      RAISE EXCEPTION 'duplicated!!!';              
    END IF;
    RETURN NULL;
  END;
$$ LANGUAGE plpgsql;


CREATE CONSTRAINT TRIGGER trigger_check_consistency
AFTER INSERT OR UPDATE ON product
DEFERRABLE INITIALLY DEFERRED
FOR EACH ROW EXECUTE PROCEDURE after_check_consistency();
0 голосов
/ 06 апреля 2010

Почему вы не можете использовать уникальный ключ для обеспечения этого?

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