Как предотвратить удаление первой строки в таблице (PostgreSQL)? - PullRequest
6 голосов
/ 01 мая 2009

Можно ли предотвратить удаление первой строки в таблице на стороне PostgreSQL?

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

Я думаю, что это как-то связано с правилами в операторе удаления, но я не смог найти ничего похожего на проблему в документации.

Ответы [ 5 ]

11 голосов
/ 04 мая 2009

Вы были правы, думая о системе правил. Здесь - ссылка на пример, соответствующий вашей проблеме. Это даже проще, чем триггеры:

create rule protect_first_entry_update as
  on update to your_table
  where old.id = your_id
  do instead nothing;
create rule protect_first_entry_delete as
  on delete to your_table
  where old.id = your_id
  do instead nothing;

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

10 голосов
/ 01 мая 2009

Вы хотите определить BEFORE DELETE триггер в таблице. При попытке удалить строку (либо сопоставить по PK, либо создать отдельный логический столбец «protect»), RAISE исключение.

Я не знаком с синтаксисом PostgreSQL, но похоже, что это то, как вы это сделаете:

CREATE FUNCTION check_del_cat() RETURNS trigger AS $check_del_cat$
    BEGIN            
        IF OLD.ID = 1 /*substitute primary key value for your row*/ THEN
            RAISE EXCEPTION 'cannot delete default category';
        END IF;

    END;
$check_del_cat$ LANGUAGE plpgsql;

CREATE TRIGGER check_del_cat BEFORE DELETE ON categories /*table name*/
    FOR EACH ROW EXECUTE PROCEDURE check_del_cat();
5 голосов
/ 01 мая 2009

Лучший способ добиться этого - создать триггер удаления для этой таблицы. По сути, вам нужно написать хранимую процедуру, чтобы убедиться, что эта категория «по умолчанию» всегда будет существовать, а затем применить ее с помощью события триггера ON DELETE в этой таблице. Хороший способ сделать это - создать триггер для каждой строки, который гарантирует, что при событиях DELETE строка категории «по умолчанию» никогда не будет удалена.

Пожалуйста, ознакомьтесь с документацией PostgreSQL о триггерах и хранимых процедурах:

http://www.postgresql.org/docs/8.3/interactive/trigger-definition.html

http://www.postgresql.org/docs/8.3/interactive/plpgsql.html

В этой вики также есть ценные примеры:

http://wiki.postgresql.org/wiki/A_Brief_Real-world_Trigger_Example

1 голос
/ 01 мая 2009

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

0 голосов
/ 06 мая 2009

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

Должен ли я использовать правило или триггер?

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

Подробности см. В документации.
http://www.postgresql.org/docs/8.3/interactive/rules-triggers.html

...