MSSQL/PostgreSQL przepisywanie triggera.

MSSQL/PostgreSQL przepisywanie triggera.
BI
  • Rejestracja:około 12 lat
  • Ostatnio:prawie 11 lat
  • Postów:8
0

Witam, staram się przepisać bazę danych oraz oprogramowanie do niej na PostgreSQL, udało mi się przepisać skrypt tworzący, funkcje, widoki itd ale na triggerach mam problem :(
Mam wrażenie że postgres jest bardzo ubogi w stosunku do mssql ponieważ nie mogę nawet znaleźć porządnego poradnika. Proszę o pomoc z tym wyzwalaczem:

Kopiuj
-- Wyzwalacz który zamiast usunąć z bazy danych stanowisko, 
-- archiwizuje je w tej samej tabeli w kolumnach które normalnie są nieużywane i mają wartość NULL.
-- W przypadku gdy stanowisko zostało już wcześniej usunięte np, przez kogoś innego, wyzwalacz wydrukuje specjalną informację.
CREATE TRIGGER del_stan ON stanowisko
INSTEAD OF DELETE
AS
	DECLARE @id INT, @name Varchar(20)
	SET @id=(SELECT id_stanowisko FROM deleted)
	SET @name=(SELECT nazwa FROM deleted)

	BEGIN
		IF (77777.00)=(SELECT stara_pensja FROM stanowisko WHERE id_stanowisko=@id)
		  BEGIN
		  	PRINT 'Stanowisko '+@name+'zostało zarchiwizowane.'
			UPDATE stanowisko SET stara_pensja=pensja_godz		WHERE id_stanowisko=@id
			UPDATE stanowisko SET stare_godz=min_ilosc_godz		WHERE id_stanowisko=@id
			UPDATE stanowisko SET data_wygasniecia = GETDATE()	WHERE id_stanowisko=@id
			UPDATE stanowisko SET pensja_godz = 0				WHERE id_stanowisko=@id
			UPDATE stanowisko SET min_ilosc_godz = 0			WHERE id_stanowisko=@id
		  END
		 ELSE
		  BEGIN
			PRINT 'Operacja nie powiodła się ponieważ:'
			PRINT 'Stanowisko '+@name+'zostało zarchiwizowane wcześniej.'
		  END
	END
GO

mój problem polega na tym że używam tam tabeli 'deleted' a z tego co wyczytałem (w sumie nie wyczytałem bo nie znalazłem info) takiej tabeli w PSQL po prostu nie ma.

OA
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 10 lat
  • Postów:95
1

http://www.postgresql.org/docs/9.2/static/sql-createtrigger.html
http://www.postgresql.org/docs/9.2/static/plpgsql-trigger.html
Do starych (nowych) rekordów można odwoływać się poprzez old.x (new.x), gdzie x jest polem tabeli.

W tym przypadku kod będzie wyglądał mniej więcej tak:

Kopiuj
-- Wyzwalacz który zamiast usunąć z bazy danych stanowisko, 
-- archiwizuje je w tej samej tabeli w kolumnach które normalnie są nieużywane i mają wartość NULL.
-- W przypadku gdy stanowisko zostało już wcześniej usunięte np, przez kogoś innego, wyzwalacz wydrukuje specjalną informację.
CREATE FUNCTION trig_del_stan() RETURNS trigger AS $$
BEGIN
    INSERT INTO stanowisko VALUES (OLD.*);
    IF 77777.00 = OLD.stara_pensja
    THEN
        RAISE NOTICE 'Stanowisko % zostało zarchiwizowane.', OLD.nazwa;
        UPDATE stanowisko
           SET stara_pensja = pensja_godz
             , stare_godz = min_ilosc_godz
             , data_wygasniecia = NOW()
             , pensja_godz = 0
             , min_ilosc_godz = 0
         WHERE id_stanowisko = OLD.id_stanowisko;
    ELSE
        RAISE NOTICE 'Operacja nie powiodła się ponieważ:';
        RAISE NOTICE 'Stanowisko % zostało zarchiwizowane wcześniej.', OLD.nazwa;
    END IF;
END;
$$ LANGUAGE PLPGSQL;

CREATE TRIGGER del_stan ON stanowisko
    AFTER DELETE FOR EACH ROW EXECUTE PROCEDURE trig_del_stan();

Uwaga: Kodu nie testowałem i nie mam jak go uruchomić, gdyż nie mam dostępu do żadnej bazy danych SQL. Mogą być jakieś drobne błędy.

edytowany 6x, ostatnio: Oak
BI
"INSTEAD OF triggers (which are always row-level triggers, and may only be used on views)" I niestety wlasnie dostaje błąd że taki trigger nie moze byc uzyty na tabeli ;/
OA
Spróbuj teraz. Może niezbyt wyrafinowany sposób, ale powinien zadziałać. ;)
BI
ERROR: syntax error at end of input LINIA 5: FROM OLD.*; nie łapię tego, non stop jakies chore errory :|
BI
  • Rejestracja:około 12 lat
  • Ostatnio:prawie 11 lat
  • Postów:8
0

udało mi się stworzyć taki zamiennik:

Kopiuj
CREATE FUNCTION del_stan()
RETURNS TRIGGER AS $$
	BEGIN
		IF (77777.00)=(OLD.stara_pensja) THEN
		  	RAISE NOTICE 'Stanowisko zostalo zarchiwizowane.';
			NEW.stara_pensja=OLD.pensja_godz;
			NEW.stare_godz=OLD.min_ilosc_godz;
			NEW.data_wygasniecia =(CURRENT_DATE);	
			NEW.pensja_godz = 0;
			NEW.min_ilosc_godz = 0;
		ELSE
			RAISE NOTICE 'Operacja nie powiodla sie poniewaz:';
		END IF;
	END;
