Avatar billede lytzen Nybegynder
27. oktober 2000 - 20:09 Der er 15 kommentarer og
1 løsning

returnering af det sidst indsatte

Følgende tabel arbejder jeg med:

Create Table KundeOrdre (
  KunOrdNr int identity(40000000,1),
  SamletPris decimal NOT NULL,
  Rabat decimal DEFAULT 0,
  Betaling decimal DEFAULT 0,
  AnsatNr int,
  KundeNr int,

  Primary Key (KunOrdNr),

  foreign key (AnsatNr) references Ansat,
  foreign key (KundeNr) references Kunde,

  check (SamletPris >0),
  check (KunOrdNr < 50000000)
)

Når jeg nu fra mit Delphi-program opretter en ny KundeOrdre så genererer databasen automatisk et unikt nummer (KundeOrdNr). Det nummer skal jeg have fat i på en eller anden måde. Jeg kan ikke lede databasen igennem med en ansat og en kunde, for der eksisterer en masse kundeordrer med disse to personer.

Er der en måde hvorpå man kan få returneret KunOrdNr lige efter jeg har oprettet kundeordren ?
Avatar billede ortrak Nybegynder
27. oktober 2000 - 20:17 #1
1. Du åbner et recordset(lad os kalde det RS)\". 2. Du indsætter dine data
3. Du skriver RS.Update
4. Dit netop oprettede KunOrdNr kan du så hente ved at skrive: enellerandenvariabel = RS(\"KunOrdNr\").
5. Derefter lukker og slukker du for recordset + connection


/ortrak
Avatar billede lytzen Nybegynder
27. oktober 2000 - 20:48 #2
Hmm, forstår jeg desværre ikke.
Når jeg opretter en Kundeordretabel, gør jeg det ved:

Begin Transaction
insert into KundeOrdre values (bla bla bla)
Commit

Hvad er det så jeg skal skrive hvis jeg vil have det genererede nummer tilbage ?
Avatar billede farouche Nybegynder
27. oktober 2000 - 22:56 #3
Prøv følgende :

begin transaction tablock

insert into kundeordre values (100, 0, 50, 10000000, 20000000)

select KunOrdNr from kundeordre
where kunordnr = (select count(*) from Kundeordre) + 39999999

commit


Det virker
Avatar billede tigerdyr Nybegynder
27. oktober 2000 - 22:58 #4
Spøjs identity seed du holder dig...

Du kan evt. lave det med en Stored Procedure og så hente det sidste nye identity (dvs. dit nye NunOrdNr) med @@Identity...

CREATE PROCEDURE SP_InsertOrder
  @Pris Decimal,
  @Rabat Decimal,
  @Betaling Decimal,
  @AnsatNr Int,
  @KundeNr Int,
  @Outvar Int = 0 OUTPUT
  WITH RECOMPILE
  AS
  INSERT INTO KundeOrdre VALUES (@Pris, @Rabat, @Betaling, @AnsatNr, @KundeNr)
  SELECT @Outvar = @@IDENTITY
Avatar billede tigerdyr Nybegynder
27. oktober 2000 - 22:59 #5
når du eksekverer SP\'en vil den returnere sidst generede ID
Avatar billede moa Nybegynder
28. oktober 2000 - 10:37 #6
Farouche : Holder dit svar virkelig vand?? Hvad hvis der er blevet slettet en kundeordre? - Derudover mener jeg ikke at der er nogen garanti for at identity er 100% fortløbende! - Enkelte numre kan nemlig springes over ifm. transaction-rollbacks og servernedbrud!

Din måde at løse det på baserer sig så vidt jeg kan se på en \"assumption\" (ja, undskyld, jeg kan ikke lige komme på det tilsvarende danske ord ;-)), der ikke altid holder.

Tigerdyrs løsning, er da så vidt jeg ved, den anbefalede?! - Og det behøves vel ikke absolut at være iform af en stored procedure? - Hvis man bare indkapsler det hele i en transaktion skulle det vel gå?:

Begin Transaction
insert into KundeOrdre values (bla bla bla)
select @@Identity
Commit

/moa
Avatar billede farouche Nybegynder
28. oktober 2000 - 12:58 #7
Du har nok ret

Det er et problem med sletning, da antallet ikke vil passe.

Men hvis man ikke sletter fra tabellen, kan man så ikke nogenlunde regne med det ?

Kan du ikke give et helt konkret statement, som ikke er en stored procedure da jeg ikke har kendskab til at arbejde med @.
Avatar billede moa Nybegynder
28. oktober 2000 - 13:10 #8
\"Men hvis man ikke sletter fra tabellen, kan man så ikke nogenlunde regne med det?\"

Jo, under forbehold af at de ting jeg skrev om rollback\'s og servercrashes ikke opstår?! (der er sikkert også andre tilfælde, som jeg overlader til nogen der er klogere end mig at svare på ;-))

Konkret statement:
Hvis vi tager udgangspunkt i dit svar fra igår, burde det kunne modificeres en smule så det opfylder det tilsigtede:

begin transaction tablock

insert into kundeordre values (100, 0, 50, 10000000, 20000000)

select @@Identity from KundeOrdre
commit

Nu sidder jeg desværre ikke lige i nærheden af en DB idag, så jeg kan ikke lige teste det, men det burde være syntaksen ihvertfald i MS-SQL.

Men jeg er faktisk ikke klar over om det skal pakkes ind i en Stored Procedure som Tigerdyr foreslår?

/moa
Avatar billede farouche Nybegynder
28. oktober 2000 - 13:23 #9
Du har ret

det vil nok være noget usikkert.

Men nok den eneste løsning med \"standard\" SQL

Din løsning virker faktisk, hvis jeg laver en select distinct istedet, da den ellers returnerer @@identity lige så mange gange som der er records i DB\'en

Nu burde Tigerdyr jo egentlig få mine point, så hvis du er der ude, så smæk lige en kommentar ind, så laver jeg et spørgsmål til dig med de 15 point.

Ret skal være ret
Avatar billede farouche Nybegynder
28. oktober 2000 - 13:25 #10
En anden ting er :

Hvad betyder @@Identity egentlig ?

Jeg har somsagt ingen kendskab til det, men er nu blevet ret nysgerrig.
Avatar billede tigerdyr Nybegynder
28. oktober 2000 - 13:27 #11
Sejt nok :o)

