A legutóbbi cikkemben nagyjából leírtam, miben különbözik a Standard SQL a T-SQL-től, és kinek melyiket érdemes megtanulnia. Most a szintaxisbeli különbségekre szeretnék koncentrálni, és ezeket a különbségeket példákkal illusztrálni. Ha azt gondolja, hogy a T-SQL egy kiterjesztés, amely a standard SQL összes funkcióját megvalósítja, akkor nincs igaza. Az SQL Serverben azonban az SQL szabvány szinte minden funkcióját megtalálja. Ebben a cikkben példákat talál a standard SQL és a Transact-SQL közötti néhány szintaxisbeli különbségre.
#1 Az adatbázis-objektumok nevei
A relációs adatbázis-rendszerekben a táblákat, nézeteket és oszlopokat nevezzük el, de néha szükség van arra, hogy ugyanazt a nevet kulcsszóként használjuk, vagy speciális karaktereket használjunk. A szabványos SQL-ben az ilyen neveket idézőjelekbe (“”), de a T-SQL-ben zárójelbe () is tehetjük. Nézze meg ezeket a példákat egy táblázat nevére a T-SQL-ben:
CREATE TABLE dbo.test."first name" ( Id INT, Name VARCHAR(100));CREATE TABLE dbo.test. ( Id INT, Name VARCHAR(100));
A speciális névnél csak az első elválasztójel (az idézőjelek) is része az SQL-szabványnak.
Mi a különbség a SELECT-kijelzésben?
Az SQL-szabványban nincs szintaxis az olyan lekérdezésekre, amelyek értékeket vagy kifejezésekből származó értékeket adnak vissza anélkül, hogy egy táblázat bármely oszlopára utalnának, de az MS SQL Server lehetővé teszi az ilyen típusú kifejezéseket. Hogyan? Használhat SELECT utasítást önmagában egy kifejezéssel vagy más, nem a táblázat oszlopaiból származó értékekkel. T-SQL nyelven ez úgy néz ki, mint az alábbi példa:
SELECT 12/6 ;
Ebben a kifejezésben nincs szükségünk táblázatra a 12 osztva 6-tal kiértékeléséhez, ezért a FROM utasítás és a táblázat neve elhagyható.
#3 Rekordok korlátozása az eredményhalmazban
Az SQL-szabványban az alábbiakban bemutatott szintaxis segítségével korlátozhatjuk a rekordok számát az eredményekben:
SELECT * FROM tab FETCH FIRST 10 ROWS ONLY
A T-SQL másképpen valósítja meg ezt a szintaxist. Az alábbi példa az MS SQL Server szintaxisát mutatja:
SELECT * FROM tab ORDER BY col1 DESC OFFSET 0 ROWS FETCH FIRST 10 ROWS ONLY;
Mint látható, ez egy ORDER BY záradékot használ. A sorok kiválasztásának másik módja, de ORDER BY nélkül, a TOP záradék használata a T-SQL-ben:
SELECT TOP 10 * FROM tab;
#4 Értékek automatikus generálása
Az SQL szabvány lehetővé teszi, hogy automatikusan generált értékekkel rendelkező oszlopokat hozzunk létre. Az ehhez szükséges szintaxis az alábbiakban látható:
CREATE TABLE tab (id DECIMAL GENERATED ALWAYS AS IDENTITY);
A T-SQL-ben szintén automatikusan generálhatunk értékeket, de ilyen módon:
CREATE TABLE tab (id INTEGER IDENTITY);
#5 Matematikai függvények
Egy sor gyakori matematikai függvény része az SQL szabványnak. Az egyik ilyen matematikai függvény a CEIL(x), amelyet a T-SQL-ben nem találunk. Ehelyett a T-SQL a következő nem szabványos függvényeket biztosítja: SIGN(x), ROUND(x,) az x tizedes érték tizedesjegyekre való kerekítéséhez, TRUNC(x) a megadott tizedesjegyekre való csonkoláshoz, LOG(x) az x érték természetes logaritmusának visszaadásához, és RANDOM() a véletlen számok generálásához. Az SQL-szabványban egy lista legnagyobb vagy legkisebb számát a MAX(list) és a MIN(list) függvények adják vissza, de a Transact-SQL-ben a GREATEST(list) és a LEAST(list) függvényeket használjuk.
T-SQL function ROUND:SELECT ROUND(col) FROM tab;
#6 Összesítő függvények
Az összesítő függvényeknél újabb szintaxisbeli különbséget találunk. A COUNT, SUM és AVG függvények mindegyike egy számlálással kapcsolatos argumentumot vesz fel. A T-SQL lehetővé teszi a DISTINCT használatát ezen argumentumértékek előtt, így a sorok csak akkor kerülnek megszámlálásra, ha az értékek különböznek más soroktól. Az SQL szabvány nem engedi meg a DISTINCT használatát ezekben a függvényekben.
Standard SQL:SELECT COUNT(col) FROM tab;T-SQL:SELECT COUNT(col) FROM tab;SELECT COUNT(DISTINCT col) FROM tab;
A T-SQL-ben azonban nem találunk populációs kovarianciafüggvényt: COVAR_POP(x,y), amelyet az SQL szabvány definiál.
#7 Dátumok és időpontok részeinek lekérdezése
A legtöbb relációs adatbázis-rendszer számos függvényt szállít a dátumokkal és időpontokkal való műveletekhez.
A szabványos SQL-ben az EXTRACT(YEAR FROM x) függvény és a dátumok részeinek kiválasztására szolgáló hasonló függvények eltérnek az olyan T-SQL függvényektől, mint az YEAR(x) vagy a DATEPART(year, x).
Az aktuális dátum és idő kinyerése is különbözik. A standard SQL lehetővé teszi az aktuális dátum kinyerését a CURRENT_DATE függvénnyel, de az MS SQL Serverben nincs hasonló függvény, ezért a GETDATE függvényt kell használnunk a CAST függvény argumentumaként a DATE adattípussá való konvertáláshoz.
#8 Működés karakterláncokon
A karakterláncokkal való működéshez használt függvények használata szintén különbözik a standard SQL és a T-SQL között. A fő különbség a sztringekből az utolsó és a vezető szóközök eltávolításában található. A standard SQL-ben létezik a TRIM függvény, de a T-SQL-ben több kapcsolódó függvény is van: TRIM (az utolsó és a vezető szóközök eltávolítása), LTRIM (a vezető szóközök eltávolítása) és RTRIM (az utolsó szóközök eltávolítása).
A másik nagyon gyakran használt karakterláncfüggvény a SUBSTRING.
A SUBSTRING függvény szabványos SQL-szintaxisa így néz ki:
SUBSTRING(str FROM start )
De a T-SQL-ben ennek a függvénynek a szintaxisa így néz ki:
SUBSTRING(str, start, length)
Azért néha más oszlopokból és/vagy további karakterláncokból származó értékeket kell hozzáadni. A szabványos SQL a következő szintaxist teszi lehetővé erre:
Mint látható, ez a szintaxis a || operátort használja az egyik karakterlánc egy másikhoz való hozzáadásához.
A T-SQL-ben azonban az ezzel egyenértékű operátor a plusz jel karakter. Nézzük meg ezt a példát:
SELECT col1 + col2 FROM tab;
Az SQL Serverben lehetőségünk van arra is, hogy a CONCAT függvényt használjuk, amely a karakterláncok listáját kapcsolja össze:
SELECT CONCAT(col1, str1, col2, ...) FROM tab;
Egy karaktert többször is megismételhetünk. A szabványos SQL erre a célra definiálja a REPEAT(str, n) függvényt. A Transact-SQL a REPLICATE függvényt biztosítja. Például:
SELECT REPLICATE(str, x);
ahol x jelzi, hogy hányszor ismételjük meg a karakterláncot vagy karaktert.
#9 Egyenlőtlenségi operátor
A rekordok szűrése során egy SELECT utasításban néha egyenlőtlenségi operátort kell használnunk. A standard SQL <> definiálja ezt az operátort, míg a T-SQL mind a standard operátort, mind a != operátort lehetővé teszi:
SELECT col3 FROM tab WHERE col1 != col2;
#10 ISNULL függvény
A T-SQL-ben lehetőségünk van az ISNULL függvény segítségével egy oszlopból érkező NULL értékek helyettesítésére. Ez egy T-SQL-specifikus függvény, amely nem szerepel az SQL szabványban.
SELECT ISNULL(col1) FROM tab;
A DML-szintaxis mely részei különböznek?
A T-SQL-ben a DELETE, UPDATE és INSERT lekérdezések alapvető szintaxisa megegyezik az SQL-szabványéval, de a fejlettebb lekérdezésekben eltérések mutatkoznak. Nézzük meg őket.
#11 OUTPUT kulcsszó
Az OUTPUT kulcsszó a DELETE, UPDATE és INSERT utasításokban fordul elő. A standard SQL-ben nincs definiálva.
A T-SQL használatával a lekérdezés által visszaadott extra információkat láthatjuk. UPDATE esetén a régi és az új értékeket is visszaadja, illetve az INSERT segítségével hozzáadott vagy DELETE segítségével törölt értékeket. Ahhoz, hogy ezeket az információkat láthassuk, előtagokat kell használnunk az INSERT, UPDATE és DELETE lekérdezésekben.
UPDATE tab SET col='new value' OUTPUT Deleted.col, Inserted.col;
Egy frissített oszlopban látjuk a rekordok módosításának eredményét a korábbi és az új értékekkel. Az SQL szabvány nem támogatja ezt a funkciót.
#12 Syntax for INSERT INTO … SELECT
Az INSERT lekérdezés másik szerkezete az INSERT INTO … SELECT. A T-SQL lehetővé teszi, hogy egy másik táblából adatokat illesszünk be egy céltáblába. Nézze meg ezt a lekérdezést:
INSERT INTO tab SELECT col1,col2,... FROM tab_source;
Ez nem szabványos, hanem az SQL Serverre jellemző funkció.
#13 FROM záradék a DELETE és UPDATE lekérdezésben
A SQL Server az UPDATE és DELETE FROM záradékkal kibővített szintaxist biztosít. A DELETE with FROM záradékkal az egyik tábla sorait használhatja egy másik tábla megfelelő sorainak eltávolítására egy elsődleges kulcsra és egy idegen kulcsra való hivatkozással. Hasonlóképpen, az UPDATE with FROM záradékkal frissítheti az egyik tábla sorait egy másik tábla soraira való hivatkozással, közös értékek használatával (elsődleges kulcs az egyik táblában és idegen kulcs a másikban, pl. ugyanaz a városnév). Íme egy példa:
DELETE FROM BookFROM AuthorWHERE Author.Id=Book.AuthorId AND Author.Name IS NULL;
UPDATE BookSET Book.Price=Book.Price*0.2FROM AuthorWHERE Book.AuthorId=Author.Id AND Author.Id=12;
Az SQL szabvány nem rendelkezik erről a szintaxisról.
#14 INSERT, UPDATE és DELETE JOIN-nal
Az INSERT, UPDATE és DELETE JOIN segítségével is használható egy másik táblához való kapcsolódáshoz. Erre egy példa:
DELETE ItemOrder FROM ItemOrderJOIN Item ON ItemOrder.ItemId=Item.IdWHERE YEAR(Item.DeliveredDate) <= 2017;
Ez a funkció nem szerepel az SQL szabványban.
Összefoglaló
Ez a cikk nem tér ki az SQL szabvány és az MS SQL Server rendszert használó T-SQL közötti szintaxisbeli különbségekkel kapcsolatos összes kérdésre. Ez az útmutató azonban segít rámutatni néhány alapvető, csak a Transact-SQL-re jellemző tulajdonságra, és arra, hogy az MS SQL szabvány szerinti szintaxist az MS SQL Server nem valósítja meg.