$$LANGUAGE'plpgsql';

CREATE TRIGGER del_stan
AFTER DELETE ON stanowisko
FOR EACH ROW EXECUTE PROCEDURE del_stan();

Niestety jak próbuje usunąć to dostaję ERROR:
ERROR: record "new" is not assigned yet
SZCZEGÓŁY: The tuple structure of a not-yet-assigned record is indeterminate.
KONTEKST: PL/pgSQL function "del_stan" line 5 at assignment

OA
NEW używa się przy insert/update. Przy delete masz do dyspozycji tylko OLD.
BI
  • Rejestracja:około 12 lat
  • Ostatnio:prawie 11 lat
  • Postów:8
0

Po kilku próbach ten kod nie wywala errora. Jednak jego wadą jest to że najpierw usuwa a później chce zaktualizować tabele dla nieistniejącego rekordu (bo przed chwilą go usunął). Więc trigger działa ale nic nie robi ;/ Nie rozumiem dlaczego nie można zastosować triggera INTEAD OF dla tabeli, może jest na to jakieś obejście ??

Kopiuj
CREATE oR REPLACE FUNCTION trig_del_stan() RETURNS TRIGGER AS $$
BEGIN
 /*   INSERT INTO stanowisko
    (SELECT * FROM OLD.*;) */
    IF 77777.00 = OLD.stara_pensja
    THEN
        RAISE NOTICE 'Stanowisko % zostalo zarchiwizowane.', OLD.nazwa;
        UPDATE stanowisko
           SET stara_pensja = pensja_godz
             , stare_godz = min_ilosc_godz
             , data_wygasniecia = NOW()
             , pensja_godz = 0
             , min_ilosc_godz = 0
         WHERE id_stanowisko = OLD.id_stanowisko;
    ELSE
        RAISE NOTICE 'Operacja nie powiodla sie poniewaz:';
        RAISE NOTICE 'Stanowisko % zostalo zarchiwizowane wczesniej.', OLD.nazwa;
    END IF;
	RETURN NEW;
END;
$$ LANGUAGE PLPGSQL;
 
CREATE TRIGGER del_stan 
    AFTER DELETE ON stanowisko FOR EACH ROW EXECUTE PROCEDURE trig_del_stan();
	
BI
to zapewne dlatego że zakomentowałem INSERT tam na górze, jednak gdy jest to aktywne to wywala ERROR: Near SELECT * FROM OLD.*;
OA
Tak pewnie dlatego. Spróbuj teraz. Jak już mówiłem nie mam gdzie tego przetestować, a kodu SQL nie pisałem przez jakieś pół roku. ;)
0

Spróbuj zamiast AFTER w trigerze użyć BEFORE, a w funkcji na końcu RETURN NULL, wtedy operacja niczego nie powinna zmieniać

BI
ERROR: duplicate key value violates unique constraint "stanowisko_pkey" SZCZEGĂĹY: Key (id_stanowisko)=(6) already exists. KONTEKST: SQL statement "INSERT INTO stanowisko VALUES (OLD.*)" PL/pgSQL function "trig_del_stanxx" line 3 at SQL statement Próbowałem różnych metod, czasem jak 'zadziałało' to wydrukowało mi tylko te RAISE NOTICE ale jak sprawdzalem potem tabele to nic sie tam nie zmienilo.
BI
  • Rejestracja:około 12 lat
  • Ostatnio:prawie 11 lat
  • Postów:8
1

Odnalazłem błąd, znajdował się on w moim głupim niedopatrzeniu. Jestem przyzwyczajony do MSSQL i tam mi się raczej takie rzeczy nie zdarzały :) Mianowicie miałem 3 funkcje i 3 triggery nałożone na tabelę stanowisko. Ta funkcja poniżej jest jak najbardziej prawidłowa. Errory wywalały stare wersje tej funkcji których nie usunęłem. 2 dni prób i denerwowania się po to żeby w tak banalny sposób rozwiązać problem.
Bardzo dziękuję za pomoc bo ostatecznie to jednak pomysł jest użytkownika Oak.
Pozdrawiam.
:)

Wersja działająca jakby ktoś miał w przyszłości problem:

Kopiuj
CREATE OR REPLACE FUNCTION trig_del_stanx() RETURNS TRIGGER AS $$
BEGIN
   INSERT INTO stanowisko VALUES (OLD.*);
    IF 77777.00 = OLD.stara_pensja
    THEN
        RAISE NOTICE 'Stanowisko % zostalo zarchiwizowane.', OLD.nazwa;
        UPDATE stanowisko
           SET stara_pensja = pensja_godz
             , stare_godz = min_ilosc_godz
             , data_wygasniecia = NOW()
             , pensja_godz = 0
             , min_ilosc_godz = 0
        WHERE nazwa = OLD.nazwa;
		RETURN NEW;
    ELSE
        RAISE NOTICE 'Operacja nie powiodla sie poniewaz:';
        RAISE NOTICE 'Stanowisko % zostalo zarchiwizowane wczesniej.', OLD.nazwa;
		RETURN NULL;
    END IF;

END;
$$ LANGUAGE PLPGSQL;
 
CREATE TRIGGER del_stanx
    AFTER DELETE ON stanowisko FOR EACH ROW EXECUTE PROCEDURE trig_del_stanx();
edytowany 1x, ostatnio: bizarri
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)