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

StackOverflow https://stackoverflow.com/questions/810180

  •  03-07-2019
  •  | 
  •  

Вопрос

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

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

Я думаю, что это как-то связано с правилами инструкции 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

Другие советы

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

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;

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

Вы хотите определить значение ПЕРЕД УДАЛЕНИЕМ триггер на столе.Когда вы пытаетесь удалить строку (либо совпадающую по PK, либо имеющую отдельный логический столбец "protect"), ПОДНЯТЬ исключение.

Я не знаком с синтаксисом 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();

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top