PK-Wert von Trigger ermitteln lassen.

27/05/2008 - 18:42 von Marian Aldenhövel | Report spam
Hallo,

Ich portiere gerade eine Datenbank von Firebird auf den SQL Server 2005
(Express).

Die Anwendung verwendet folgenden Ansatz für die Behandlung von PKs:

Der Client kann bei INSERTs einen PK angeben, dazu holt er den natürlich
vorher von eine SP in derselben DB ab. Oder er kann ihn im INSERT
als '' spezifizieren und dann befragt die DB selber in einem AFTER INSERT
Trigger die SP und setzt den Wert ein.

Das bedeutet in den Fàllen, in denen die Applikation einfach was einfügt
und sich (zunàchst) nicht dafür interessiert, gibt sie keinen PK an.
Ebensowenig gibt man einen an, wenn man in irgendwelchen anderen Werkzeugen
Daten einfügt.

Wenn man aber den PK gleich braucht - zum Beispiel weil man Detail-Datensàtze
hinterher-INSERT-en will - dann làsst man sich vorher einen generieren und
verwendet den beim Insert des Master-Records und der daran hàngenden Details.
Man muss also die DB nicht nach dem Master-INSERT nach dem von ihr generierten
Autowert/Sequence/Identity-Wert fragen.

Diese Logik auf den SQL-Server zu übertragen bin ich zu doof. Ich habe
mal ganz naiv folgendes versucht:


CREATE TRIGGER TR_AU_TABELLE ON TABELLE AFTER UPDATE AS
BEGIN
UPDATE TABELLE SET
ID = NewID(),
WHERE ID IN (SELECT ID FROM Inserted)
END



Daß das nicht funktionieren kann sehe ich, und natürlich beschwert sich der
SQL Server auch über den fehlenden PK.

Kann mir jemand auf die Sprünge helfen? Ist die Logik zu retten? Oder muss
ich meinen Client àndern so daß er IMMER schon brauchbare IDs mitgibt?

Tiefer auf Spezialitàten des SQL-Server eingehen, also zum Beispiel als
IDENTITY deklarieren und @@IDENTITY abfragen, möchte ich nicht, weil das zu
mehr Abhàngigkeiten vom SQL-Server im Client führen würde.

Ciao, MM
Marian Aldenhövel, Rosenhain 23, 53123 Bonn
http://www.marian-aldenhoevel.de
"Success is the happy feeling you get between the time you
do something and the time you tell a woman what you did."
 

Lesen sie die antworten

#1 Hannes Brunner
28/05/2008 - 12:16 | Warnen spam
Hallo Marian,

Marian Aldenhövel schrieb:
Hallo,

Ich portiere gerade eine Datenbank von Firebird auf den SQL Server 2005
(Express).

Die Anwendung verwendet folgenden Ansatz für die Behandlung von PKs:

Der Client kann bei INSERTs einen PK angeben, dazu holt er den natürlich
vorher von eine SP in derselben DB ab. Oder er kann ihn im INSERT
als '' spezifizieren und dann befragt die DB selber in einem AFTER INSERT
Trigger die SP und setzt den Wert ein.

Das bedeutet in den Fàllen, in denen die Applikation einfach was einfügt
und sich (zunàchst) nicht dafür interessiert, gibt sie keinen PK an.
Ebensowenig gibt man einen an, wenn man in irgendwelchen anderen Werkzeugen
Daten einfügt.

Wenn man aber den PK gleich braucht - zum Beispiel weil man Detail-Datensàtze
hinterher-INSERT-en will - dann làsst man sich vorher einen generieren und
verwendet den beim Insert des Master-Records und der daran hàngenden Details.
Man muss also die DB nicht nach dem Master-INSERT nach dem von ihr generierten
Autowert/Sequence/Identity-Wert fragen.

Diese Logik auf den SQL-Server zu übertragen bin ich zu doof. Ich habe
mal ganz naiv folgendes versucht:

> CREATE TRIGGER TR_AU_TABELLE ON TABELLE AFTER UPDATE AS
> BEGIN
> UPDATE TABELLE SET
> ID = NewID(),
> WHERE ID IN (SELECT ID FROM Inserted)
> END

Daß das nicht funktionieren kann sehe ich, und natürlich beschwert sich der
SQL Server auch über den fehlenden PK.

Kann mir jemand auf die Sprünge helfen? Ist die Logik zu retten? Oder muss
ich meinen Client àndern so daß er IMMER schon brauchbare IDs mitgibt?



das làsst sich mit einem INSTEAD-OF Trigger bewerkstelligen. Ist aber
IMHO keine besonders elegante Lösung. Beispielcode:

USE tempdb
GO

CREATE TABLE tblTest (
ID int NOT NULL PRIMARY KEY,
Txt varchar(50) NOT NULL
)
GO

CREATE TABLE tblIDs(
TableName sysname NOT NULL PRIMARY KEY,
ID int NOT NULL
)
GO

INSERT INTO tblIDs(TableName, ID)
VALUES('tblTest', 0)
GO

CREATE PROCEDURE spSequence @TableName sysname, @NextID int OUT
AS
SET NOCOUNT ON
UPDATE tblIDs
SET @NextID = ID = ID + 1
WHERE TableName = @TableName
GO

CREATE TRIGGER tblTestInsert ON tblTest
INSTEAD OF INSERT
AS
SET NOCOUNT ON
DECLARE curInserted CURSOR
FOR SELECT ID, txt FROM inserted
DECLARE @ID int
DECLARE @txt varchar(50)

OPEN curInserted
FETCH NEXT FROM curInserted
INTO @ID, @txt
WHILE @@FETCH_STATUS = 0 BEGIN
IF @ID = 0 BEGIN
EXEC spSequence 'tblTest', @ID OUT
END
INSERT INTO tblTest(ID, txt)
VALUES(@ID, @txt)

FETCH NEXT FROM curInserted
INTO @ID, @txt
END
CLOSE curInserted
DEALLOCATE curInserted
GO

DECLARE @NextID int
EXEC spSequence 'tblTest', @NextID OUT
INSERT INTO tblTest(ID, txt)
VALUES (@NextID, 'bla')
GO

INSERT INTO tblTest(ID, txt)
VALUES(0, 'fasel')
GO

SELECT * FROM tblTest
GO

DROP PROCEDURE spSequence
GO
DROP TABLE tblIDs
GO
DROP TABLE tblTest
GO

Gruß
Hannes

Ähnliche fragen