Og nej, det er IKKE nødvendigt at pakke @@Identity ind i en SP, men det anbefales for at sikre at der ikke startes en anden INSERT op inden @@Identity er aflæst :o)

@@IDENTITY = Global variabel i SQL Serveren, der ALTID opdateres til at indeholde det sidste nye ID fra en IDENTITY kolonne.
Avatar billede moa Nybegynder
28. oktober 2000 - 13:43 #12
Tigerdyr: Hvis man nu pakker insert og aflæsning af @@identity ind i en transaktion så kan der vel ikke starte en ny insert op der \"piller\" ved @@identity inden man har aflæst den??

Og så lige et totalt off-track spg: Er en SP atomar?
Avatar billede tigerdyr Nybegynder
28. oktober 2000 - 14:01 #13
atomar ?? der tabte du mig...

Tjaa...logisk set burde en Transaction fungere ganske som en SP og indkapsle eksekveringen, men om det altid er sikkert tør jeg ikke sige!
Avatar billede moa Nybegynder
28. oktober 2000 - 14:07 #14
Atomar: Altså uden at andre queries til DB kan nå at udføres! Eksempel med udgangspunkt i dit svar tidligere:

CREATE PROCEDURE SP_InsertOrder
  @Pris Decimal,
  @Rabat Decimal,
  @Betaling Decimal,
  @AnsatNr Int,
  @KundeNr Int,
  @Outvar Int = 0 OUTPUT
  WITH RECOMPILE
  AS
  INSERT INTO KundeOrdre VALUES (@Pris, @Rabat, @Betaling, @AnsatNr, @KundeNr)
  SELECT @Outvar = @@IDENTITY

Altså udføres de to statements i denne SP (insert\'en og select\'en) uden at andre kan have lavet noget imens? - Jeg er selvfølgelig godt klar over at de udføres meget hurtigt efter hinanden, så det er nok kun i teorien at de kan give problemer?!
Avatar billede tigerdyr Nybegynder
28. oktober 2000 - 14:45 #15
Officielt set (dvs. MS synspunkt) er at når 1 eller flere statements er pakket ind i en SP, vil de blive eksekveret så hurtigt efter hinanden (og med fornuftige låse) at ingen andre statements kan nå/få lov at ændre noget, før SP\'en er færdig
Avatar billede tigerdyr Nybegynder
28. oktober 2000 - 14:46 #16
Synspunktet har iøvrigt altid holdt hos mig :o)
Jeg kører alt med Views og SP\'s og indtil videre har jeg ikke oplevet nogle fejl med updates osv. (selv om jeg i nogle af dem laver op mod 7 eller 8 queries i en SP)
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
Computerworld tilbyder specialiserede kurser i database-management

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