Avatar billede fennec Nybegynder
10. januar 2007 - 13:37 Der er 10 kommentarer og
1 løsning

Problem med select @@identity

Jeg har et lille problem, som jeg har fundet et workaround på, men vil lige høre om nogen kender til det specifikke problem.

Jeg bruger en MS-SQL server.

Jeg har 2 tabeller som jeg indsætter data i og trækker ID'et ud.

oConn.execute("insert into aaTest(test) values('hgh')")
set oRs = oConn.execute("select @@identity")
Response.write oRs(0) &"**<br>"

oConn.execute("insert into bbTest(test) values('hgh')")
set oRs = oConn.execute("select @@identity")
Response.write oRs(0) &"**<br>"

Problemet er at det giver mig resultatet:
31**
**

Altså får jeg ikke ID'et fra bbTest ud.

Jeg prøvede så at sætte oRs til nothing:
oConn.execute("insert into aaTest(test) values('hgh')")
set oRs = nothing
set oRs = oConn.execute("select @@identity")
Response.write oRs(0) &"**<br>"

oConn.execute("insert into bbTest(test) values('hgh')")
set oRs = nothing
set oRs = oConn.execute("select @@identity")
Response.write oRs(0) &"**<br>"

Det giver mig resultatet:
32**
32**

Altså får jeg det første ID ud med begge "select @@identity". Rent tilfældig mens jeg roede med problemet ko jeg til at sætte nothing før indsættelsen:
set oRs = nothing
oConn.execute("insert into aaTest(test) values('hgh')")
set oRs = oConn.execute("select @@identity")
Response.write oRs(0) &"**<br>"

set oRs = nothing
oConn.execute("insert into bbTest(test) values('hgh')")
set oRs = oConn.execute("select @@identity")
Response.write oRs(0) &"**<br>"

Det gav mig resultatet:
33**
29**

Hvilket er det rigtige. Er der nogen der kender til denne problematik, og en bedre løsning på problemet??

Man kan jo nemt komme til at glemme at sætte "set oRs = nothing" foran indsættelsen.
Avatar billede softspot Forsker
10. januar 2007 - 13:47 #1
Jeg ved ikke om det virker, men prøv at kalde oRs.Close efter du har hentet det nye id ud af oRs.

Jeg tror det er fordi oRs holder fast i forbindelsen når det er åben og at du derfor får det samme id returneret når du kalder execute (noget med at der kun kan være en aktiv cursor på en forbindelse ad gangen).

Altså skulle jeg mene at dette fungerede:

oConn.execute("insert into aaTest(test) values('hgh')")
set oRs = oConn.execute("select @@identity")
Response.write oRs(0) &"**<br>"
oRs.Close

oConn.execute("insert into bbTest(test) values('hgh')")
set oRs = oConn.execute("select @@identity")
Response.write oRs(0) &"**<br>"
oRs.Close

Det er i øvrigt altid en god idé at lukke og slukke efter sig, når man arbejder med databaser, dvs. både kalde close på recordsettet og forbindelsen, samt sætte objektreferencerne til nothing, så du er sikker på at de bliver frigivet med det samme (det har noget med låsning af resurser at gøre og hvor lang tid du gør det).
Avatar billede fennec Nybegynder
10. januar 2007 - 14:04 #2
Jeg er enig med dig i at det er en god ide at lukke forbindelsen, og det virker også som du har skrevet det. Men jeg prøvede at ændre lidt på koden:

oConn.execute("insert into aaTest(test) values('hgh')")
set oRs = oConn.execute("select @@identity from aaTest")
Response.write oRs(0) &"**<br>"

oConn.execute("insert into bbTest(test) values('hgh')")
oRs.close
set oRs = oConn.execute("select @@identity from bbTest")
Response.write oRs(0) &"**<br>"
oRs.close

Dette giver mig det første ID 2 gange:
47**
47**
Avatar billede slash Nybegynder
10. januar 2007 - 14:07 #3
du skal bruge SCOPE_IDENTITY() istedet for @identity. @identity returnerer indsat ID globalt for DB så at sige, mens scope_identity returnerer for aktuel session / insert
Avatar billede softspot Forsker
10. januar 2007 - 14:15 #4
slash >> det synes jeg da ikke giver mening, da fennec's eksempel så burde returnere det sidste id databasen har genereret og det er jo ikke tilfældet - tvært imod.

