26. februar 2003 - 15:12Der er
20 kommentarer og 1 løsning
Triggers
Jeg har spurgt før, men uden 100 % held..
Jeg har 2 tabeller: Main og ItemsForSale.
I Main har jeg et felt der hedder ForSale som kan være enten 0 eller 1. I ItemsForSale har jeg oplysniner såsom pris og reservation og den slags. De to tabeller har begge et felt der hedder IDNumber, og de numre "hænger sammen" så der er tale om det samme item.
Jeg vil gerne have en trigger der fyres af hver gang ForSale i Main opdateres, og som tester på om den herefter er 1 eller 0. Er den 0 skal dens "ven" i ItemsForSale slettes helt,..¨
Denne side indeholder artikler med forskellige perspektiver på Identity & Access Management i private og offentlige organisationer. Artiklerne behandler aktuelle IAM-emner og leveres af producenter, rådgivere og implementeringspartnere.
Sådan skal din trigger laves... Er testet på SQL2000 og virker!!! Både når du ændre en eller MANGE records /Thomas
CREATE TRIGGER ut_main ON [dbo].[Main] FOR UPDATE AS SET NOCOUNT on
Declare @@IDnumber as Integer Declare @@ForSale as integer
IF UPDATE(ForSale) IF @@ROWCOUNT = 1 BEGIN SELECT @@IDnumber=IDnumber, @@ForSale=ForSale FROM inserted if @@ForSale=0 Delete from ItemsForSale where IDnumber=@@IDnumber END ELSE BEGIN DECLARE ut_main_cursor CURSOR FOR SELECT IDnumber, ForSale FROM inserted
OPEN ut_main_cursor
-- hent første FETCH NEXT FROM ut_main_cursor into @@IDnumber, @@ForSale
-- Check @@FETCH_STATUS WHILE @@FETCH_STATUS = 0 BEGIN if @@ForSale=0 Delete from ItemsForSale where IDnumber=@@IDnumber FETCH NEXT FROM ut_main_cursor into @@IDnumber, @@ForSale END
uhauha da, sådan noget må man aldrig gøre, en cursor i en trigger... Meget meget skamfuldt!
Det eneste der skal til for opfylde tullas behov er:
CREATE TRIGGER delForSale ON dbo.Main FOR UPDATE AS IF NOT UPDATE(ForSale) RETURN DELETE ItemsForSale WHERE id = (SELECT id FROM INSERTED)
---------
tulla, tag det som en fortsættelse af den anden tråd. Jeg vil ikke have point, men lov mig at du aldrig bruger en cursor i en trigger medmindre det er eneste udvej (og det er det meget sjældent).
hmm, hvis den sføli kun skal slette når forsale bliver sat til 0, da:
CREATE TRIGGER delForSale ON dbo.Main FOR UPDATE AS IF NOT UPDATE(ForSale) RETURN DECLARE @id INT, @fs INT SELECT @id = id, @fs = ForSale FROM INSERTED IF @fs = 0 DELETE ItemsForSale WHERE id = @id
Janus_007 du har helt ret i at det ikke er en god ide at bruge cursor i en trigger, derfor er koden lavet så den checkker @@rowcount og kun benytter cursoren HVIS man fx opdaterer FLERE rækker. Din løsning virker IKKE på flere rækker (fx update forsale=0 where kunde='janus_007' ) men kun på EN, men vi man aldring kommer i den sitiuation er dette jo ikke noget problem!
Det ser rigtigt ud,.. men der er lige et lille problem, mit id er ikke en int, men en VarChar, og det er den ganske enkelt nødt til at være. Jeg bruger så selvfølgelig varchar i triggeren,.meeen det virker ikke, ved en af jer noget om det ?
CREATE TRIGGER delForSale ON dbo.Main FOR UPDATE AS IF UPDATE(ForSale) DECLARE @id varchar, @fs int SELECT @id = IDnumber, @fs = ForSale FROM INSERTED IF @fs = 0 DELETE dbo.ItemsForSale WHERE dbo.ItemsForSale.IDnumber = @id
Men den sletter ingenting, og jeg får ingen fejlmeddelelser af nogen art.
Du mangler en BEGIN END og så synes jeg det vil være en rigtig god ide af sætte størrelse på din varchar /Thomas
CREATE TRIGGER delForSale ON dbo.Main FOR UPDATE AS IF UPDATE(ForSale) BEGIN DECLARE @id varchar(10), @fs int SELECT @id = IDnumber, @fs = ForSale FROM INSERTED IF (@fs = 0) DELETE FROM dbo.ItemsForSale WHERE dbo.ItemsForSale.IDnumber = @id END
Update triggere er i sig selv ikke til at opdatere med, de er kun til at få udført et event som fx bremser updaten eller sørger for at der opdateres i andre tabeller. Update skal ses som, delete + insert.
Jeg gentager lige igen... Lad være med at bruge cursor i en trigger! -
Ved updatering af flere værdier, laves blot en SELECT ala... DELETE ItemsForSale WHERE id IN (SELECT id FROM Main WHERE ForSale = 0)
eller måske, hvis man hellere er ligeglad med 0 eller 1 så bare: DELETE ItemsForSale WHERE id IN (SELECT id FROM INSERTED)
techhouse, få styr på din sql.... og undgå at bruge cursor løsninger!! og forøvrigt techhouse, man behøver ikke en BEGIN END ved 1 linjes statement, en varchar skal altid sættes til en størrelse, så det er ikke bare en god idé, det er et krav!!
Efter janus_007 gode indlæg og ide kan triggeren ændres til overnævnte Jeg har til tilført "where ForSale=0" således at vi ikke får formeget access til SQLen.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.