Forum Użytkownikow Subiekt GT
InsERT GT => Dodatki - zestawienia - sfera => Wątek zaczęty przez: lkozlowski w Czerwiec 23, 2016, 15:54:05
-
Witam,
Chciałem skonstruować trigger, który aktualizuje pole własne rozszerzone, gdy zmieniana jest data realizacji zamówienia.
Niestety, gdy go włączam, niemożliwe jest edytowanie Faktur Sprzedażowych (FS) - po zapisaniu.
Czy może ktoś ma wiedzę dlaczego "gryzą się" te dwa elementy, gdy w IF jest wybrany Typ= 16 (ZK)?
ALTER TRIGGER [dbo].[Aktualizacja_Kolejnosci_ZK_Po_Zmianie_Terminu_Realizacji]
ON [dbo].[dok__Dokument]
AFTER UPDATE
AS
IF (SELECT dok_Typ FROM inserted) = 16 AND (SELECT pwd_Fk01 FROM pw_Dane WHERE pwd_IdObiektu = (SELECT dok_Id FROM inserted)) >0
BEGIN
DECLARE @termin int, @priorytet int, @pwdid int
SET @termin = (SELECT CONVERT(INT, dok_TerminRealizacji) FROM inserted) -- Termin ZK
SET @priorytet = (SELECT pwd_Fk01 FROM pw_Dane WHERE pwd_IdObiektu = (SELECT dok_Id FROM inserted))
SET @pwdid = (SELECT dok_Id FROM inserted) -- ID rekordu w tabeli pw_Dane
UPDATE dbo.pw_Dane
SET dbo.pw_Dane.pwd_Liczba01 = (CASE WHEN @priorytet in (29) THEN 3
WHEN @priorytet in (31) THEN 1
WHEN @priorytet in (32) THEN 2
WHEN @priorytet in (33,34,36,37,38,39,40,42,43,45,46) THEN 4
WHEN @priorytet in (47) THEN 6
ELSE 0 END )*100000000
+100000000-@termin*100
+@priorytet -- ustalenie kolejnosci kolumna #99Kolejność
WHERE dbo.pw_Dane.pwd_IdObiektu= @pwdid AND pwd_TypObiektu = -8
END
-
Nie analizowałem triggera, ale od razu nasuwa się pytanie. Co się dzieje, jeżeli aktualizowany jest więcej niż 1 rekord?
Co wtedy jest w inserted?
-
@birds22, Dzięki za uwagę! ;)
Generalnie mam założenie, że trigger działa tylko i wyłącznie w momencie zapisu otwartego ZK, więc zawsze powinien być to pojedynczy wiersz w inserted.
-
A jak zapewniasz że trigger działa "tylko i wyłącznie w momencie zapisu otwartego ZK"?
Na pierwszy rzut oka wydaje mi się że tylko siłą woli ;)
-
Kolejny podstawowy błąd to odwoływanie się do tabeli pw_Dane po identyfikatorze obiektu zamiast po identyfikatorze i typie obiektu (tabela ta zawiera dane dla wszystkich typów obiektów).
-
@birds22, Dzięki za uwagę! ;)
Generalnie mam założenie, że trigger działa tylko i wyłącznie w momencie zapisu otwartego ZK, więc zawsze powinien być to pojedynczy wiersz w inserted.
Twój trigger działa przy zdarzeniu update na tabeli dok__dokument, a nie przy zdarzeniu zapisu ZK. Wykonuje się przy update każdego dokumentu, który jest w tej tabeli. Dopiero w samym triggerze decydujesz co i kiedy będzie się działo.
-
Dzięki Panowie za uwagi :)
Kolejny podstawowy błąd to odwoływanie się do tabeli pw_Dane po identyfikatorze obiektu zamiast po identyfikatorze i typie obiektu (tabela ta zawiera dane dla wszystkich typów obiektów).
Założyłem, że identyfikator jest unikalny dla każdego wiersza (wg tego co widzę Pwd_id jest kluczem w tej tabeli). Czy się mylę?
@birds22, Dzięki za uwagę! ;)
Generalnie mam założenie, że trigger działa tylko i wyłącznie w momencie zapisu otwartego ZK, więc zawsze powinien być to pojedynczy wiersz w inserted.
Twój trigger działa przy zdarzeniu update na tabeli dok__dokument, a nie przy zdarzeniu zapisu ZK. Wykonuje się przy update każdego dokumentu, który jest w tej tabeli. Dopiero w samym triggerze decydujesz co i kiedy będzie się działo.
Rzeczywiście mam IF na zmianę na ZK (dok_Typ =16) Myślałem, że jeżeli nie jest spełniony ten warunek, to SQL nie podejmuje działa... Czy uważacie, że powinienem użyć jakiegoś ELSE?
-
Kolejny podstawowy błąd to odwoływanie się do tabeli pw_Dane po identyfikatorze obiektu zamiast po identyfikatorze i typie obiektu (tabela ta zawiera dane dla wszystkich typów obiektów).
Założyłem, że identyfikator jest unikalny dla każdego wiersza (wg tego co widzę Pwd_id jest kluczem w tej tabeli). Czy się mylę?
Unikalny jest pwd_Id, a nie pwd_IdObiektu, który nie tylko nie jest unikalny, ale może odnosić się do różnych tabel.
Krótko mówiąc to:
SELECT pwd_Fk01 FROM pw_Dane WHERE pwd_IdObiektu = (SELECT dok_Id FROM inserted)
wcale nie musi dać jednego rekordu
-
(...)
Założyłem, że identyfikator jest unikalny dla każdego wiersza (wg tego co widzę Pwd_id jest kluczem w tej tabeli). Czy się mylę?
Unikalny jest pwd_Id, a nie pwd_IdObiektu, który nie tylko nie jest unikalny, ale może odnosić się do różnych tabel.
Krótko mówiąc to:
SELECT pwd_Fk01 FROM pw_Dane WHERE pwd_IdObiektu = (SELECT dok_Id FROM inserted)
wcale nie musi dać jednego rekordu
Dzięki candy! :)
Chyba łapię. Czyli powinienem dodać "AND [pwd_TypObiektu]=-8 ", żeby dotyczyło to Rozszerzonego pola ZK, tak? =>
SELECT pwd_Fk01 FROM pw_Dane WHERE pwd_IdObiektu = (SELECT dok_Id FROM inserted) AND [pwd_TypObiektu]=-8
-
@birds22, Dzięki za uwagę! ;)
Generalnie mam założenie, że trigger działa tylko i wyłącznie w momencie zapisu otwartego ZK, więc zawsze powinien być to pojedynczy wiersz w inserted.
Twój trigger działa przy zdarzeniu update na tabeli dok__dokument, a nie przy zdarzeniu zapisu ZK. Wykonuje się przy update każdego dokumentu, który jest w tej tabeli. Dopiero w samym triggerze decydujesz co i kiedy będzie się działo.
Rzeczywiście mam IF na zmianę na ZK (dok_Typ =16) Myślałem, że jeżeli nie jest spełniony ten warunek, to SQL nie podejmuje działa... Czy uważacie, że powinienem użyć jakiegoś ELSE?
Ciągle nie łapiesz, przecież napisałem, że błędnie odwołujesz się do tabeli pd_Dane, a robisz to już w warunku, więc na już na etapie jego sprawdzania zapewne jest generowany błąd.
-
Chyba łapię. Czyli powinienem dodać "AND [pwd_TypObiektu]=-8 ", żeby dotyczyło to Rozszerzonego pola ZK, tak? =>
SELECT pwd_Fk01 FROM pw_Dane WHERE pwd_IdObiektu = (SELECT dok_Id FROM inserted) AND [pwd_TypObiektu]=-8
Tak i piszę o tym od początku, a poprawne odwołanie miałeś już przecież w przedostatniej linii w pierwszym zamieszczonym kodzie...
-
Chyba łapię. Czyli powinienem dodać "AND [pwd_TypObiektu]=-8 ", żeby dotyczyło to Rozszerzonego pola ZK, tak? =>
SELECT pwd_Fk01 FROM pw_Dane WHERE pwd_IdObiektu = (SELECT dok_Id FROM inserted) AND [pwd_TypObiektu]=-8
Tak i piszę o tym od początku, a poprawne odwołanie miałeś już przecież w przedostatniej linii w pierwszym zamieszczonym kodzie...
Dzięki Danielu, chyba wcześniej Cię nie zrozumiałem :)
Dziękuję wszystkim za cierpliwość i spokojne wytłumaczenie. No i zarazem podejście, w którym mogłem się nauczyć czegoś nowego, a nie tylko dostać odpowiedź! Super! :D
-
Rzeczywiście mam IF na zmianę na ZK (dok_Typ =16) Myślałem, że jeżeli nie jest spełniony ten warunek, to SQL nie podejmuje działa... Czy uważacie, że powinienem użyć jakiegoś ELSE?
Tu nie chodzi o dodatkowy warunek. Inserted to tabela i niekoniecznie musi mieć jeden rekord. Może być zmienione jednocześnie wiele wierszy, więc musisz wykonać to na wszystkich (jeżeli jest ich więcej niż 1)
-
Rzeczywiście mam IF na zmianę na ZK (dok_Typ =16) Myślałem, że jeżeli nie jest spełniony ten warunek, to SQL nie podejmuje działa... Czy uważacie, że powinienem użyć jakiegoś ELSE?
Tu nie chodzi o dodatkowy warunek. Inserted to tabela i niekoniecznie musi mieć jeden rekord. Może być zmienione jednocześnie wiele wierszy, więc musisz wykonać to na wszystkich (jeżeli jest ich więcej niż 1)
???Przed UPDATE dodać
IF EXISTS (SELECT pwd_IdObiektu FROM dbo.pw_Dane WHERE dbo.pw_Dane.pwd_IdObiektu=@pwdid)
??...
-
Chyba zupełnie nie łapiesz o czym piszę...
Masz w swojej procedurze:
(SELECT dok_Typ FROM inserted) = 16
Jeżeli w tabeli inserted będzie więcej niż 1 rekord to ten test wywoła błąd.
Musisz to obsłużyć.
-
Masz w swojej procedurze:
(SELECT dok_Typ FROM inserted) = 16
Jeżeli w tabeli inserted będzie więcej niż 1 rekord to ten test wywoła błąd.
Musisz to obsłużyć.
@Bird22 Dzięki za poświęcony czas, cierpliwość, a nawet edycję pierwszej swojej odpowiedzi :) (załapałem poranną odpowiedź, ale nie miałem czasu)
Proponuję takie rozwiązanie.
IF (SELECT Count (dok_Id) FROM inserted)=1 -- Zapewnienie, że tylko 1 wiersz (tak się dzieje przy edycji ZK)
IF (SELECT Dok_Typ FROM inserted) = 16 AND (SELECT pwd_Fk01 FROM pw_Dane WHERE pwd_IdObiektu = (SELECT dok_Id FROM inserted) AND pwd_TypObiektu = -8 ) >0 --dalsze sprawdzanie warunków
Czy myślicie, że coś jeszcze warto uwzględnić?
-
Sprawdź i nam opowiedz ;)
NB po co to dok_Id w SELECT Count (dok_Id) FROM inserted ?
Jeśli chcesz sprawdzić ile jest rekordów to piszesz po prostu SELECT COUNT(*) FROM...
Dostajesz poprawny wynik bez względu na do czy w tabeli jest pole dok_Id czy go nie ma.
-
Jasne, że sam sprawdziłem i wiem, że działa ;)
Chodziło mi o to czy widzicie jeszcze jakieś potencjalne zagrożenia :)