Подтвердить что ты не робот

Для чего нужны ПРАВИЛА PostgreSQL?

Вопрос

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

Я спрашиваю об этом из общих интересов; Я не очень приправлен базами данных.

Пример того, что может быть допустимым использованием

Например, в прошлом мне нужно было блокировать определенные данные, поэтому я сделал что-то вроде этого:

CREATE OR REPLACE RULE protect_data AS
  ON UPDATE TO exampletable             -- another similar rule for DELETE
  WHERE OLD.type = 'protected'
  DO INSTEAD NOTHING;

Затем, если я хочу отредактировать защищенные данные:

START TRANSACTION;
  ALTER TABLE exampletable DISABLE RULE protect_data;
  -- edit data as I like
  ALTER TABLE exampletable ENABLE RULE protect_data;
COMMIT;

Я согласен, что это хакерство, но я не смог изменить приложение (ы), обращаясь к базе данных в этом случае (или даже выбросив на него ошибки). Итак, бонусные очки для поиска причины, по которой это опасное/недействительное использование системы правил, но не, почему это плохой дизайн.

4b9b3361

Ответ 1

Одним из вариантов использования для ПРАВИЛ являются обновляемые представления (хотя эти изменения в 9.1, поскольку эта версия вводит триггеры INSTEAD OF для просмотров)

Еще одно хорошее объяснение можно найти в руководстве:

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

(взято из: http://www.postgresql.org/docs/current/static/rules-triggers.html)

Ответ 2

Некоторые проблемы с правилами показаны здесь: http://www.depesz.com/index.php/2010/06/15/to-rule-or-not-to-rule-that-is-the-question/ (например, если в запрос включен random(), он может быть выполнен дважды и вернуть разные значения).

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

Например, можно подумать, что имея правило:

CREATE OR REPLACE RULE protect_data AS
  ON UPDATE TO exampletable             -- another similar rule for DELETE
  WHERE OLD.type = 'protected'
  DO INSTEAD NOTHING;

Будет означать, что если я выпущу:

update exampletable set whatever = whatever + 1 where type = 'protected'

Ни один запрос не будет выполнен. Что не соответствует действительности. Запрос будет выполнен, но он будет выполнен в измененной версии - с дополнительным условием.

Более того - правила нарушают очень полезную вещь, то есть возвращаемое предложение:

$ update exampletable set whatever = whatever + 1 where type = 'normal' returning *;
ERROR:  cannot perform UPDATE RETURNING on relation "exampletable"
HINT:  You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause.

Чтобы обернуть это - если вам действительно, действительно, положительно нужно использовать доступные для записи представления, и вы используете pre 9.1 PostgreSQL - у вас может быть веская причина для использования правил.

Во всех других случаях - вы, скорее всего, стреляете себе в ногу, даже если не сразу это видите.

Ответ 3

У меня было несколько горьких опытов с правилами при работе с летучими функциями (если память используется, сообщение в блоге depesz выделяет некоторые из них).

Я также нарушил ссылочную целостность при их использовании из-за времени, в которое запускаются триггеры fkey:

CREATE OR REPLACE RULE protected_example AS
  ON DELETE TO example
  WHERE OLD.protected
  DO INSTEAD NOTHING;

... затем добавьте другую таблицу и сделайте пример ссылкой на эту таблицу с внешним ключом для удаления каскада. Затем удалите * из этой таблицы... и отбросьте в ужасе.

Я сообщил об этой проблеме как ошибке, которая была отклонена как функция/необходимый край. Только через несколько месяцев я понял, почему это может произойти, т.е. Триггер fkey выполняет свою работу, а затем правило запускается и делает свое, но триггер fkey не будет проверять правильность его работы по причинам производительности.

Практический прецедент, в котором я по-прежнему использую правила, - это когда триггер BEFORE, который предварительно обрабатывает данные (стандарт SQL говорит, что это запрещено, но Postgres с радостью обязуется) может привести к предварительному манипулированию затронутыми строками и таким образом изменяя их ctid (т.е. он обновляется дважды или не удаляется, поскольку обновление аннулирует удаление).

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

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

Ответ 4

Как насчет этого: у вас есть таблица, которая должна быть изменена в виде. Для поддержки устаревших приложений, которые вставляются в указанную таблицу, создается правило, которое отображает "вставки" в новое представление в базовую таблицу (таблицы).