
A példához szükséges a VariantDb adatbázis, melyet a mellékelt VariantDb.sql lefuttatásával hozhatunk létre. A VariantDb.sql script 5. sorában adja meg helyesen a létrehozandó adatbázisfájlok mappájának nevét és elérési útvonalát.
Általános jellemzők
Ha röviden szeretnénk jellemezni az sql_variant adattípust, akkor annyit mondanánk, hogy az ilyen típusú változóban képesek vagyunk tárolni az SQL Server által támogatott valamennyi adattípusú adatot, kivétel a text, ntext, image, timestamp, és sql_variant típusú értéket. Felhasználhatjuk táblák oszlopainak, paraméterek, változók, valamint felhasználó által definiált függvények visszatérési értékének tipizálásakor. Minden sql_variant típusú oszlophoz tartozik egy érték melyet tárol, valamint egy meta információ, mely tartalmazza a tárolt érték alaptípusát, pontosságát, skáláját, maximális méretét, valamint nyelvi információkat.
Az ilyen típusú változóban tárolt adatokra a fenti megszorítás mellett érvényes az is, hogy a tárolt adatok maximális mérete nem haladhatja meg a 8016 bájtot. Az adatokat először alaptípusukra kell konvertálni, mielőtt valamilyen műveletet végeznénk velük, ugyanis nem történik implicit konverzió és konvertálás nélkül az értelmező hibaüzenetet ad.
Az sql_variant típusú oszlopokban megadhatunk NULL értéket, mint ahogy ezt az alaptípusok is megengedik, azonban NULL érték esetén ez az alaptípus-információ nem határozható meg.
UNIQUE, PRIMARY KEY ÉS FOREIGN KEY megszorítással rendelkező oszlopok szintén lehetnek sql_variant típusúak, de méretük nem haladhatja meg az indexekre vonatkozó mérethatárt, amely 900 bájt. A táblák természetesen akárhány sql_variant típusú oszlopot tartalmazhatnak.
Az sql_variant típusú oszlopok nem támogatják az IDENTITY tulajdonságot, valamint a COMPUTE záradékot.
Az ALTER TABLE utasítás használható az oszlopok típusának sql_variant típusúra változtatására, amennyiben az oszlop típusa nem a kivételt képező típusok egyikébe tartozik. Az sql_variant oszlopok típusa nem változtatható meg, mivel nem lehetséges az implicit konverzió semmilyen adattípusra.
Fontos megemlíteni, hogy az ODBC interfész nem támogatja az sql_variant típust. Ennek következményeként a Microsoft OLE DB Provider for ODBC-t (MSDASQL) használva az ilyen típusú oszlopra irányuló lekérdezés eredményeként egy bináris adatsort kapunk vissza. Például a ’PS2091’ karakterláncot tartalmazó oszlop eredménye a ’0x505332303931’ bináris érték lesz.
sql_variant típusú értékek összehasonlítása
Sokszor előfordul a különböző DML utasításokban, hogy változók értékein logikai műveleteket kell elvégezni. Ha a változók adattípusa valamilyen SQL Server alaptípus, akkor az összehasonlítás gond nélkül elvégezhető. Más a helyzet azonban az sql_variant típusú változókban tárolt értékekkel.
Összehasonlítás történik az alábbi műveletekben:
- Összehasonlító operátorok használatakor
- ORDER BY, GROUP BY utasításokban
- Indexek esetén
- MIN és MAX függvényekben
- UNION utasításban
- CASE használatakor.
Az SQL Server alaptípusok különböző adattípus-családokba sorolhatók, melyeket a következő táblázatban összefoglalunk:
| Data Type Hierarchy |
Data Type Family |
| Sql_variant |
sql_variant |
| datetime |
datetime |
| smalldatetime |
datetime |
| float |
közelítő |
| real |
közelítő |
| decimal |
pontos szám |
| money |
pontos szám |
| smallmoney |
pontos szám |
| bigint |
pontos szám |
| Int |
pontos szám |
| smallint |
pontos szám |
| tinyint |
pontos szám |
| Bit |
pontos szám |
| nvarchar |
Unicode |
| nchar |
Unicode |
| varchar |
Unicode |
| char |
Unicode |
| varbinary |
binary |
| binary |
binary |
| uniqueidentifier |
uniqueidentifier |
Az egyes adattípus-családokba tartozó típusokkal deklarált változók értékeinek összehasonlításakor bizonyos szabályokat figyelembe kell venni:
- Amennyiben két sql_variant típusú változóban olyan értékeket tárolunk melyek adattípusa eltérő, de azonos típus-családba tartozik, és az első érték típusa a típus-hierarchiában magasabb szinten van, akkor először a második típusú érték implicit módon az első érték típusára konvertálódik, majd ezután történik meg az összehasonlítás.
- Amennyiben két sql_variant típusú változóban olyan értékeket tárolunk melyek adattípusa eltérő és még eltérő típus-családba tartoznak, akkor összehasonlításkor a típus-hierarchiában magasabb szinten található típusú adat lesz a nagyobb, még ha értéke kisebb is. Ez utóbbira található egy példa a mellékelt programban. A programot elindítva az alkalmazás Form-ján található TabControl kontrol ’Compare’ feliratú fülére kattintva jelenik meg a példa. A példa a következő: adott két sql_variant típusú változó, rendre @ff és @ii, valamint egy float és egy int típusú változó, melyek @f és @i. @f értékét 5.0-ra és @i értékét 6-ra választva értékül adjuk ezen változókat az sql_variant típusú változóknak. A TabPage kontrol ’Get Info’ feliratára kattintva megtörténik az összehasonlítás, melynek eredménye az lesz, hogy a float típusú érték, mely a típus-hierarchiában magasabb szinten található, nagyobb lesz, mint az int típusú, annak ellenére, hogy ez matematikailag helytelen. A fenti műveletet egy a VariantDb.sql script lefuttatásával a táblába került, Compare nevű tárolt eljárás végzi el, mely paraméterként megkapja a float és az int típusú változókat.
- Az SQL Server által használt kódlapok listája lekérdezhető az alábbi módon fn_helpcollations függvény segítségével. A különböző nyelvi beállításokkal deklarált varchar típusú oszlopok értékeinek összehasonlításkor az adott nyelvi beállítás listában elfoglalt helye határozza meg, hogy melyik érték a nagyobb. Például három érték sorrendben:
| 1 |
’klm’ (varchar SQL_Latin1_General_CP1_CS_AS) |
| 2 |
’qrs’ (varchar SQL_Latin1_General_CP1_CS_AS) |
| 3 |
’abc’ (varchar SQL_Latin1_General_Pref_Cp1_CI_AS) |
Függvények és az sql_variant típus
Amennyiben a következő függvények sql_variant értéket kapnak paraméterként, visszatérési értékük is sql_variant típusú lesz:
A következő függvények paraméterként kaphatnak sql_variant típusú oszlopot vagy változót, de nem támogatják ezt a típust visszatérési értékként:
- COL_LENGTH
- COLUMNPROPERTY
- DATALENGTH, például a következő műveletben @e változó értéke 8 lesz:
DECLARE @p SQL_VARIANT,@e INT
SET @p = 'karakter'
SELECT @e = DATALENGTH(@p)
PRINT @e
A következő függvények nem támogatják a típust:
- AVG
- RADIANS
- SUM
- ROUND
- SIGN
- ISNUMERIC
- POWER
A következők, viszont teljes mértékben támogatják az sql_variant típust:
- CAST
- CONVERT
- SQL_VARIANT_PROPERTY
SQL_VARIANT_PROPERTY függvény
Az sql_variant adattípushoz szorosan kötődik, így kicsit részletesebben is megismerjük. Az SQL Server új konstrukciója, mellyel információkat szerezhetünk az sql_variant típusú oszlopban, illetve változóban tárolt adatokról. A függvény két paraméterrel rendelkezik, melyek a következők:
- Az oszlop, illetve változó neve, melyről információt szeretnénk gyűjteni.
- Az információ megnevezése. A függvénnyel lekérdezhető információk a következő táblázatban olvashatók:
| Információ megnevezése (függvény második paramétere) |
Leírás |
Alaptípusa az információknak |
| BaseType |
Az sql_variant típusban tárolt érték alaptípusa. Például money, int, stb. |
sysname (nem valós bevitelnél NULL) |
| Precision |
Numerikus alaptípusok pontossága. Például datetime = 23, float = 53, real = 24, decimal(p,s) = p, money = 19, stb. |
int (nem valós bevitelnél NULL) |
| Scale |
A numerikus adattípus tizedesvesszője utáni helyjegyek száma. Például decimal (p,s) = s, money = 4, smallmoney = 4, datetime = 3, egyébként 0. |
int (nem valós bevitelnél NULL) |
| TotalBytes |
A tárolt információ és metaadatok együttes mérete, mely maximum 900 bájt lehet. |
int (nem valós bevitelnél NULL) |
| Collation |
Nyelvi beállítások az adott adatokra. |
sysname (nem valós bevitelnél NULL) |
| MaxLength |
Az adott adattípus maximális hossza bájtban. Például int esetén 4, varchar(50) esetén 100. |
int (nem valós bevitelnél NULL) |
A függvényt a következőképpen hívhatjuk:
SQL_VARIANT_PROPERTY(paraméter1, paraméter2)
Példa alkalmazás
A VariantDb.sql script lefuttatása után Table1 néven bekerülő tábla második oszlopa sql_variant típusú. A fent említett tárolt eljáráson kívül még kettő kerül az adatbázisba. Az ’InsertRow’ elnevezésű beszúr, az ’UpdateRow’ elnevezésű pedig módosít egy rekordot a táblában. Ezeket a funkciókat a program TabControl-jának ’Insert’ és ’Update’ fülére kattintva érhetjük el. A felületeken megtalálható gombok indítják a műveleteket, a tárolt eljárások meghívását. Nem megfelelő adat esetén a beviteli mezőre kerül a fókusz, és a Form alsó felében található, egyébként a bevitel és módosítás követésére szolgáló, DataGrid kontrolban nem jelenik meg változás.
A két fül alatt elhelyezett funkciókkal jól megfigyelhető, milyen módon tárolhatók változatos adattípusok az sql_variant oszlopban. Adatbázis tervezésekor ugyanis lehetnek olyan adatok, melyekről változatos információt szeretnénk tárolni, de mindegyikről más típusút. Elképzelhető olyan adatsor, melyekről csak szöveges információt szeretnénk tárolni, a másikról viszont olyat, melyeket matematikai függvényekben is szeretnénk felhasználni, amennyiben statisztikai jellegű eredményekre van szükségünk. Azonban az sql_variant használatával elkerülhető, hogy minden adatfajtának külön oszlopot deklaráljunk, egyes adatok esetén esetleg feleslegesen, növelve ezzel az adattárolás helyigényét, költségeit. Az adatok kinyerésénél jól használható a fent említett SQL_VARIANT_PROPERTY függvény.
A mellékelt programban a ’sql_variant’ Column Information fülre kattintva kipróbálható a függvény használata. Egyszerűen ki kell választani egy rekordazonosítót a ComboBox kontrolból, majd a ’Get Info’ gombra kattintva megkapható a ’BaseType’, a ’Precision’ és a ’Scale’ tulajdonság az adott adatról. A programban használata közben a következő utasítást adtuk át az SqlCommand komponens CommandText property-jének, ahol az ’siCombo.Text’ kifejezés tartalmazza a kiválasztott rekordazonosítót:
general.CommandText = "SELECT SQL_VARIANT_PROPERTY(Information,'BaseType') FROM Table1 WHERE ItemID=" + siCombo.Text;