Thema: Delphi Auto-Insertwert abfragen

Einzelnen Beitrag anzeigen

Benutzerbild von Jelly
Jelly

Registriert seit: 11. Apr 2003
Ort: Moestroff (Luxemburg)
3.741 Beiträge
 
Delphi 2007 Professional
 
#6

Re: Auto-Insertwert abfragen

  Alt 1. Okt 2008, 14:09
Einfach nach dem Post den Wert in einer getrennten Abfrage auslesen.
select Scope_Identity() (Scope_Identity() ist besser geeignet weil @@identity den wirklich letzten Auto Wert der aktuellen Session zurückgibt. Führt ein Insert in eine Tabelle einen InsertTrigger aus, der selbst wieder in eine andere Tabelle mit Autoinc Wert was einfügt, so gibt dir @@identity diesen letzten Wert zurück.

Angst um parallelen Zugriff muss man übrigens nicht haben, weil dieses Ganze Identity Auslesen Session bezogen ist, sich also auf eine Connection bezieht.

Persönlich allerdings bevorzuge ich das Reservieren eines eindeutigen Werte bereits vor dem Insert (In anderen Datenbank als Sequenzen bekannt). Hier muss man allerdings darauch achten, dass die Ganze Spielerei transaktionssicher ist (sobald es mehr als eine SQL Anweisung ist kann es passieren, dass eine andere Session dazwischenfunkt).

Hier z.B. mal der Code zum Nachahmen von Sequenzen unter MSSQL. Dazu noch eine geeignete Delphi Klasse zum Kapseln, und schon erhält man ganz easy bereits vorm Insert einen eindeutigen ID Wert auch ohne diese Identity Gedöhns (was einem z.B. bei .NET tierisch auf den Sack geht weil connectionslos gearbeitet wird).

SQL-Code:
CREATE TABLE [dbo].[Sequence] (
   [SequenceName] [varchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
   [CurrentValue] [bigint] NOT NULL ,
   [Increment] [int] NOT NULL ,
   [CreationDate] [datetime] NOT NULL
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Sequence] WITH NOCHECK ADD
   CONSTRAINT [PK_Sequence] PRIMARY KEY CLUSTERED
   (
      [SequenceName]
   ) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Sequence] ADD
   CONSTRAINT [DF_Sequence_CurrentValue] DEFAULT (0) FOR [CurrentValue],
   CONSTRAINT [DF_Sequence_Increment] DEFAULT (1) FOR [Increment],
   CONSTRAINT [DF_Sequence_CreationDate] DEFAULT (getdate()) FOR [CreationDate],
   CONSTRAINT [CK_Sequence] CHECK ([Increment] <> 0)
GO




SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO




CREATE PROCEDURE spNextSequence (@SequenceName varchar(255), @SequenceId bigint OUTPUT) AS
DECLARE @Increment int


SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION SP_GEN_ID


SET @SequenceId = (Select CurrentValue from Sequence where SequenceName = @SequenceName)

IF @SequenceId is null BEGIN
    insert into Sequence (SequenceName) values (@SequenceName)
   SET @SequenceId = (Select CurrentValue from Sequence where SequenceName = @SequenceName)
END
  

SET @Increment = (Select Increment from Sequence where SequenceName = @SequenceName)
update Sequence set CurrentValue=CurrentValue+@Increment where SequenceName = @SequenceName
SET @SequenceId = (Select CurrentValue from Sequence where SequenceName = @SequenceName)


COMMIT TRANSACTION SP_GEN_ID

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
Man beachte hier in der Stored Procedure das
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE Damit wird sichergestellt, dass immer nur einer diese Prozedur gleichzeitig ausführen kann.
  Mit Zitat antworten Zitat