Strona główna Aktualizacja widoku w PosgreSQL
Wpis
Anuluj

Aktualizacja widoku w PosgreSQL

Aktualizacja widoku w PosgreSQL

Pracując na bazie danych PostgreSQL natchnąłem się na informacje dotyczące wykonywania update’ów na widokach. Oczywiście dotyczy to wersji >9.0 tego silnika baz danych, ale - po kolei.

Ogarnimy moją sytuację. Mam dwie tabele: message i messagetext.

1
2
3
4
5
6
7
8
9
10
11
12
CREATE TABLE message (
    id serial PRIMARY KEY,
    sender integer NOT NULL,
    recipient integer NOT NULL,
    date timestamp without timezone NOT NULL,
    messagetextid integer NOT NULL
);
CREATE TABLE messagetext (
    textid serial PRIMARY KEY,
    subject character varying NOT NULL,
    message text NOT NULL
);

Jedna przetrzymuje instancje wiadomości (nadawca, odbiorca, daty, itp), a druga teksty (oczywiście w grę wchodzą wiadomości “do wielu”). Aby pobrać listę wiadomości, trzeba albo łączyć te dwie tabele, albo joinować. I tu z pomocą przychodzi widok.

1
2
3
4
CREATE VIEW messages AS
    SELECT message.id, message.recipient, message.date, message.sender, messagetext.textid, messagetext.message, messagetext.subject
        FROM message
        JOIN messagetext ON message.messagetextid = messagetext.textid;

Teraz pobranie listy to po prostu:

1
SELECT * FROM messages

Domyślnie wszystkie widoki zachowują się jak tabele, ale w trybie tylko do odczytu. Próba wykonania na nich aktualizacji zakończy się błędem, ponieważ silnik bazodanowy nie będzie wiedział, jak zaktualizować fizyczne tabele kryjące się pod definicją widoku:

1
2
3
Błąd SQL:
ERROR:  cannot update a view
HINT:  You need an unconditional ON UPDATE DO INSTEAD rule.

W poleceniu:

1
UPDATE messages SET sender=3 WHERE id=3

Z pomocą w tym przypadku przychodzą nam reguły. Widoki modyfikowalne tworzone są dzięki systemowi tych reguł.

1
2
3
4
5
CREATE RULE messages_upd AS
    ON UPDATE TO messages DO INSTEAD (
        UPDATE message SET sender = NEW.sender, recipient=NEW.recipient, date=NEW.date WHERE id = NEW.id;
        UPDATE messagetext SET subject=NEW.subject, message=NEW.message WHERE textid = NEW.textid;
    );
Ten post jest udostępniony na licencji CC BY 4.0 przez autora.

Parsowanie plików CSV w PHP

Jak policzyć różnicę pomiędzy dwoma datami w miesiącach?