|
|
MS SQL adatbázis kezelés Delphi-ből
7. rész
|
|
Példaprogram letöltése
9335 bájt
|
Aktuális cikkünkben az Identity mező használatát mutatjuk be.
Az SQL Server identity mezője nagyon hasonló a Paradox autoincrement mezőjéhez vagy a Microsoft Access counter mezőjéhez, vagyis minden alkalommal automatikusan megnövekszik az értéke, amikor a táblába rekordot szúrunk be, mégpedig annyival, amennyit a tábla definiálásakor beállítottunk.
IDENTITY (seed, increment)
A mezőt remekül használhatjuk egyedi azonosító érték tárolására akár a Primary Key constraint-tel együtt is. Meg kell adnunk egy kezdeti értéket, ami a legelső beszúrás alkalmával lesz kiosztva (seed), és egy növekményt (increment). Ennyivel lesz több a mező értéke a következő beszúráskor. Ha elhagyjuk a két paramétert, (1,1)-nek tekinti az SQL Server. A identity mező csak egész típusú lehet, tehát tinyint, smallint, int, decimal(p,0), vagy numeric(p,0). Nézzünk egy példát:
CREATE TABLE jobs
(
job_id smallint IDENTITY(1,1) PRIMARY KEY CLUSTERED,
job_desc varchar(50) NOT NULL,
min_lvl tinyint NOT NULL CHECK (min_lvl >= 10),
max_lvl tinyint NOT NULL CHECK (max_lvl <= 250)
)
Amiért érdemes ezzel a mezővel külön is foglalkozni, az az a probléma, hogy egy beszúrás után a BDE nem tudja, hogy az identity mező milyen értéket kapott. Bizonyos alkalmazásoknál ez problémát jelenthet. Például ha egy táblában identity mező a primary key, a táblát egy TTable komponensen keresztül érjük el és az adatokat a primary key szerint rendezve nézzük, egy beszúrás után a BDE nem fogja megtalálni az új rekordot. Mégpedig azért nem, mert a rekord beszúrása előtt a kulcs értéke Null, és ez csak az SQL Serverben kap helyes értéket, amiről a BDE nem kap értesítést. Az aktuális rekordra mutató pointer ezért a tábla első rekordjára mutat ahelyett, hogy a most beszúrt rekordra mutatna.
A problémát a példaprogram bal oldali panelje szemlélteti. A program a 4. fejezetben létrehozott test1 nevű aliasra csatlakozik, ami az SQL Server pubs nevű példa adatbázisára mutat. Innen megnyitjuk a jobs nevű táblát, ami tartalmaz identity mezőt és ugyanez a mező primary key is. Ha most a navigator segítségével beszúrunk egy értéket, látni fogjuk, hogy az identity érték nem jelenik meg és a rekord az első helyre kerül. Több, egymást követő beszúrás esetén pedig mindig csak az utolsó jelenik meg. Amíg nem kérünk egy frissítést, nem látjuk az identity értékeket.
Beszúráskor vigyázzunk arra, hogy magát az identity értéket nem adhatjuk meg, továbbá a min_lvl és max_lvl mezőkre check constraint van definiálva, ezért itt sem adhatunk meg akármekkora értéket. (A tábla definícióját lásd a fenti példában.)
A probléma feloldására számtalan megoldás létezik, mutatunk egy párat.
1. Alternatív mező használata a rendezésre
Ne az identity mező szerint rendezzük a táblát. Ha a tábla szerkezete megengedi, ügyesen válasszunk olyan rendezést, ami hasonló vagy ugyanolyan sorrendet produkál, mint az identity mező szerinti.
2. @@identity változó lekérdezése
Az SQL Server az utolsó beszúráskor kalkulált identity értéket a @@identity globális változóban tárolja. Ha az utolsó INSERT vagy SELECT INTO nem érintett identity mezőt, a @@identity változó értéke NULL lesz. Ha a művelet egyszerre több sort is érintett, az utolsó beszúrt identity mező értéke lesz a nyerő. Írhatunk egy egyszerű tárolt eljárást, ami a beszúrás után ezt rögtön lekérdezi. A kapott érték alapján már könnyen megtaláljuk az utoljára beszúrt rekordot a Delphi-s alkalmazásunkban is.
Ez a megoldás azonban hiába elegáns, nem maradéktalanul problémamentes. Ha ugyanis a táblán olyan INSERT trigger van, ami szintén végrehajt néhány beszúrást más identity mezőt tartalmazó táblákba, a @@identity értéke már ezt a legutolsó értéket fogja tartalmazni, és nem azt, ami nekünk kell. Ha pedig a trigger olyan táblába szúr be, ahol nincs identity mező, a globális változó értéke NULL lesz. Szintén probléma, hogy ha egy INSERT vagy SELECT INTO művelet meghiúsul, vagy egy tranzakciót visszagörgetünk (rollback), a @@identity értéke nem áll vissza az utolsó, konzisztens értékre.
Ha ezt a megoldást választjuk, a fentieket is figyelembe kell vennünk.
3. UNIQUE mező felhasználása
Szerencsénk van, ha az adattáblánkban az identity mező mellett szerepel egy UNIQUE mező is. Ekkor az INSERT után ezt a mezőt felhasználva még az SQL Serverben visszakeressük a rekordot, és kiolvassuk belőle az identity mező értékét, amit visszaadunk az alkalmazásunknak.
Például tegyük fel, hogy a jobs táblában a job_desc mezőt UNIQUE-nak definiáltuk. Ekkor az adatok beszúrását végző tárolt eljárás a következőképpen nézne ki:
CREATE PROCEDURE sp_add_job
@job_desc varchar(50),
@min_lvl tinyint,
@max_lvl tinyint
AS
insert into jobs (job_desc, min_lvl, max_lvl)
values (@job_desc, @min_lvl, @max_lvl)
select job_id
from jobs
where job_desc = @job_desc
Mivel a job_desc mező egyedi, biztosan a helyes identity értéket kapjuk. Ha nincs ilyen UNIQUE mezőnk, akkor is gondolkodhatunk úgy, hogy van-e olyan kombinációja a mezőknek, amelyekre igen valószínűtlen, hogy ugyanazokat az értékeket veszik fel.
4. Nem használunk identity mezőt kulcsmezőként
Valami más módon generálunk egyedi azonosítót, például egy táblában minden beszúráskor inkrementálunk egy egész típusú mezőt, és minden beszúrás előtt kiolvassuk az értékét. Az INSERT utasításban ekkor minden mezőt megadunk, így föl sem merülnek az előbb említett problémák. Persze nem valami elegáns, hogy minden beszúrás előtt egy extra alkalommal az adatbázisszerverhez fordulunk, de ha a feladat jellege olyan, hogy nem kell sokszor adatot beszúrni, ez a szisztéma is kitűnően működik.
A példaprogramban a 2. módszerre mutatunk példát. A beszúrás után lekérdezzük a @@identity mezőt, és a kapott érték alapján visszakeressük a rekordunkat. A program működéséhez hozzuk létre az alábbi tárolt eljárást az SQL Server pubs példaadatbázisában, mondjuk az SQL Server Enterprise Manager-ével:
CREATE PROCEDURE sp_add_job
@job_desc varchar(50),
@min_lvl tinyint,
@max_lvl tinyint
AS
insert into jobs (job_desc, min_lvl, max_lvl)
values (@job_desc, @min_lvl, @max_lvl)
select @@identity as result
|
Cikksorozat
| 2591 | Windows | Tippek és trükkök - RAS - Modem csengetési szám állítása | 1. rész |
| 2622 | Windows | Tippek és trükkök - Program futtatása más felhasználóként | 2. rész |
| 2640 | Windows | A Windows ikonméretének megváltoztatása és Windows 2000 Asztaltémák | 3. rész |
| 2657 | Windows | Tippek és trükkök - Internet Explorer | 4. rész |
| 2667 | Windows | Tippek és trükkök | 5. rész |
| 2684 | Windows | Alapértelmezések állítása, telepítési fájlok helye, intéző nézetek | 6. rész |
| 2696 | Windows | Biztonsági trükkök | 7. rész |
| 2702 | Windows | Windows XP trükkök | 8. rész |
| 2729 | Windows | Windows 2000 és XP tippek, trükkök | 9. rész |
| 2757 | Windows | Registry trükkök | 10. rész |
| 2784 | Windows | Tippek, trükkök | 11. rész |
| 2829 | Windows | Tippek, trükkök | 12. rész |
| 2889 | Windows | Windows XP tippek | 13. rész |
| 2909 | Windows | Tippek Windows XP-hez | 14. rész |
| 2919 | Windows | Windows tippek | 15. rész |
| 2924 | Windows | Windows tippek | 16. rész |
| 2963 | Windows | Windows tippek | 17. rész |
| 2973 | Windows | Windows Tippek | 18. rész |
| 2981 | Windows | Windows tippek | 19. rész |
| 2990 | Windows | Tippek-trükkök | 20. rész |
| 3027 | Windows | IIS tippek | 21. rész |
| 3034 | Windows | Windows XP tippek-trükkök | 22. rész |
| 3088 | Windows | Windows 2000/XP tippek, trükkök | 23. rész |
| 3133 | Windows | Windows XP tippcsokor | 24. rész |
| 3140 | Windows | Windows XP tippek, trükkök | 25. rész |
| 3152 | Windows | XP és IIS tippek - trükkök | 26. rész |
| 3158 | Windows | Windows XP tippek, trükkök | 27. rész |
| 3168 | Windows | Tippek, trükkök | 28. rész |
| 3170 | Windows | Registry trükkök | 29. rész |
| 3179 | Windows | Tippek, trükkök | 30. rész |
| 3197 | Windows | Windows XP tippek, trükkök | 31. rész |
| 3205 | Windows | Tippek, trükkök | 32. rész |
| 3214 | Windows | Tippek, trükkök | 33. rész |
| 3223 | Windows | Tippek, trükkök | 34. rész |
| 3233 | Windows | Tippek, trükkök | 35. rész |
| 3271 | Windows | Tippek, trükkök | 36. rész |
| 3307 | Windows | Tippek, trükkök | 37. rész |
| 3370 | Windows | Tippek, trükkök | 38. rész |
| 3399 | Windows | Tippek, trükkök | 39. rész |
| 3510 | Windows | Tippek, trükkök | 40. rész |
| 3611 | Windows | Hardverrel kapcsolatos tippek, trükkök | 41. rész |
| 3668 | Windows | Registry trükkök | 42. rész |
| 3711 | Windows | Tippek, trükkök | 43. rész |
| 3771 | Windows | Tippek, trükkök | 44. rész |
| 3801 | Windows | Tippek, trükkök | 45. rész |
| 3831 | Windows | Tippek, trükkök | 46. rész |
| 3891 | Windows | Tippek, trükkök | 47. rész |
| 3921 | Windows | Tippek, trükkök | 48. rész |
| 3981 | Windows | Tippek, trükkök | 49. rész |
| 4041 | Windows | Tippek, trükkök | 50. rész |
| 4071 | Windows | Tippek, trükkök | 51. rész |
| 4151 | Windows | Tippek, trükkök | 52. rész |
| 4171 | C# | Tippek, trükkök | 53. rész |
| 4211 | Windows | Tippek, trükkök | 54. rész |
| 4251 | Windows | Tippek, trükkök | 55. rész |
| 4281 | Windows | Tippek, trükkök | 56. rész |
| 3589 | Delphi | Tippek, trükkök | 57. rész |
| 3718 | Delphi | Tippek, trükkök | 58. rész |
Könyv
Ez a cikk megtalálható ebben a könyvben:
Delphi Software Offline 2000 évkönyv 527. oldal
Felhasználási feltételek
A Software Online szoftverfejlesztői magazin mindegyik cikke, minden megjelent képe, és egyéb publikált anyaga szerzői jog védelme alatt áll! Bármilyen formában történő másodlagos terjesztésük, közzétételük vagy felhasználásuk kizárólag a kiadó előzetes írásbeli engedélyével történhet!
|