fennec >> Ja, og det synes jeg bare underbygger min teori om at sålænge recordsettet er åben, holder den fast i nogle resurser i databasen (via sin cursor iflg. min opfattelse) og du får derfor ikke den nye id tilbage.

Jeg her personligt gjort det til en vane at lukke mine recordsets hurtigst muligt efter jeg er færdig med dem, så slipper jeg for at bøvle med problemer af denne slags. Der er naturligvis situationer hvor jeg er nød til at håndtere et behov for at loope og måske opdatere databasen i dette loop, men det prøver jeg at holde på et minimum, da det er kilde til denne slags problemstillinger...
Avatar billede fennec Nybegynder
10. januar 2007 - 14:18 #5
oConn.execute("insert into aaTest(test) values('hgh')")
set oRs = oConn.execute("select SCOPE_IDENTITY() from aaTest")
Response.write oRs(0) &"**<br>"

oConn.execute("insert into bbTest(test) values('hgh')")
set oRs = oConn.execute("select SCOPE_IDENTITY() from bbTest")
Response.write oRs(0) &"**<br>"

Har det samme problem som @@identity. Den returnere kun det første ID:
50**
**

Desuden har vi ingen Triggers på tabellerne så @@identity er ok at bruge. Vi kører også noget multidatabase så kunderne selv kan vælge at gøre Access eller MS-SQL (senere også MySQL). Det er derfor vigtitg at sql sætningerne er crossDB, og mig bekendt virker scope ikke i Access (har dog ikke afprøvet det)

Softspot >>
Jeg er enig, synes bare det er en mærkelig situation.

oConn.execute("insert into bbTest(test) values('hgh')")
oRs.close
set oRs = oConn.execute("select @@identity from bbTest")

og
oRs.close
oConn.execute("insert into bbTest(test) values('hgh')")
set oRs = oConn.execute("select @@identity from bbTest")

Burde ikke have forskellig resultater, hvad de dog har. Men point må gå til dig.
Avatar billede softspot Forsker
10. januar 2007 - 14:24 #6
Nej, det er ikke altid at MickeySofts implementeringer giver mening på overfladen, men det er jo det der gør det så interessant at være udvikler - hvad har de mon fundet på af kringelkroge denne gang ;D

Anyway! Seriøst, så synes jeg MS' arkitekturer er rimelig konsistente og jeg bøjer mig i støvet for deres evne til at få tingene skruet nogenlunde fornuftigt og forståeligt sammen - det gælder dels arkitekturer men også deres evne til at dokumentere på en konsistent måde.

Velbekomme :)
Avatar billede softspot Forsker
10. januar 2007 - 14:28 #7
Tak for point :)
Avatar billede cpufan Juniormester
10. januar 2007 - 15:18 #8
oConn.execute("insert into aaTest(test) values('hgh')")
set oRs = oConn.execute("select SCOPE_IDENTITY() from aaTest")
Response.write oRs(0) &"**<br>"

oConn.execute("insert into bbTest(test) values('hgh')")
set nRs = oConn.execute("select SCOPE_IDENTITY() from bbTest")
Response.write nRs(0) &"**<br>"

giver vel en ny.

og så læste mit "korrekturøje"  citat: Rent tilfældig mens jeg roede med......

så har man hørt det med.... ude at ro med problemerne :-)
Avatar billede cpufan Juniormester
10. januar 2007 - 15:22 #9
skulle så ha' været:

oConn.execute("insert into aaTest(test) values('hgh')")
set oRs = oConn.execute("select @@identity")
Response.write oRs(0) &"**<br>"

oConn.execute("insert into bbTest(test) values('hgh')")
set nRs = oConn.execute("select @@identity")
Response.write nRs(0) &"**<br>"


fik kopieret det forkerte    "slag til mig"
Avatar billede fennec Nybegynder
10. januar 2007 - 15:23 #10
cpufan >>
Nope. Den kode returnere også:
53**
**

Og hvad er der nu galt med at tage sine problemer ud i en båd på havet :o)
Avatar billede fennec Nybegynder
10. januar 2007 - 15:24 #11
Den anden virker heller ikke.
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester