Identity

Adatbázis és adatelérési réteg tervezésekor gyakran futunk bele abba a problémába, hogy egy táblába beszúrt rekord valamely automatikusan előálló mezőjét a rekord beszúrása után vissza kellene adnunk a tárolt eljárást hívó felsőbb szintű kódnak. Tipikusan egy rekord beszúrása után kellene tudnunk az új rekord azonosítóját.

Ha az azonosító egy int típusú oszlop IDENTITY default értékkel, akkor nincs nagy probléma, csak ki kell bogarászni, hogy a @@IDENTITY, SCOPE_IDENTITY() és IDENT_CURRENT függvények közül melyik lekérdezésével kaphatjuk vissza a beszúrt azonosítót.

Ha az ID oszlopunk uniqueidentifier, akkor azért vagyunk könnyű helyzetben, mert már az adatbázis hívás előtt generálhatunk egy GUID-ot, hiszen annak mindegy, hogy ki hozza létre, ígyis-úgyis egyedi lesz.

Ámde mi van akkor, ha uniqueidentifiert használunk, de NewSequentialID() kezdőértékkel? Ezt nem fogjuk tudni C#-ban generálni, ezt csak az adatbázis fogja tudni, ráadásul az is csak DEFAULT constraintben (vagy aki hajlandó meghívni az UuidCreateSequential API függvényt, amit az SQL is burkol). Nincs más hátra, vissza kell kérdezni a beszúrt sor adatait.

SQL Server 2005-től kezdve az OUTPUT clause segítségével talán ez egy kicsit egyszerűbb. Íme egy példa tábla két automatikusan kitöltött mezővel:

    CREATE TABLE Nevek (
      ID uniqueidentifier DEFAULT( NewSequentialID() ),
      Nev nvarchar( 100 ),
      Datum datetime DEFAULT( GetDate() ),
      Nem char( 1 ) )
    GO

Töltsük fel érdekes adatokkal:

    INSERT INTO Nevek ( Nev, Nem ) VALUES ( 'Ágnes', 'N' )
    INSERT INTO Nevek ( Nev, Nem ) VALUES ( 'András', 'F' )
    INSERT INTO Nevek ( Nev, Nem ) VALUES ( 'Zoltán', 'F' )
    INSERT INTO Nevek ( Nev, Nem ) VALUES ( 'Gábor', 'F' )
    INSERT INTO Nevek ( Nev, Nem ) VALUES ( 'Bogi', 'N' )
    GO

A táblába beszúrhatunk egy rekordot pusztán az alapértékekkel:

    INSERT INTO Nevek DEFAULT VALUES

Ha arra is kíváncsiak vagyunk, hogy mi került a táblába, tegyük a közepére az OUTPUT kulcsszót és használjuk az INSERTED táblát, mintha csak triggerben lennénk:

    INSERT INTO Nevek OUTPUT INSERTED.* DEFAULT VALUES

Persze lehetünk ennél specifikusabbak is, ha nincs szükségünk minden oszlopra:

    INSERT INTO Nevek ( Nev, Nem ) OUTPUT INSERTED.ID, INSERTED.Nev VALUES ( 'Róbert', 'F' ) 

 Mi van akkor, ha a beszúrt azonosító értékét később szeretnénk használni? Nosza töltsük át egy változóba, amihez sajnos kell egy tábla típusú változó is:

    DECLARE @New TABLE( ID uniqueidentifier, Datum datetime )
    INSERT INTO Nevek ( Nev ) OUTPUT INSERTED.ID, INSERTED.Datum INTO @New VALUES ( 'Hassan' ) 
    SELECT ID FROM @New

Sőt, ez nem csak INSERTtel, hanem UPDATE és DELETE utasításokkal is működik. Szeretnénk tudni, hogy egy UPDATE hívás mely rekordokon dolgozott? Már mindent tudunk, csak össze kell rakni:

    UPDATE Nevek
    SET Nem = 'F'
    OUTPUT INSERTED.ID, INSERTED.Nev
    WHERE Nem IS NULL

Természetesen nem csak INSERTED, hanem DELETED tábla is létezik, annak kipróbálása viszont már házi feladat!

 

Technorati tags:

Vélemény, hozzászólás?

Adatok megadása vagy bejelentkezés valamelyik ikonnal:

WordPress.com Logo

Hozzászólhat a WordPress.com felhasználói fiók használatával. Kilépés / Módosítás )

Twitter kép

Hozzászólhat a Twitter felhasználói fiók használatával. Kilépés / Módosítás )

Facebook kép

Hozzászólhat a Facebook felhasználói fiók használatával. Kilépés / Módosítás )

Google+ kép

Hozzászólhat a Google+ felhasználói fiók használatával. Kilépés / Módosítás )

Kapcsolódás: %s