2012-03-22 7 views
6

Mam trzy tabele, nazwijmy je GRANDPARENT, PARENT i CHILD. PARENT ma kolumnę FK do GRANDPARENT 's PK, a CHILD ma kolumnę FK do PARENT' s PK. Jak na razie dobrze.Jak ustawić aktualizowalny widok z dołączeniem do Firebird?

Teraz chcę ustawić widok, który zawiera wszystkie informacje w CHILD, plus PK od GRANDPARENT. A więc:

CREATE VIEW CHILD_VIEW 
(
    ID, 
    PARENT_ID, 
    OTHER_STUFF, 
    GRANDPARENT_ID 
) 
AS 
SELECT 
    C.ID, 
    C.PARENT_ID, 
    C.OTHER_STUFF, 
    C.GRANDPARENT_ID 
FROM CHILD C 
join PARENT P on P.ID = C.PARENT_ID; 

Nie za ciężko. Ale tu jest podchwytliwa część: chcę mieć możliwość wyświetlenia tego widoku w postaci INSERT lub UPDATE, a wszystkie istotne dane zostaną zapisane w tabeli CHILD, a wartość GRANDPARENT_ID, jeśli taka istnieje, powinna zostać zignorowana.

Zrobiłem trochę Googling i najwidoczniej powinno być możliwe ustawienie widoku aktualizowalnego, takiego jak to "przy użyciu wyzwalaczy", ale nie wyjaśnia to nigdzie, co mam zrobić z wyzwalaczami, aby osiągnąć ten efekt. Myślę, że wiem mniej więcej jak sobie radzić z obudową INSERT, ale co z obudową UPDATE? UPDATE Wyrażenia mają klauzule WHERE i mogą zawierać dowolne kolumny w tabeli.

Na przykład, jak użyć wyzwalacza, aby przekształcić coś w rodzaju update CHILD_VIEW set (blah blah blah) where ID = 5 w update CHILD set (blah blah blah excluding GRANDPARENT_ID) where ID = 5?

+0

Dobre pytanie o 'UPDATE' tylko niektórych kolumn ... AFAIK tam nie jest sposobem na wykrycie, które kolumny są zawarte w instrukcji 'UPDATE', która spowodowała uruchomienie wyzwalacza' ON UPDATE'. Myślę, że jest to warte polecenia funkcji w Firebird tracker, jeśli jeszcze go nie ma. – ain

+0

Czy w swoim kodzie 'C.GRANDPARENT_ID' nie powinien być' P.GRANDPARENT_ID'? – EMBarbosa

+0

brak widoku wielu tabel 'INSERT' /' UPDATE's? booooo! –

Odpowiedz

6

Cóż, to zrobić za pomocą wyzwalaczy, jak już dowiedziałem :)

To naprawdę jest takie proste, można korzystać z wszystkich funkcji dostępnych w wyzwalacze (tj OLD i NEW kontekstów) ... jeśli używasz Firebird 2.1 lub nowszego, możesz użyć instrukcji UPDATE OR INSERT lub możesz użyć zmiennych kontekstowych INSERTING i UPDATING, aby wykryć, czy jest to aktualizacja czy wstawienie do wyzwalacza wielozadaniowego. Albo, oczywiście, można napisać osobne ON UPDATE i ON INSERT wyzwalacze ...

Więc spust może wyglądać jak ten

CREATE TRIGGER CHILD_VIEW_Save FOR CHILD_VIEW 
ACTIVE BEFORE INSERT OR UPDATE POSITION 10 
AS 
BEGIN 
    IF(NEW.ID IS NULL)THEN NEW.ID = GEN_ID(GEN_Child, 1); 
    UPDATE OR INSERT INTO CHILD (ID, PARENT_ID, OTHER_STUFF, GRANDPARENT_ID) 
      VALUES(NEW.ID, NEW.PARENT_ID, NEW.OTHER_STUFF, NEW.GRANDPARENT_ID); 
END 
+0

... a co z klauzulą ​​WHERE, gdy jest to 'UPDATE'? –

+2

Co z tym? Jeśli masz na myśli 'gdzie' w' UPDATE CHILD_View WHERE', to nie przejmujesz się tym w wyzwalaczu (wyzwalacz zostanie uruchomiony dla każdego pasującego wiersza), jeśli masz na myśli "GDZIE" wewnątrz wyzwalacza ", wtedy albo użyj 'UPDATE OR INSERT' lub napisz klauzulę WHERE (znasz PK tabeli, którą zamierzasz zaktualizować wewnątrz wyzwalacza). – ain

+0

OK, dobry punkt na PK. Inną trudną rzeczą jest 'UPDATE', która nie aktualizuje całego zestawu kolumn. Jeśli mam 5 kolumn w tabeli, a instrukcja UPDATE ustawia tylko 3 z nich, co spowoduje, że przykładowy przykład spowoduje, że do innych kolumn? –

Powiązane problemy