2009-05-01 7 views
5

Czy można zapobiec usunięciu pierwszego wiersza w tabeli po stronie PostgreSQL?Jak zapobiec usunięciu pierwszego wiersza w tabeli (PostgreSQL)?

Mam tabelę kategorii i chcę zapobiec usunięciu domyślnej kategorii, ponieważ może ona spowodować zerwanie aplikacji. Oczywiście mogłem to łatwo zrobić w kodzie aplikacji, ale byłoby o wiele lepiej zrobić to w bazie danych.

Myślę, że ma to coś wspólnego z regułami dotyczącymi instrukcji usuwania, ale nie mogłem znaleźć niczego, co byłoby bliskie mojemu problemowi w dokumentacji.

Odpowiedz

6

Najlepszym sposobem widzę, aby to osiągnąć, jest stworzenie usuwania spust na tym stole. Zasadniczo, będziesz musiał napisać procedurę przechowywaną, aby upewnić się, że ta "domyślna" kategoria zawsze będzie istniała, a następnie wymusić ją przy użyciu zdarzenia wyzwalacza NA DELETE w tej tabeli. Dobrym sposobem na zrobienie tego jest utworzenie wyzwalacza na wiersz, który zagwarantuje, że w przypadku zdarzeń DELETE wiersz kategorii "domyślny" nigdy nie zostanie usunięty.

Proszę sprawdzić dokumentację PostgreSQL o wyzwalaczy i procedur przechowywanych:

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

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

Istnieje również cenne przykłady w tym wiki:

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

9

Chcesz zdefiniować PRZED USUNĄĆ trigger na stole. Przy próbie usunięcia wiersza (dopasowanego przez PK lub posiadającego osobną kolumnę binarną "protect") wyjątek stanowi RAISE.

nie jestem zaznajomiony z składni PostgreSQL, ale it looks like to jak chcesz to zrobić:

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(); 
+0

Dzięki za odpowiedź. Zarówno ty i Macalendas dał pomocne odpowiedzi, więc trudno było wybrać "akceptowaną" odpowiedź, ale zdecydowałem się przekazać ją Macalendom, aby zachęcić nowych użytkowników do wzięcia udziału w tej niesamowitej witrynie. Dzięki! –

+0

Nie ma problemu i cieszę się, że mogłem pomóc. Właśnie zamknąłem niedopasowane cytuj w tagu , więc linki powinny teraz działać poprawnie. –

9

Miałeś rację, myśląc o systemie reguł. Here to link do przykładu pasującego do Twojego problemu. Jest jeszcze prostsze niż wyzwalacze:

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; 

Niektóre odpowiedzi pomijają jeden punkt: również aktualizacja chronionego wiersza musi być ograniczona. W przeciwnym razie można najpierw zaktualizować chroniony wiersz, tak aby nie spełniał on już zabronionego kryterium usuwania, a następnie można usunąć zaktualizowany wiersz, ponieważ nie jest już chroniony.

+0

nie wiesz, dlaczego ta odpowiedź nie ma więcej miłości, ale zasady ochrony są niesamowite!: +1: –

0

Należy pamiętać, jak działają wyzwalacze. Będą strzelać do każdego rzędu, z którego usunie twoje polecenie usunięcia. Nie oznacza to, że nie powinieneś używać wyzwalaczy, tylko miej to na uwadze, a co najważniejsze przetestuj scenariusze użytkowania i upewnij się, że wydajność spełnia wymagania.

Czy powinienem użyć reguły lub spustu?

Z oficjalnych dokumentów: "Dla rzeczy, które mogą być zaimplementowane przez oba, co jest najlepsze, zależy od użycia bazy danych." Reguła manipuluje zapytaniem lub generuje dodatkowe zapytanie. Tak więc, jeśli w jednej instrukcji występuje wiele wierszy, reguła wydająca jedno dodatkowe polecenie prawdopodobnie będzie szybsza niż wyzwalacz, który jest wywoływany dla każdego wiersza i musi wykonywać swoje operacje wiele razy.Jednak podejście wyzwalania jest koncepcyjnie znacznie prostsze niż podejście regułę, a jest łatwiejsze dla początkujących, aby uzyskać prawo „.

Zobacz docs o szczegóły.
http://www.postgresql.org/docs/8.3/interactive/rules-triggers.html