|
| MSSQL triggers, hvordan ændrer man værdier~ Fra : Jørgen Østergaard |
Dato : 19-11-02 00:25 |
|
Hej,
jeg har behov for at bruge en insert/update trigger til at ændre værdier på
det indsatte/opdaterede, afhængigt af nogle betingelser. Hvordan gør man det
i SQL Server 2000?
I Oracle ville jeg skrive noget i retning af:
---
create trigger ...
....
begin
if(:new.col1='test') then
:new.col1='test2';
end if;
end;
---
Findes der en pendant i Transact-SQL verdenen??? ;)
På forhånd tak,
Jørgen
| |
Stig Johansen (19-11-2002)
| Kommentar Fra : Stig Johansen |
Dato : 19-11-02 07:21 |
|
Hej.
"Jørgen Østergaard" <joesterg@hotmail.comremovethis> wrote in message
news:arbssg$1hfr$1@news.cybercity.dk...
>
> Hej,
>
> jeg har behov for at bruge en insert/update trigger til at ændre værdier
på
> det indsatte/opdaterede, afhængigt af nogle betingelser. Hvordan gør man
det
> i SQL Server 2000?
>
> I Oracle ville jeg skrive noget i retning af:
> ---
> create trigger ...
> ...
> begin
> if(:new.col1='test') then
> :new.col1='test2';
> end if;
> end;
> ---
>
> Findes der en pendant i Transact-SQL verdenen??? ;)
Jeg bruger ikke selv triggers, men jeg er grumme bange for, at der kun er
'after' triggers i M$ SQLServer.
--
Med venlig hilsen/Best regards
Stig Johansen
Stig.Johansen@udvikling.it.dk
(remove dot dk)
| |
Jens Gyldenkærne Cla~ (19-11-2002)
| Kommentar Fra : Jens Gyldenkærne Cla~ |
Dato : 19-11-02 10:11 |
|
Stig Johansen skrev:
>> jeg har behov for at bruge en insert/update trigger til at
>> ændre værdier på det indsatte/opdaterede, afhængigt af nogle
>> betingelser. Hvordan gør man det i SQL Server 2000?
> Jeg bruger ikke selv triggers, men jeg er grumme bange for, at
> der kun er 'after' triggers i M$ SQLServer.
Hvad er problemet i det? Man kan sagtens lave triggere i T-SQL der
ændrer værdier i den tabel der er opdateret (såvel som i andre
tabeller). Her er et eksempel fra skuffen:
CREATE TRIGGER kontaktpersoner_nytlogin_trig
ON kontaktpersoner
FOR INSERT
AS
BEGIN
IF EXISTS ( SELECT 't' FROM Inserted
WHERE login = '#####')
BEGIN
UPDATE kontaktpersoner
SET login = 'b' + dbo.fillZero(CAST(@@IDENTITY AS
varchar(6)),4)
WHERE kontaktpersoner.personID = @@IDENTITY
END
END
Triggers i T-SQL benytter de virtuelle tabeller Inserted og Deleted
hvor indsatte/opdaterede, hhv. slettede rækker befinder sig. Man
kan ikke opdatere de virtuelle tabeller, men man kan - som det ses
- opdatere de rigtige tabeller bagved, uanset om det er samme tabel
som her, eller en helt anden tabel. Hvis man vil validere med
triggers kan man også med ROLLBACK TRAN annullere en handling.
Eventuelle constraints skal overholdes i selve insert/update-
forespørgslen, fordi triggeren først køres efter selve
forespørgslen. I eksemplet ovenfor måtte jeg bruge pseudoværdien
'#####' i loginfeltet, fordi loginfeltet ikke tillader null-
værdier, og den værdi som triggeren sætter ikke kan ses af den
interne validering der foregår før kørslen af forespørgslen.
--
Jens Gyldenkærne Clausen
MF (medlem af FIDUSO - www.fiduso.dk)
I ovenstående tekst benyttes nyt komma
(rettelser modtages gerne i dk.kultur.sprog)
| |
Stig Johansen (19-11-2002)
| Kommentar Fra : Stig Johansen |
Dato : 19-11-02 12:20 |
|
Hej.
"Jens Gyldenkærne Clausen" <jens@gyros.invalid> skrev i en meddelelse
news:Xns92CB679C9BA3Ejcdmfdk@gyrosmod.dtext.news.tele.dk...
> Hvad er problemet i det? Man kan sagtens lave triggere i T-SQL der
> ændrer værdier i den tabel der er opdateret (såvel som i andre
> tabeller). Her er et eksempel fra skuffen:
<snip en masse>
Rekursivitet?
Som nævnt, bruger jeg ikke triggers, men jeg ved ganske udmærket hvad det
er, og hvordan de bliver (mis)brugt.
mvh
Stig Johansen.
| |
Jens Gyldenkærne Cla~ (19-11-2002)
| Kommentar Fra : Jens Gyldenkærne Cla~ |
Dato : 19-11-02 13:34 |
|
Stig Johansen skrev:
> Rekursivitet?
Nested triggers kan slås fra på serverniveau (jeg ved dog ikke om
det fjerner enhver mulighed for rekursivitet).
> Som nævnt, bruger jeg ikke triggers, men jeg ved ganske
> udmærket hvad det er, og hvordan de bliver (mis)brugt.
Triggers kan nemt misbruges - som mange andre ting. Men der er også
mange ting der kun kan opnås med en trigger, hvis koden skal ligge
direkte på databaseniveau. Jeg har svært ved at se nødvendigheden
af at fraråde enhver brug af triggers under mssql (jeg er ikke
sikker på at det er det du gør, men det ser sådan ud).
--
Jens Gyldenkærne Clausen
MF (medlem af FIDUSO - www.fiduso.dk)
I ovenstående tekst benyttes nyt komma
(rettelser modtages gerne i dk.kultur.sprog)
| |
Stig Johansen (19-11-2002)
| Kommentar Fra : Stig Johansen |
Dato : 19-11-02 13:44 |
|
Hej.
"Jens Gyldenkærne Clausen" <jc@dmf.dk> skrev i en meddelelse
news:Xns92CB89ECC4476jcdmfdk@gyrosmod.dtext.news.tele.dk...
> direkte på databaseniveau. Jeg har svært ved at se nødvendigheden
> af at fraråde enhver brug af triggers under mssql (jeg er ikke
> sikker på at det er det du gør, men det ser sådan ud).
Nej, jeg giver ikke nogen som helst form for råd. Jeg skriver blot hvad jeg
selv gør.
mvh
Stig Johansen.
| |
Stig Johansen (19-11-2002)
| Kommentar Fra : Stig Johansen |
Dato : 19-11-02 13:47 |
|
på rendyrket misbrug af triggers, så prøv at se hvordan Navision opbygger
sine 'sum index felter' på MS SQLServer (med efterfølgende lock-in på M$
SQLServer = tvungen upgrade osv..)
mvh
Stig.
| |
Kristian Damm Jensen (19-11-2002)
| Kommentar Fra : Kristian Damm Jensen |
Dato : 19-11-02 21:46 |
|
Stig Johansen wrote:
>
> Hej.
> "Jens Gyldenkærne Clausen" <jens@gyros.invalid> skrev i en meddelelse
> news:Xns92CB679C9BA3Ejcdmfdk@gyrosmod.dtext.news.tele.dk...
> > Hvad er problemet i det? Man kan sagtens lave triggere i T-SQL der
> > ændrer værdier i den tabel der er opdateret (såvel som i andre
> > tabeller). Her er et eksempel fra skuffen:
> <snip en masse>
>
> Rekursivitet?
Hvad er problemet i rekursion?
Hvis man blot sørger for at den update man laver i sin update-trigger
ikke giver anledning til en fornyet update, så stopper kaldene dér.
> Som nævnt, bruger jeg ikke triggers, men jeg ved ganske udmærket hvad det
> er, og hvordan de bliver (mis)brugt.
Triggers er som alle andre værktøjer: De kan bruges og misbruges.
--
Kristian Damm Jensen | Feed the hungry at www.thehungersite.com
kristian-damm.jensen@cgey.com | Two wrongs doesn't make a right,
ICQ# 146728724 | but three lefts do.
| |
Jørgen Østergaard (19-11-2002)
| Kommentar Fra : Jørgen Østergaard |
Dato : 19-11-02 16:41 |
|
Hej,
----- Original Message -----
From: "Jens Gyldenkærne Clausen" <jens@gyros.invalid>
Newsgroups: dk.edb.database
Sent: Tuesday, November 19, 2002 10:11
Subject: Re: MSSQL triggers, hvordan ændrer man værdierne?
> Stig Johansen skrev:
> > Jeg bruger ikke selv triggers, men jeg er grumme bange for, at
> > der kun er 'after' triggers i M$ SQLServer.
>
> Hvad er problemet i det? Man kan sagtens lave triggere i T-SQL der
> ændrer værdier i den tabel der er opdateret (såvel som i andre
> tabeller). Her er et eksempel fra skuffen:
>
Allerførst: Tak for eksemplet.
Dernæst: de værdier, som jeg ønsker at ændre er dem, som indsættes. F.eks.
ønsker jeg at en bruger ikke skal kunne indsætte tomme strenge i en tabel,
men hvis det sker, skal disse omdannes til NULL's. Til dette formål vil jeg
gerne bruge en trigger.
At dømme efter eksemplet ovenfor (og min MEGET basale viden om Transact-SQL
;) kan jeg altså lave noget i stil med:
---
CREATE TRIGGER nullify_trg
ON nullifyTable
FOR INSERT, UPDATE
AS
BEGIN
UPDATE nullifyTable
SET stringCol=null
WHERE id = @@IDENTITY
AND stringCol=''
END
---
Eller er det totalt forkert? -det beror selvfølgelig på at @@IDENTITY
indeholder den id, som lige er blevet inserted/updated, og at jeg, som Stig
kommenterer, har stringCol='' som garant for at jeg ikke fyrer triggers
rekursivt.
vh. Jørgen
| |
Jørgen Østergaard (19-11-2002)
| Kommentar Fra : Jørgen Østergaard |
Dato : 19-11-02 17:26 |
|
Hej,
efter lidt prøven, kom jeg frem til følgende, der ser ud til at virke:
---
CREATE TRIGGER nullify ON nullifyTable
FOR INSERT, UPDATE
AS
begin
update nullifyTable
set stringCol=null
where id in (select id from inserted where stringCol='')
end
---
Dette ser som sagt ud til at virke, men er det en smart løsning?
vh. Jørgen
| |
Jens Gyldenkærne Cla~ (19-11-2002)
| Kommentar Fra : Jens Gyldenkærne Cla~ |
Dato : 19-11-02 22:35 |
|
Jørgen Østergaard skrev:
> CREATE TRIGGER nullify ON nullifyTable
> FOR INSERT, UPDATE
> AS
> begin
> update nullifyTable
> set stringCol=null
> where id in (select id from inserted where stringCol='')
> end
Der er ikke nogen grund til at finde id-numrene for at opdatere. Du
kan enten blot opdatere enhver række hvor stringCol ='' (og i
princippet være ligeglad med om den netop er blevet indsat eller
det er sket for længe siden), eller også kan du benytte et join
mellem Inserted og din normale tabel:
UPDATE n
SET stringCol = Null
FROM nullifyTable n INNER JOIN Inserted i
ON n.id = i.id
WHERE n.stringCol = ''
(jeg er ikke 100 % sikker på at jeg husker syntaksen for en update
baseret på flere tabeller korrekt - men det kan slås op i BOL hvis
det ikke virker).
> Dette ser som sagt ud til at virke, men er det en smart
> løsning?
Hvis den gør hvad du er ude efter, uden at der er mærkbar
performanceproblemer er det jo fint nok. Det kan gøres mere
effektivt, som jeg har beskrevet ovenfor, men det er ikke sikkert
at det er nødvendigt.
--
Jens Gyldenkærne Clausen
MF (medlem af FIDUSO - www.fiduso.dk)
I ovenstående tekst benyttes nyt komma.
| |
Peter Lykkegaard (19-11-2002)
| Kommentar Fra : Peter Lykkegaard |
Dato : 19-11-02 22:54 |
|
Som svar på skriblerier forfattet af Jens Gyldenkærne Clausen
> Jørgen Østergaard skrev:
>
<X - en trigger>
>> Dette ser som sagt ud til at virke, men er det en smart
>> løsning?
>
> Hvis den gør hvad du er ude efter, uden at der er mærkbar
> performanceproblemer er det jo fint nok. Det kan gøres mere
> effektivt, som jeg har beskrevet ovenfor, men det er ikke sikkert
> at det er nødvendigt.
Jeg blander mig lige
Jeg sidder bare og tænker på om det ikke er bedre at tage højde en tom
streng andre steder
Fx i den insert/update sætning der indsætter dataene i tabellen?
Det kan være at denne fremgangsmåde ikke er mulig i forbindelse med Jørgens
applikation?
mvh/Peter Lykkegaard
| |
Jørgen Østergaard (20-11-2002)
| Kommentar Fra : Jørgen Østergaard |
Dato : 20-11-02 00:04 |
|
Hej Peter,
"Peter Lykkegaard" <polonline@hotmail.com> wrote in message
news:arec2u$n8q$1@sunsite.dk...
> Jeg sidder bare og tænker på om det ikke er bedre at tage højde en tom
> streng andre steder
> Fx i den insert/update sætning der indsætter dataene i tabellen?
Jo, det er det som du også selv kommer ind på, hvis du kender dem, der
indsætter, herunder indkapsler dine tabeller i et API eller lign.
Det kan jeg desværre ikke gøre på en umiddelbart nem måde, da jeg får brug
for at kunne tilgå data fra flere forskellige platforme, hvoraf nogle af dem
kun har eksperimentel/alpha/beta support for procedurekald til en MSSQL
server... Så jeg styrer den simpleste dataintegritet så tæt på mine data som
muligt.
Det er den sædvanlige historie om hvem der har tillid til hvem, og i mit
tilfælde stoles der ikke så meget på dem der er udenfor databasen ;)...
vh. Jørgen
| |
Jørgen Østergaard (19-11-2002)
| Kommentar Fra : Jørgen Østergaard |
Dato : 19-11-02 23:58 |
|
Hej Jens,
"Jens Gyldenkærne Clausen" <jens@gyros.invalid> wrote in message
news:Xns92CBE5B211839jcdmfdk@gyrosmod.cybercity.dk...
> Der er ikke nogen grund til at finde id-numrene for at opdatere. Du
> kan enten blot opdatere enhver række hvor stringCol ='' (og i
> princippet være ligeglad med om den netop er blevet indsat eller
> det er sket for længe siden), eller også kan du benytte et join
> mellem Inserted og din normale tabel:
>
> UPDATE n
> SET stringCol = Null
> FROM nullifyTable n INNER JOIN Inserted i
> ON n.id = i.id
> WHERE n.stringCol = ''
Ja, join'en er nok mere effektiv end det jeg har nu, men jeg tror ikke at en
full-table scan på tomme tekststrenge er effektiv (din første løsning), men
den rammer bredere ;).
Tak for dit svar -det var meget nyttigt!
vh. Jørgen
| |
Jørgen Østergaard (20-11-2002)
| Kommentar Fra : Jørgen Østergaard |
Dato : 20-11-02 00:09 |
|
Hej Jens,
"Jens Gyldenkærne Clausen" <jens@gyros.invalid> wrote in message
news:Xns92CBE5B211839jcdmfdk@gyrosmod.cybercity.dk...
> Der er ikke nogen grund til at finde id-numrene for at opdatere. Du
> kan enten blot opdatere enhver række hvor stringCol ='' (og i
> princippet være ligeglad med om den netop er blevet indsat eller
> det er sket for længe siden), eller også kan du benytte et join
> mellem Inserted og din normale tabel:
>
> UPDATE n
> SET stringCol = Null
> FROM nullifyTable n INNER JOIN Inserted i
> ON n.id = i.id
> WHERE n.stringCol = ''
Ja, join'en er nok mere effektiv end det jeg har nu, men jeg tror ikke at en
full-table scan på tomme tekststrenge er effektiv (din første løsning), men
den rammer bredere ;).
Ved du forøvrigt om det har nogen indflydelse på dine indexes, hvis der
indgår Null værdier i de(n) kolonne, som indekseres?
Tak for dit svar -det var meget nyttigt!
vh. Jørgen
| |
Jens Gyldenkærne Cla~ (20-11-2002)
| Kommentar Fra : Jens Gyldenkærne Cla~ |
Dato : 20-11-02 01:03 |
|
Jørgen Østergaard skrev:
> Ja, join'en er nok mere effektiv end det jeg har nu, men jeg
> tror ikke at en full-table scan på tomme tekststrenge er
> effektiv (din første løsning), men den rammer bredere ;).
Nu er jeg bestemt ikke velbefaren i hvilke kriterier der udløser en
tablescan, men hvis rækken er indekseret behøver en søgning på ''
vel ikke at bruge scan? Er det ikke kun nødvendigt med LIKE-
forespørgsler?
Men hvis der ikke er indeks på det felt der skal erstattes er det
nok en tablescan der skal til.
Under alle omstændigheder er joinmodellen utvivlsomt bedre.
> Ved du forøvrigt om det har nogen indflydelse på dine indexes,
> hvis der indgår Null værdier i de(n) kolonne, som indekseres?
Ingen anelse.
--
Jens Gyldenkærne Clausen
MF (medlem af FIDUSO - www.fiduso.dk)
I ovenstående tekst benyttes nyt komma.
| |
|
|