Gå til innhold

Microsoft SQL Server Management Studio Express [Omskrevet]


Anbefalte innlegg

Hei!

 

Jeg kan grunnleggende ting om databaser, men har aldri jobbet i noe annet enn Access. Altså går jeg meg _noe_ vill i det programmet jeg nå skulle ha gjort en bitteliten endring i. Databasen er der, men skulle bare ha gjort EN liten sak.

 

Dette dreier seg om en artikkeltabell. Se for deg to felter, Price1 og Price2. Ønsker å sette det slik at når skriver inn en verdi i Price1 så skal denne automatisk "dupliseres" til Price2.

 

EDIT:

OK, jeg har fått hjelp fra noen andre enn folk fra forumet. Ikke bare litt hjelp, men MYE hjelp og har kommet frem til følgende trigger som nå har blitt nesten korrekt:

 

USE [Databasenavn]
GO
/****** Object:  Trigger [Databasenavn].[Triggernavn]	Script Date: 01/19/2008 05:31:23 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER trigger [Databasenavn].[Triggernavn] on [Databasenavn].[Tabellnavn] for update as 
if Update(Price1) 
begin 
update [Databasenavn].[Tabellnavn] set [Databasenavn].[Tabellnavn].[Price2] = [Databasenavn].[Tabellnavn].[Price1]
from [Databasenavn].[Tabellnavn]
inner join inserted
on inserted.[Primærnøkkel] = [Databasenavn].[Tabellnavn].[Primærnøkkel]
end

Kun en primærnøkkel eksisterer i tabellen.

 

Denne løser nå følgende riktig:

 

1. Når lagrer skjemaet så settes price2 lik price1. Det er jo det grunnleggende.

2. Det er kun artikkelen som blir lagret hvor price2 settes lik price1. Også greit å få til da _noe_ unødvendig å lagre price2 for x-antall tusen artikkler når det holder med en...

 

Så er det punkt tre, heldigvis det minst vesentlige, som vi ikke har fått til foreløpig:

3. Kun når price1 har fått endret verdi skal price2 settes lik price1. Hvis f.eks. endrer artikkelnavnet og lagrer skal ikke dette påvirke price2. Slik at manuelt kan overstyre price2 til ulik price1, men så fort man da gjør en endring på price1 "forsvinner overstyring" og price2 blir igjen lik price1 (inntil man eventuelt velger å manuelt overstyre på nytt).

 

Kortversjon: Kun sette price2 lik price1 når price1 har blitt endret, og ikke når noe annet på artikkelen har blitt lagret.

 

Noen som kan komme med forslag til hvordan skal endre koden for å få til punkt tre?

 

- Amund

Endret av amundsf
Lenke til kommentar
Videoannonse
Annonse

ALTER trigger [Databasenavn].[Triggernavn] on [Databasenavn].[Tabellnavn] for update as 
if Update(Price1) 
begin 
update [Databasenavn].[Tabellnavn] set [Databasenavn].[Tabellnavn].[Price2] = [Databasenavn].[Tabellnavn].[Price1]
from [Databasenavn].[Tabellnavn]
inner join inserted
on inserted.[Primærnøkkel] = [Databasenavn].[Tabellnavn].[Primærnøkkel]
inner join deleted on deleted.[Primærnøkkel] = [Databasenavn].[Tabellnavn].[Primærnøkkel]
where deleted.price1<>inserted.price1
end

 

Denne forutsetter at price1 ikke kan ha NULL verdi.

deleted.price1<>inserted.price1 vil ikke fungere hvis inserted.price1 er NULL eller deleted.price1 er NULL.

Lenke til kommentar

Den så ut til å fungere helt alderes strålende! :-) Takker så mye!

 

For det første, den rettet i alle fall:

Nå settes price2 = price1 kun år det er price 1 som får endret verdi. Veldig bra! :-)

 

Og når det gjelder det med at den ikke ville fungere hvis price1 eller price2 er NULL: Ser fakatisk ikke ut til å være noe problem! Jeg kan sette både price1 og price2 (begge, eller kun en av dem) og triggeren fungerer alikevel :)

 

 

Mulig jeg har missforstått noe (forklar i så fall gjerne bedre), men ut fra det jeg har forstått/testet så ser det ikke ut til å være noe problem med NULL. For antar at NULL i databasen blir det samme som 0 inne i økonomiprogrammet?

 

 

- Amund

Lenke til kommentar

Selv om programmet viser 0 for NULL (noe jeg mener er feil) så betyr ikke det at WHERE inserted.price1<>deleted.price1 vil fungere hvis price1 er eller setter til NULL. NULL verdier håndteres nemlig litt spesielt i sammelikninger. Når du sammelikner to verdier så forventer du at uttrykket returnerer TRUE eller FALSE. Eks. 1=1 er true, 1=2 er false, 1<>1 er false, 1<>2 er true. 1=NULL skulle en tro ga false, men det gjør det ikke, det gir NOTHING. Alle sammenlikninger med NULL vil returnere NOTHING. Eneste måte å sjekke mot NULL verdier er ved å bruke IS operatoren som i price1 is null, eller ved å sette SET ANSI_NULLS OFF; da vil NULL=NULL gi true og 1=NULL gi false.

Lenke til kommentar

Jeg forstår noe av det du skriver, men må innrømme at jeg ikke forstår det 100%.

 

MEN: Så lenge den ser ut til å fungere som ønsket så får man vel si seg fornøyd :)

 

Testa også nå med å opprette en ny artikkel, og triggeren fungerer da også.

 

Så hvis ingen har noe "nytt å melde" så tror je at jeg sier meg frnøyd jeg :)

 

- Amund

Lenke til kommentar

Poenget mitt er st hvis price1 har verdien NULL og du endrer den til 10 så vil ikke price2 bli oppdatert til 10 fordi uttrykket inserted.price1<>deleted.price1 ikke gir true.

 

Jeg vill sjekket skjemaet til tabellen for å finne ut om price1 er nullable. Hvis den er det så bør du håndtere dette i WHERE uttrykket. Den enkleste måten er å bruke ISNULL() funksjonen. HVis vi kan anta at price1 ikke kan være negativ så kan du endre uttykket til

 

where isnull(deleted.price1,-1)<>isnull(inserted.price1,-1)

Lenke til kommentar
Poenget mitt er st hvis price1 har verdien NULL og du endrer den til 10 så vil ikke price2 bli oppdatert til 10 fordi uttrykket inserted.price1<>deleted.price1 ikke gir true.

Det hovedpoenget tok jeg sånn ca. ja :thumbup:

 

Jeg vill sjekket skjemaet til tabellen for å finne ut om price1 er nullable.

Slik det ser ut for meg så er den ikke nullable, så lenge man legger inn dataene fra Visma (hva som skjer hvis legger direkte i databasen, det veit jeg ikke, men blir jo uansett aldri gjort).

 

Men OK, la oss forsøke å teste.

Hvis den er det så bør du håndtere dette i WHERE uttrykket. Den enkleste måten er å bruke ISNULL() funksjonen. HVis vi kan anta at price1 ikke kan være negativ så kan du endre uttykket til

 

where isnull(deleted.price1,-1)<>isnull(inserted.price1,-1)

Hvor skal jeg legge inn denne hen? Er det en test? Skal den legges inn som "New Query"? Eller skal den inn i triggerkoden? Eller et annet sted?

 

Jeg kan dessverre alt for lite om koding, så trenger det meste med tesje...

 

Takker for hjelpen og tålmodigheten!

 

- Amund

Endret av amundsf
Lenke til kommentar

Hvis kolonnen ikke er nullable så fungere triggeren fint som den er. Er den derimot nullable så bytter du ut WHERE delen i triggeren med WHERE delen i min siste post slik:

 

ALTER trigger [Databasenavn].[Triggernavn] on [Databasenavn].[Tabellnavn] for update as 
if Update(Price1) 
begin 
update [Databasenavn].[Tabellnavn] set [Databasenavn].[Tabellnavn].[Price2] = [Databasenavn].[Tabellnavn].[Price1]
from [Databasenavn].[Tabellnavn]
inner join inserted
on inserted.[Primærnøkkel] = [Databasenavn].[Tabellnavn].[Primærnøkkel]
inner join deleted on deleted.[Primærnøkkel] = [Databasenavn].[Tabellnavn].[Primærnøkkel]
where isnull(deleted.price1,-1)<>isnull(inserted.price1,-1)
end

 

Men som sagt, det er ikke nødvendig å gjøre dette hvis price1 ikke er nullable.

 

Kjør følgende og finn raden for price1 og se om det står true eller false i kolonnen IsNullable. Er verdie True så endrer du triggeren, hvis verdien er False så lar du den være.

sp_help 'tabellnavn'

Lenke til kommentar
Kjør følgende og finn raden for price1 og se om det står true eller false i kolonnen IsNullable. Er verdie True så endrer du triggeren, hvis verdien er False så lar du den være.

sp_help 'tabellnavn'

Spørsmålet for meg blir jo da hvor skriver jeg den koden? I new query? Prøvde det, men det var ikke velykket...

 

Har imidlertid benyttet "mappestrukturen" og funnet tabellen og gått på edit, der står det:

 

[Price1] [float] NULL

Betyr det at den er nullable?

 

- Amund

Endret av amundsf
Lenke til kommentar

Det holder da at jeg bytter følgende linje ikke sant?

where isnull(deleted.price1,-1)<>isnull(inserted.price1,-1)

Eller har jeg oversett noen andre endringer?

 

Er så mye jobb å bytte om fra generelle navn til de egentlige i databasen ;)

 

Takker for hjelpen!

 

- Amund

Endret av amundsf
Lenke til kommentar

Har testet litt og noe er feil med den nye koden. Når oppretter en ny artikkel så er price2 sin verdi ikke 0 (som den jo burde ha vært), men "Objekt ID'en" til Price1. Inne i Visma går alt på Object ID'er, og price2 settes nå altså lik Objekt ID'en til Price1. Det gir jo ikke så mye mening....

 

OBS! Så fort registrerer en verdi i Price1 så endres Price2, så det fungerer. Men så lenge Price1 er 0 er det altså noe feil.

 

- Amund

Lenke til kommentar

Det er bare WHERE delen som må endres.

 

Angående feilen ved ved insert av ny rader: Triggeren er definert til KUN å kjøre ved UPDATE. Hvis du vil at triggeren skal kjøres ved INSERT også så må du endre til følgende (endring i bold):

ALTER trigger [Databasenavn].[Triggernavn] on [Databasenavn].[Tabellnavn] for insert,update as

if Update(Price1)

begin

update [Databasenavn].[Tabellnavn] set [Databasenavn].[Tabellnavn].[Price2] = [Databasenavn].[Tabellnavn].[Price1]

from [Databasenavn].[Tabellnavn]

inner join inserted

on inserted.[Primærnøkkel] = [Databasenavn].[Tabellnavn].[Primærnøkkel]

inner join deleted on deleted.[Primærnøkkel] = [Databasenavn].[Tabellnavn].[Primærnøkkel]

where isnull(deleted.price1,-1)<>isnull(inserted.price1,-1)

end

 

At price2 får verdien til ObjectId må ligge i INSERT statementet. Antar det noe feil der som du må se på. Post gjerne SQLen her hvis du trenger hjelp.

Lenke til kommentar
Det er bare WHERE delen som må endres.

 

Angående feilen ved ved insert av ny rader: Triggeren er definert til KUN å kjøre ved UPDATE.

Burde ikke det egentlig holde? Fordi, når setter inn en ny rad (legger til en ny artikkel) så har jo begge feltene som standardverdi 0, altså er de like. For å være pirkete kunne man vel sikkert satt triggeren til å kjøre ved ny rad også, men er vel egentlig ikke nødvendig?

 

Så lenge den fungerer når setter inn en verdi for price1 etter at en ny rad er satt inn burde jo det være nok. Og det fungerer jo.... :)

 

At price2 får verdien til ObjectId må ligge i INSERT statementet. Antar det noe feil der som du må se på. Post gjerne SQLen her hvis du trenger hjelp.

SQLen følger nedenfor. Jeg gidder ikke endre alle feltnavnene her, så noen små definisjoner først:

 

FullPrice_Update = Triggernavn

Article = Tabellnavn

PurchasePrice = Price1

FullCost = Price2

og at ArticleNo = primærnøkkel antar jeg at er enkelt å forstå.

 

Eneste jeg har gjort om til et "generelt navn" er databasenavnet. Fordi databasenavnet inneholder firmanavnet og ser ikke noe poeng i å offentliggjøre det. Ikke at det hadde vært noe farlig, men...

 

ALTER trigger [Databasenavn].[FullPrice_Update] on [Databasenavn].[Article] for update as 
if Update(PurchasePrice) 
begin 
update [Databasenavn].[Article] set [Databasenavn].[Article].[FullCost] = [Databasenavn].[Article].[PurchasePrice]
from [Databasenavn].[Article]
inner join inserted
on inserted.[ArticleNo] = [Databasenavn].[Article].[ArticleNo]
inner join deleted on deleted.[ArticleNo] = [Databasenavn].[Article].[ArticleNo]
where isnull(deleted.PurchasePrice,-1)<>isnull(inserted.PurchasePrice,-1)
end

 

- Amund

Endret av amundsf
Lenke til kommentar

Jeg kan dessverre ikke finne ut hvorfor price2 blir "objectId" ved INSERT. Til det har jeg for lite info, og det kan være maaaaange ting som forårsaker feilen.

Mener du å si at det fungerte med den opprinnelige triggeren?

Jeg ville begynt med SQL Server Profiler for å finne ut hva som skjer når en ny rad registreres.

Lenke til kommentar
Mener du å si at det fungerte med den opprinnelige triggeren?

Det var det jeg trodde, men det viste seg å være feil... Har testet følgende nå:

 

1. Koden fra i går (tar ikke høyde for NULL), ikke med insert i første linja.

2. Koden fra i går (tar ikke høyde for NULL), med insert i første linja.

3. Koden fra i dag (tar høyde for NULL), ikke insert i første linja.

4. Koden fra i dag (tar høyde for NULL), med insert i første linja.

 

Alle med samme feil.

 

Jeg kan dessverre ikke finne ut hvorfor price2 blir "objectId" ved INSERT. Til det har jeg for lite info, og det kan være maaaaange ting som forårsaker feilen.

 

Jeg ville begynt med SQL Server Profiler for å finne ut hva som skjer når en ny rad registreres.

Kunne ikke vært en løsning å lagt en egen regel på at hvis price1 er 0 (og/eller NULL) så skal price2 også få verdi 0? For å overstyre på en måte mener jeg... Men jeg veit selvsagt ikke om det er løsbart.

 

- Amund

Lenke til kommentar
Kunne ikke vært en løsning å lagt en egen regel på at hvis price1 er 0 (og/eller NULL) så skal price2 også få verdi 0? For å overstyre på en måte mener jeg... Men jeg veit selvsagt ikke om det er løsbart.

 

Den eneste riktige måten å lese dette på er å finne ut hvorfor price2 får verdien til "objectId". Dette skjer nemlig ikke av seg selv. Jeg vil påstå at det er bedre å finne roten til problemet enn å lae en fix som overkriver verdien til evt. buggete kode.

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...