SQL tanköny tartalomjegyzéke
  ----- ----- --------- ----- ---- 
 2.1. Bevezetés 1
 2.2. Adat definició 3
 2.3. Adat manipulálás 5
 2.4. Cursor műveletek 7
 2.5. Nézetek 9
 2.6. Adat vezérlés  10
 2.7. Néhány eltérés a DB2-töl   12 
 3.1. Alap adat tárgyak  16
 3.2. Modulok, eljárások, beágyazott SQL.  20
 3.3. Adatvédelem, integritás és tranzakció 
  feldolgozás  23
 3.4 Alapvetö nyelvi elemek  26
 3.5. Jelölés   28 
 4. Adatdefinició: a séma leiró nyelv
 4.1. Szintaxis  31
 4.2. Alap táblák    32
 4.3. Privilégiumok  35  
 5. Adat manipul ció: a modul nyelv
 5.1. Szintaxis  37
 5.2. Eljárások, paraméterek és manipulativ 
  utasitások   38
 5.3. Indikátor paraméterek  40
 5.4. COMMIT és ROLLBACK  42 
 6. Adat manipuláció: cursor müveletek
 6.1. Bevezetés  43
 6.2. Cursorok  44
 6.3. Cursoron alapuló manipulációk  47
 6.4. Egy globális példa  49 
 7. Adat manipuláció: nem cursor müveletek
 7.1. Bevezetés  53
 7.2. SELECT   53
 7.3. INSERT  56
 7.4. Keresett UPDATE  57
 7.5. Keresett DELETE  58 
 8. Nézetek
 8.1. Bevezetés  60
 8.2. Nézet definició  62
 8.3. Visszanyerési müveletek  64
 8.4. Aktualizálási müveletek  66 
 9. Általános nyelvkonstrukciók
 9.1. Lekérdezés kifejezések  70
 9.2. Lekérdezés specifikációk  71
 9.3. Skalár kifejezések  72
 9.4. Függvények  74
 9.5. Tábla kifejezések  77
 9.6. Keresési feltételek  84
 9.7. Nem kvantoros predikátumok  85
 9.8. Al-lekérdezések   91
 9.9. Kvantoros predikátumok  93 
 10. Beágyazott SQL
 10.1. Bevezetés  96
 10.2. Egy teljes példa  96
 10.3. Felmerülö szempontok  98  
 11. Definiciós kiterjesztések
 11.1. Bevezetés  101
 11.2. Alaoértékek  101
 11.3. CHECK követelmények  102
 11.4. Referenciális integritás  103 
 12. Manipulativ kiterjesztések
 12.1. Ortogonalitás továbbfejlesztések  109
 12.2. Csusztató cursorok  111  
 A. Függelék
  Mintafeladatok 
 A.1. Bevezetés  112
 A.2. Adat definició  112
 A.3. Adat manipuláció: visszanyerési müveletek  115
 A.4. Adat manipuláció: akzualizálási müveletek 119
 A.5. Beágyazott SQL   119
 A.6. Válaszok  120 
 B. Függelék
  Egy SQL nyelvtan
 B.1. Bevezetés  130
 B.2. Séma definiáló nyelv  131
 B.3. Modul nyelv  132
 B.4. Manipulativ utasitások  132
 B.5. Lekérdezés kifejezések  134
 B.6. Keresési feltételek   134
 B.7. Skalár kifejezések  136
 B.8. Egyebek  137 
 C. Függelék
  Nyelvi szintek és konformancia  138
  Betűrendes mutató  140  
  
 __________ ______ ____ _____ _______ ______ _______________     
 Az SQL áttekintése    
 2.1 BEVEZETÉS  
 A jelen fejezet célja a szabványos SQL fö lehetöségei közül 
 néhánynak rövid és nagyon "informális" bevezetö ismertetése,
 és ezzel az ut egyengetése az ezt követö fejezetekben a nyelv
 szabályszerü és alaposabb leirásának megértéséhez. A fejezet
 nagyjából a szerzönek a Relational Database: Selected Writings
 /relációs adatbázis| válogatott irások/, /Addison-Wesley,1986/
 könyvében lévö 1.fejezeten /"Relációs adatbázis:áttekintés"/ 
 alapul.
  Az SQL nyelvnek az a feladata, hogy támogassa egy relá-
 ciós adatbázisban lévö adatok definiálását, manipulálását és
 vezérlését. Egy relációs adatbázis egyszerüen olyan adatbázis,
 amelyet a felhasználó táblák gyüjteményeként észlel - ahol
 egy tábla sorok nem rendezett gyüjteménye /"reláció" egysze-
 rüen egy matematikai kifejezés egy ilyen táblázathoz/. Egy pld,
 a szállitók és alkatrészek adatbázisa, a 2.1-es ábrában lát-
 ható. Ebben az ábrában az S, P és SP táblák a szállitókat, al-
 katrészeket illetve a szállitók által az alkatrészek elszálli-
 tásait reprezentálják. Megjegyezzük, hogy mindegyik tábla fájl-
 ként is tekinthetö ugy, hogy a sorok a rekordokat és az oszlo-
 pok a mezöket reprezentálják. Az SQL szabvány azonban mindig
 a "sor" /row/ és "oszlop" /column/ kifejezéseket használja,
 sohasem használja a "rekord" /record/ és "mezö" /field/ kifeje-
 zéseket és ebben a könyvben ezért mi is általában hasonlóképpen
 teszünk.
  Az SQL "adatmanipuláló" utasitások, melyek adat vissza-
 nyerési és aktualizálási feladatokat hajtanak végre - vagy in-
 teraktiv módon, vagy egy alkalmazási programból hivhatók meg.
 a 2.2 ábra mutatja mindkét esetet; bemutat egy olyan adat 
 visszanyerési müveletet /SELECT az SQL-ben/, amely mind /a/
 interaktiv módon, mind pedig /b/ egy PL/I programból hasz-
 nálható. 
  sql.doc Page: 2 
 2.1 ábra. Szállitók és alkarészek adatbázis /minta értékek/
  ___ _____ ______ ______ ___ ___ ___
  S SNO SNAME STATUS CITY SP SNO PNO QTY
  ___ _____ ______ ______ ___ ___ ___
  S1 Smith 20 London S1 P1 300
  S2 Jones 10 Paris S1 P2 200
  S3 Blake 30 Paris S1 P3 400
  S4 Clark 20 London S1 P4 200
  S5 Adams 30 Athens S1 P5 100
  S1 P6 100
  ___ _____ ______ ______ ____ S2 P1 300
  P PNO PNAME COLOR WEIGHT CITY S2 P2 400
  ___ _____ ______ ______ ____ S3 P2 200
  P1 Nut Red 12 London S4 P2 200
  P2 Bolt Green 17 Paris S4 P4 300
  P3 Screw Blue 17 Rome S4 P5 400
  P4 Screw Red 14 London 
  P5 Can Blue 12 Paris
  P6 Cog Red 19 London
 ahol:
 SNO = szállitó száma
 SNAME = szállitó neve
 STATUS = állapot
 CITY = város
 PNO = alkatrész száma
 PNAME = alkatrész neve
 COLOR = szin
 WEIGHT = suly
 Nut = anya
 Bolt = fejes csavar
 Can = bütyök
 Cog = fogaskerék
 Red = vörös
 Green = zöld
 Blue = kék
 QTY = mennyiség 
 2.2 ábra. SQL visszanyerésre példa
 /a/ Interaktiv meghivás:
  ______
  SELECT S.CITY Eredmény: CITY 
  FROM S ______
  WHERE S.SNO = 'S4' London
 /b/ Meghivás egy alkalmazási programból /PL/I/:
   ______
  EXEC SQL SELECT S.CITY INTO :SC Eredmény: SC
  FROM S ______
  WHERE S.SNO = 'S4'; London       
  sql.doc  Page: 3 
 Altalában az interaktiv meghivás azt jelenti, hogy a kérdéses
 utasitás interaktiv terminálról hajtodik végre és /vissza-
 nyerés esetén / az eredmény terminálon jelenik meg. Egy
 alkalmazási programból meghivás azt jelenti, hogy az utasitás
 a program végrehajtási folyamatának részeként hajtódik végre
 és /visszanyerés esetén/ az eredmény a programon belüli in-
 put területre töltödik /fetch/ /":SC" a 2.2/b/ ábrában/.
 Megjegyzés: a 2.2 ábrában egy alkalmazási programból az SQL
 meghivására bemutatott szintaxis tipus nem az egyetlen lehet-
 séges tipus. Lásd a 3. fejezet.
  Egy további megjegyzés: Az olvasót majd figyelmeztetni 
 fogjuk, hogy minösitett oszlop neveket használtunk /S.SNO,
 S.CITY/ a 2.2 ábrában. Az SQL tulajdonképpen lehetövé teszi,
 hogy a minösitök kimaradhassanak sok összefüggésböl /ez föleg
 a SELECT és a WHERE klauzulákra érvényes/ feltéve, hogy az ilyen
 kihagyásokból semmilyen félreérthetöség nem származhat. Igy
 például a 2.2 ábra két SELECT klauzulája mindkét esetben lerö-
 vidithetö lehetett volna egyszerüen a "SELECT CITY" klauzulára.
 Ebben a könyvben, világos megfogalmazási és szabatos kifeje-
 zési okok miatt, általában minösitett neveket fogunk használni,
 még akkor is, ha ezekre szigoruan véve nincs szükség - kivéve
 természetesen az olyan szöveg összefüggéseket, ahol ezek tiltva
 vannak. Egy olyan szöveg összefüggésre példa, melyben a minö-
 sitett nevek tiltva vannak, egy UPDATE utasitásban egy SET 
 klauzula értékadás baloldala. Lásd a 2.3 alfejezetet.    
 2.2 ADAT DEFINICIO  
 A 2.1 ábra, a szállitók és alkatrészek adatbázisa, természe-
 tesen ezt az adatbázist ugy reprezentálja, ahogyan valamilyen
 adott idöpontban megjelenik. A megfelelö adatbázis definició,
 vagy séma/*/, a 2.3 ábrában látható. Az AUTHORIZATION TED klauzula
 azt adja meg, hogy a TED felhasználó ennek a sémának a létre-
 hozója; a három CREATE TABLE müvelet három üres táblát defini-
 ál a megadott nevekkel és a megadott , megnevezett oszlopokkal.
 Az S táblán belül az SNO oszlop NOT NULL-ként és UNIQUE-ként
 van definiálva; hasonlóan a P táblában lévö PNO oszlophoz és
 az SP táblában a /SNO,PNO/ oszlopok kombinációjához. Az ada-
 tok ezt követöen ezekbe a táblákba az SQL INSERT utasitással,
 melyet a következö alfejezetben tárgyalunk, vihetök be.
 ___________________
 * Pontosabban megfogalmazva egy séma az adatbázisnak azt a
 részét definiálja, amely valamilyen specifikus felhasználó
 tulajdonában van. A komplett adatbázis definició általában
 több sémából fog állni, nem csak egyböl.
 ___________________     
   sql.doc Page: 4 
 2.3 ábra. Példa séma definiálására 
  CREATE SCHEMA AUTHORIZATION TED
  CREATE TABLE S ( SNO CHAR(5) NOT NULL,
  SNAME CHAR(20), 
  STATUS DECIMAL(3),
  CITY CHAR(15),
  UNIQUE ( SNO ))
  CREATE TABLE P ( PNO CHAR(6) NOT NULL,
  PNAME CHAR(20),
  COLOR CHAR(6),
  WEIGHT DECIMAL(3),
  CITY CHAR(15),
  UNIQUE ( PNO ))
  CREATE TABLE SP ( SNO CHAR(5) NOT NULL,
  PNO CHAR(6) NOT NULL,
  QTY DECIMAL(5),
   UNIQUE (SNO, PNO ))
 Megjegyzés: Ezt a sémát alap sémaként fogjuk használni a 
 példáink nagyrészéhez a jelen könyvben mindenhol.
  Kétfajta tábla definiálható egy SQL sémában:
 alap táblák és nézet táblák /melyeket egyszerüen nézeteknek
 nevezünk/. A 2.3 ábra táblái közül mindegyik alap tábla. Egy
 alap tábla "valós" tábla - vagyis olyan tábla, amely fizikailag
 létezik, abban az értelemben, hogy léteznek fizikailag tárolt
 rekordok és esetleg fizikai elérési utak, mint például indexek,
 a tárolt fájlok közül egyben vagy több-ben, melyek közvetlen tá-
 mogatják ezt a táblát a tárolóban. Ezzel ellentétben egy nézet
 "virtuális" tábla, vagyis olyan tábla, amely nem létezik
 fizikai tárolóban, de a felhasználó számára ugy látszik, mint-
 ha létezne. A nézetek egy vagy több alapul szolgáló alap táb-
 la segitségével /kifejezéseivel/ vannak definiálva, a 2.5
 alfejezetben elmagyarázására kerülö módon.
  Megjegyzés: A jelen szakasz leirását nem szabad ugy értel-
 mezni, hogy ez azt jelentené, hogy egy alap tábla fizikailag
 táblaként van tárolva - vagyis fizikailag egymás mellett tárolt
 rekordok készleteként ugy, hogy minden egyes rekord egyszerüen
 az alap tábla egy sorának közvetlen másolatát tartalmazza. Az
 alap tábla legjobban ugy tekinthetö, mint tárolt adatok vala-
 milyen készletének absztrakciója - olyan absztrakció, melyben
 számos tárolási szint részlet /ilyen például a fizikai adat
 hely, fizikai rendezés, tárolt érték kódolások, fizikai elérési
 utak, stb./ van elrejtve. Igy tehát általában sok különbség
 van egy alap tábla és ennek tároló reprezentálása között. A lé-
 nyeg azonban az, hogy a felhasználók az alaptáblákra mindig 
 ugy gondolhatnak, hogy ezek "fizikailag léteznek" , ugyanakkor
 nem kell önmaguknak foglalkozni azzal, hogy ezek a táblák hogyan
 vannak ténylegesen reprezentálva a tárolóban. Másrészröl azonban
 a nézetek ebben az értelemben "fizikailag nem léteznek"; a
 nézetek egyszerüen az alap táblákban lévö adatok másféle
 "megtekintési" módjai. A nézeteket semmilyen saját külön, meg-
 különböztethetö, fizikailag tárolt adatuk nem reprezentálja.   
  sql.doc Page: 5 
 2.3 ADAT MANIPULALAS 
 Négy alapvetö SQL adat manipulálási müvelet létezik: SELECT,
 INSERT, UPDATE, és DELETE. Már megadtunk egy példát a SELECT-re
 /két verzió/ a 2.2 ábrában. A 2.4 ábra példákat ad meg a másik
 három müveletre - az ugynevezett aktualizálási müveletekre.
 megjegyzés: Az "aktualizálás" /update/ kifejezésnek sajnos két
 jelentése van az SQL-ben: generikusan használják egy osztályként
 az INSERT, UPDATE és DELETE három müveletre utaláshoz és 
 specifikusan is használják az UPDATE müveletre utaláshoz.
 Ebben a könyvben különbséget fogunk tenni a kétféle jelentés
 között ugy, hogy mindig kisbetüt használunk, amikor a gene-
 rikus jelentéshez szánjuk és nagybetüt, amikor a specifikus
 jelentéshez szánjuk. 
 2.4 ábra. Update példák 
  INSERT Eredmény: A megadott sor hozzá-
  INTO SP (SNO, PNO, QTY) adódik az SP táblához
  VALUES ('S5','P1',1000) 
   UPDATE S Eredmény: A STATUS megkettözö-
  SET STATUS = 2 * S.STATUS dik londoni szallitok
  WHERE S.CITY = 'London' esetén /vagyis S1 és
  S4/
  DELETE  Eredmény: Sorok törlése P táb-
  FROM P lából P2-es, P3-as
  WHERE P.WEIGHT > 15 és P6-os alkatrészek
  esetén   
  Megjegyezzük, hogy a 2.4 ábra UPDATE és DELETE müveletei
 közül mindkettö több soron fejti ki a hatását, nem csak egyet-
 len soron. Altalában ugyanez igaz INSERT müveletekre /jól-
 lehet a 2.4 ábra INSERT müvelete ténylegesen egysoros müvelet/,
 és SELECT müveletekre is. Azonban SELECT esetében a szabvá-
 nyos SQL nem engedi meg, hogy egy többsoros SELECT müvelet
 közvetlenül végrehajtódjon /vagyis saját jogán, külön utasi-
 tásként/; ehelyett definiálni kell egy plusz sort, mely "ér-
 vényességi köreként" /scope/ tartalmazza ezt a SELECT müve-
 letet és ezután egyenként kell elérni a SELECT /kiválasz-
 tott/ sorokat ennek a corsornak a segitségével. Azonban ok-
 tatási okok miatt a cursorok tárgyalását a 2.4 alfejezetig
 elhalasztjuk és egyenlöre feltételezzük, hogy többsoros
 SELECT-ek valóban közvetlenül végrehajthatók. /Megjegyezzük,
 hogy egysoros SELECT-ek végrehajthatók közvetlenül a 2.2
 ábrában láthatóak szerint./
  A SELECT müveletnek "SELECT-FROM-WHERE" általános alakja
 van a 2.5 ábrában bemutatottak szerint. Megjegyzés: Ebben az
 ábrában a "<>" szimbólum "nem egyenlöt" jelent.
  Figyelje meg, hogy a SELECT eredménye egy másik tábla
 /olyan tábla, amely egy meglévö táblából származik, nem pedig
 az adatbázisban tárolt tábla/. Többféle szempont merül fel
 ezzel az egyszerü példával kapcsolatban:
   sql.doc Page: 6  
 2.5 ábra. Az alap "SELECT-FROM-WHERE"
  ______ ______
  SELECT DISTINCT P.COLOR, P.CITY Eredmény: COLOR CITY 
  FROM P  ______ ______
  WHERE P.WEIGHT > 10 Red London
  AND P.CITY <> 'Paris' ---Red-----London---
  ORDER BY P.COLOR DESC ---Red-----London---
   Blue Rome 
  /A 2. és 3.sor ki-
  marad, ha a felhasz-
  náló DISTINCT-et
   ir elö./ 
 - Az eredmény tábla rendezve van az ORDER BY klauzula
  szerint. Ha DESC /descending, csökkenö/ nincs megadva,
  ASC /ascending, növekvö/ rendezés a feltételezés.
 - Ha a teljes ORDER BY klauzula kimaradt, az eredmény imp-
  lementálás - definiálta sorrendben jelenik meg.
 - Ha a teljes WHERE klauzula kimaradt, a FROM tábla minden
  sora minösit /qualify/.
 - Ha DISTINCT nincs megadva, az eredmény kettös sorokat 
  tartalmazhat, /a példában négy sor fog vissztérni,
  ha a DISTINCT nincs megadva, kettö ha meg van adva./ 
 Összekapcsolás 
 Egy jellemzö, amely csaknem minden másnál nagyobb mérték-
 ben megkülönbözteti a relációs rendszereket a nem relációs
 rendszerektöl, a relációs összekapcsolási /join/ operátor
 rendelkezésre állása. Altalában fogalmazva ez azt jelenti,
 hogy lehetöség van több táblából adatok kiválasztására 
 egyetlen SELECT müvelet segitségével. Erre egy példát
 adunk meg a 2.6 ábrában. Az "összekapcsolás" kifejezés abból
 a tényböl származik, hogy /a példában/ az SP és S táblák
 fogalmilag /konceptuálisan/ össze vannak kapcsolva a közös
 SNO oszlopuknál. Figyelje meg, hogy ebben a speciális eset-
 ben a WHERE klauzulában az S.SNO és SP.SNO oszlopokra hivat-
 kozásokat minösiteni kell a félreérthetöség elkerülésére. 
 2.6 ábra. Összekapcsolást tartalmazó példa
  ___ ___ ___ ___ ______ ___ ______
  SP SNO PNO ... S SNO ... CITY PNO CITY
  ___ ___ ___ ___ ______ ___ ______
  S1 P1 ... S1 London P1 London
  S1 P2 ... PLUS S2 Paris ==> P2 London
  . . . ---- . . . .
  . . . . . . .
  .  . . . . . .
  S2 P1 ... P1 Paris
  . . . . .
  SELECT SP.PNO,S.CITY
  FROM SP, S
   WHERE SP.SNO = S.SNO 
  sql.doc Page: 7 
 Feladat: Minden leszállitott alkatrészhez keresse vissza
 az alkatrész számot és az összes olyan városnak a nevét,
 melyben van olyan szállitó, aki az alkatrészt szállitja. 
 Beépitett függvények 
 Az SQL speciális beépitett függvény halmazt biztosit: COUNT,
 SUM, AVG, MAX, MIN és COUNT(*) /A "*" az érintett tábla egy
 teljes sorára utal./. A 2.7 ábrában adunk meg példákat. Az
 utólsó példa a GROUP BY klauzulát is mutatja, melyet egy táb-
 lának /konceptuálisan/ csoportokra osztására használunk ugy,
 hogy egy függvény, például SUM, alkalmazható legyen minden
 egyes csoportra. /Egyébként figyelje meg, hogy az elsö három
 példa mindegyike egysoros SELECT./ 
 2.7 ábra. Példák SQL beépitett függvényekre
  Eredmény:
  Szállitók száma: SELECT COUNT (*) 5
  FROM S
  Az alkatrészeket SELECT COUNT (DISTINCT SP.SNO) 4
   szállitó szállitók FROM SP
  száma
  P2 teljes mennyi- SELECT SUM (SP.QTY) 1000
  sége: FROM SP
  WHERE SP.PNO = 'P2'
  ___ ____
   PNO QTY
  ___ ____
  Az egyes leszálli- SELECT PNO, SUM (SP.QTY) P1 600
  tott alkatrészekhez FROM SP P2 1000
  tartozó alkatrész GROUP BY SP.PNO P3 400
  szám és teljes meny- P4 500
  nyiség P5 500
  P6 100 
 2.4 CURSOR MÜVELETEK 
 Mint ahogyan a 2.3 alfejezetben már emlitettük, többsoros SELECT müvele-
 tek közvetlenül nem hajthatók végre a szabványos SQL-ben. A dolgok ilyen
 állásának az az oka, hogy a szabvány elsödlegesen olyan programozási
 nyelvekkel kapcsolatban foglalkozik az SQL használatával, mint például
 a PL/I és COBOL, és az ilyen nyelvek általában nincsenek jól "felszerel-
 ve" azzal, hogy halmazokkal /melyek több sorból állnak/ egyedülálló ope-
 randusokként foglalkozzanak. Tehát az amire szükség van, az egy mecha-
 nizmus egy ilyen halmazon /készleten/ történö lépésenkénti keresztül ha-
 ladáshoz és a sorok egyenkénti kiválasztására; a cursorok ilyen mecha-
 nizmust biztositanak. A cursor egy SQL tárgy /objektum/, amely egy spe-
 cifikus SELECT müvelettel van kapcsolatba hozva /megfelelö deklaráción
 keresztül/./*/ Ahhoz hogy hozzáférjen azokhoz a sorokhoz, amelyek ezen
 SELECT-nek megfelelnek, a felhasználónak a következöket kell tennie:  
 /a/ OPEN /meg kell nyitnia/ a cursort, mely /fogalmilag/
  a SELECT végrehajtását eredményezi és ennek következté-
  ben azonositja a megfelelö sorok halmazát;
  sql.doc Page: 8 
 /b/ Ismétlödöen használnia kell a FETCH-t a megnyitott cur-
  soron, mely /minden egyes végrehajtásá 242e42c nál/ tovább lépteti
  a cursort a következö sorra a SELECT-en /kiválasztott/
  halmazban és visszanyeri ezt a sort; és végül
 /c/ CLOSE /le kell zárnia/ a cursort, amikor az összes szük-
  séges sor feldolgozása már megtörtént.  
 ___________________
 * Pontosan megfogalmazva egy specifikus "lekérdezési kife-
  jezéssel". Lásd a 6.2 és 9.1 alfejezeteket. 
 ___________________ 
 2.8 ábra. Példa cursor használatára 
  EXEC SQL DECLARE C CURSOR FOR
  SELECT SP.SNO, SP.QTY
   FROM SP
  WHERE SP.PNO = 'P2' ;
  DECLARE X CHAR (5) ; 
  DECLARE Y FIXED DEC (5) ;
  DECLARE Z FIXED DEC (3) ;
  EXEC SQL OPEN C ;
  DO WHILE more rows to come ;
  EXEC SQL FETCH C INTO :X, :Y ;
  IF a row was found THEN
  DO :
  process X and Y ;
  EXEC SQL UPDATE SP
  SET QTY + :Z
  WHERE CURRENT OF C ;
  END ;
  END;
  EXEC SQL CLOSE C; 
  Az UPDATE és DELETE speciális alakjai is biztositva
 vannak annak a sornak az aktualizálására vagy törlésére,
 amelyben a cursor éppen elhelyezkedik. Erre a 2.8 ábrában
 adunk meg egy példát /vázlatosan, sok fontos részlet kima-
 radt/.
  Megjegyzés: mint ahogyan a 2.1 alfejezetben már meg-
 emlitettük, az SQL szabvány számos különbözö módszert enged
 meg egy alkalmazási programból SQL müvelet meghivására.
 A 2.9 ábra bemutatja a legáltalánosabb módszert, mely SQL
 utasitásoknak közvetlenül a program forrás szövegbe történö
 beágyazása. A beágyazott SQL utasitásokat EXEC SQL elötaggal kell
 ellátni azért, hogy könnyen felismerhetö legyen. Ezek az uta-
 sitások tartalmazhatnak hivatkozásokat /utalásokat/ Host nyelvü
 változókra; az ilyen referenciák elé kettöspontot /:/ kell
 elhelyezni, ismét felismerési célokra. A további részleteket
 lásd a 3.2 alfejezetben vagy a 10. fejezetben.    
  sql.doc Page: 9 
 2.9 ábra. CREATE VIEW /példa/ 
  CREATE VIEW LS (SNO, SNAME, STATUS)
  AS SELECT S.SNO, S.SNAME, S.STATUS
   FROM S
   WHERE S.CITY = 'London' 
 2.5 NÉZETEK 
 Emlékezzünk vissza a 2.2 alfejezetböl arra, hogy egy nézet
 /vagy "viewed table" /nézet tábla / / virtuális tábla -
 vagyis olyan tábla, amely valójában "nem létezik", de a
 felhasználó számára ugy látszik, mintha létezne. A nézeteket
 közvetlenül nem támogatják a saját tárolt adataik; ehelyett
 ezek definiciói, más táblák /alap táblák és/vagy nézetek/ ki-
 fejezéseivel vannak megadva az adatbázis definició részeként.
 Egy nézet definicióra a 2.9-es ábrában adunk meg példát.
  Az LS /"London suppliers" /londoni szállitók// nézet
 egyfajta ablakként müködik, melyen keresztül a felhasználó
 az S alap táblában lévö azon sorok SNO, SNAME és STATUS érté-
 keit /csak ezeket/ láthatja, melyekhez a London CITY érték
 /csak ez az érték/ tartozik. Az ezt a nézetet definiáló
 SELECT nem kerül végrehajtásra a nézet létrehozásakor, hanem
 erre egyszerüen csak emlékezik a rendszer valamilyen módon.
 Azonban a felhasználó számára ugy tünik, mintha ténylegesen
 létezne LS nevü tábla az adatbázisban. A 2.10-es ábra az ehhez
 a táblázathoz kiadott visszanyerésre mutat példát. 
 2.10 ábra. Egy nézethez kiadott visszanyerés /példa/
   ---
  SELECT LS. SNO  Eredmény: SNO
  FROM LS   ---
  WHERE LS.STATUS < 50  S1
   S4 
  Egy nézethez kiadott müveletek kezelése /konceptuálisan/
 ugy történik, hogy helyettesitik a nézetre hivatkozásokat a
 nézet definiciójával /vagyis azzal a SELECT müvelettel, amelyre
 a rendszer emlékezett/. A rendszer igy logikailag "merges"
 /összefésüli/ a 2.9 ábra SELECT-jét a 2.10 ábra SELECT-jével
 azért, hogy megkapja a 2.10-es ábra módositott SELECT-jét. 
 2.11 ábra. Összefésült SELECT utasitás
   --- 
  SELECT S.SNO Eredmény: SNO
  FROM S  ---
  WHERE S.STATUS < 50  S1
  AND S.CITY = 'London'  S4 
  A módositott SELECT most a normál módon hajtható végre.
 Más szavakkal a nézeten az eredeti SELECT át van alakitva
 egy ekvivalens SELECT-té az alapul szolgáló alap táblán. Az
 aktualizálási müveletek kezelése hasonló módon történik;
 azonban a nézeteken az aktualizálási müveletekre számos kü-
 lönbözö megszigoritás érvényes, melyeknek a részletei a jelen
  sql.doc  Page: 10 
 fejezet vizsgálati körén tulnyulnak. Kissé leegyszerüsitve a
 dolgokat, a szabványos SQL csak akkor engedi meg egy nézet ak-
 tualizálását, ha ez egyetlen alapul szolgáló alap tábla egy-
 szerü sor és oszlop részhalmazát reprezentálja /például nem
 egy összekapcsolás/. A további részleteket lásd a 8. fejezet-
 ben.
  A nézetekre két további példa /mindkettö nem aktuali-
 zálható/ látható a 2.12-es ábrában. 
 2.12 ábra. További nézet példák 
  CREATE VIEW PQ (PNO, SUMQTY)
  AS SELECT SP.PNO, SUM (SP.QTY)
  FROM SP
  GROUP BY SP.PNO
  CREATE VIEW CITY_PAIRS (SCITY, PCITY)
  AS SELECT S.CITY, P.CITY
  FROM S, SP, P
  WHERE S.SNO = SP.SNO AND SP.PNO = P.PNO 
 2.6 ADAT VEZÉRLÉS 
 Mint ahogyan a 2.1-es alfejezetben is megemlitettük, az SQL
 lehetöségeket biztosit adat vezérléshez valamint adat defi-
 niáláshoz és adat manipuláláshoz. Az adat vezérlö lehetö-
 ségek három kategóriába csoportosithatók: /a/ hiba elháritás
 és konkurencia, /b/ adat védelem és /c/ integritás. 
 Hiba elháritás és konkurencia 
 A szabványos SQL támogatja a tranzakció fogalmat. A tranzakció
 kezelést valamint a hiba elháritás és konkurencia ezzel kap-
 csolatos fogalmait tartalmazó oktatási anyag a szerzönek
 az An Introduction to Database Systems: /az adatbázis rend-
 szerek bevezetése/: Volume 1 /1-es kötet/ /4. kiadás, Addison
 Wesley, 1985./ könyvében található. A tranzakció kezeléséhez
 az SQL jellemzök részletes tárgyalását a 3. fejezetre halaszt-
 juk; az alábbiakban csak egy nagyon rövid, vázlatos áttekintést
 adunk meg. 
 - Egy tranzakció egy olyan müveletsorozat, amely garantáltan 
  atomi /atomic/ a hibaelháritás és a konkurrencia szempontjá-
  ból. Minden tranzakció vagy COMMIT /normál befejezés/ vagy 
  ROLLBACK /rendellenes befejezés/ végrehajtásával fejezödik be. 
 - Egy adott T1 tranzakció által végrehajtott adatbázis aktu-
  alizálások semmilyen ettöl eltérö T2 tranzakció számára nem 
  láthatók mindaddig, amig a T1 végre nem hajt egy COMMIT-ot. 
  A COMMIT eredményeként a tranzakció végrehajtotta összes 
  aktualizálás más tranzakciók számára láthatóvá válik; az i-
  lyen aktualizálások számára garantálva van, hogy sohasem tör-
  lödnek. Ha ehelyett a tranzakció ROLLBACK-ot hajt végre, a 
  tanzakció végrehajtotta összes aktualizálás törlödik.  
  sql.doc Page: 11 
 - A konkurens /egyidejü/ tranzakciók sorozata /készlete/
  interleaved párhuzamosan történö végrehajtásának sorba
  rendezhetönek kell lennie abban az értelemben, hogy ugyanazt 
  az eredményt kell létrehoznia, mint ugyanezen tranzakciók 
  egyenkénti, valamilyen sorrendben történö végrehajtásának. 
 Adat védelem 
 SQL-ben az adatvédelemnek /security/ két aspektusa van, a né-
 zet mechanizmus és a GRANT opció. Elöször, nézetek használha-
 tók érzékeny adatoknak nem meghatalmazott felhasználóktól való
 elrejtésére. Az ilyen módon használható nézetekre néhány példa 
 a 2.13-as ábrában látható. Az elsö csak a vörös alkatrészek-
 hez tartozó információkat fedi fel; a második csak azokhoz az
 alkatrészekhez tartozó információkat fedi fel /mutatja meg/,
 melyeket a nézet felhasználója adott meg; a harmadik elrejti
 a szállitó állapot információkat; és a negyedik megadja az
 alkatrészenkénti étlagos mennyiséget, de nem adja meg az egyes
 mennyiségeket. Megjegyzés: A "SELECT*" egy olyan SELECT rövi-
 ditése, ami a tábla összes oszlopát megnevezi - vagyis egy
 olyan SELECT-é, mely a teljes sorhoz hozzáfér /a WHERE klauzu-
 lát kielégitö minden sorhoz./  
 2.13 ábra. Nézetek használata adatok elrejtésére /példák/ 
  CREATE VIEW RED_PARTS AS
   SELECT* FROM P WHERE P.COLOR = 'Red'
  CREATE VIEW MY_PARTS AS
  SELECT* FROM P WHERE P.PNO IN
   (SELECT SP.PNO FROM SP
   WHERE SP.SNO = USER)
  CREATE VIEW STATUS_HIDDEN AS
   SELECT S.SNO, S.SNAME, S.CITY FROM S
  CREATE VIEW AVG_QTYS (PNO, AVGQTY) AS
   SELECT SP.PNO, AVG (SP.QTY) FROM SP GROUP BY SP.PNO 
  A második a GRANT müvelet. Ahhoz, hogy egyáltalán bármi-
 lyen SQL utasitás végrehajtásra kerülhessen, a felhasználónak
 megfelelö privilégiummal kell rendelkeznie az érintett müvelet
 és operandus kombinációjához /egyébként az utasitás figyel-
 men kivül fog maradni/. A lehetséges privilégiumok a SELECT,
 UPDATE, DELETE és INSERT, melyek minden egyes esetben a kér-
 déses táblán /alap tábla vagy nézet/ a jelzett müveletet végre-
 hajtásának privilégiumát reprezentálják. UPDATE esetében a 
 privilégium specifikus oszlopokra korlátozható. A privilégi-
 umok hozzárendelése a következöképpen történik:
 - Egy felhasználó, aki egy táblát létrehoz, automatikusan
  megkapja ezen a táblán az összes alkalmazható privilégi-
  umot "with the grant option" /a grant opcióval/.
 - Bármelyik felhasználó, akinek "with the grant option"
  /a grant opcióval/ egy privilégium van a birtokában,
  átadhatja azt a privilégiumot más felhasználónak, ezen-
  kivül opcionálisan tovább adhatja a grant opciót más fel-
  használónak /ugy hogy most ez a felhasználó haladhat 
  tovább a privilégiumnak egy harmadik fél számára tör-
  sql.doc Page: 12 
  ténö átadásához, és igy tovább/.
 - A privilégiumok megadása a GRANT opció segitségével
  történik, mely az adatbázis definició részeként van
  megadva /vagyis a sémában/. 
  A GRANT-ra néhány példa a 2.14-es ábrában látható. 
 2.14 ábra. GRANT példák 
  GRANT INSERT, DELETE, UPDATE ON SP TO JOE
  GRANT SELECT ON SP TO ALICE WITH GRANT OPTION
  GRANT UPDATE (STATUS) ON S TO JUDY
  GRANT DELETE ON SP TO BONNIE, CLYDE 
 Integritás 
 Az "integrity" /integritás/ kifejezés az adatbázisban az
 adatok helyességére, pontosságára utal. A szabványos SQL
 lehetövé teszi bizonyos adatbázis integritás követelmények
 definiálását /a CREATE TABLE részeként/; minden aktualizálás,
 amely bármelyik elöirt követelményt megszegné, visszautasi-
 tásra kerül és az adatbázis változatlan marad. A lehetsé-
 ges követelmények a következök:
 - NOT NULL: bármelyik oszlophoz elöirható. Egy ilyen osz-
  lopba null érték bevitelére irányuló minden kisérlet visz-
  szautasitásra kerül. /Lásd a 3. alfejezetben a null érték
  tárgyalását./
 - UNIQUE: bármelyik oszlophoz vagy oszlopok kombinációjá-
  hoz elöirható, feltéve, hogy a NOT NULL ugyancsak elö
  van irva minden ilyen oszlophoz. Visszautasitásra fog
  kerölni minden kisérlet, melynek során az elöirt oszlop-
  ban vagy oszlop kombinációban valamilyen meglévö sorral
  azonos értékü sort próbálnak bevinni.    
  A teljesség érdekében két további integritás jellemzöt
 is meg kell emliteni: adat tipus ellenörzés és "the check
 opcion" /a check opció/. Elöször, az SQL vissza fog utasitani
 minden kisérletet, mely az adat tipus specifikációk elöirá-
 sait megszegné - vagyis minden olyan kisérletet, melynek so-
 rán karakter füzér értéket helyeznénk be DECIMAL-ként defi-
 niált oszlopba. Másodszor az SQL a WITH CHECK OPTION klau-
 zulát is támogatja a CREATE VIEW-ben. A részleteket lásd a 
 8. fejezetben. 
 2.7 NÉHANY ELTÉRÉS DB2-TÖL 
 A DB2-t vagy valamilyen más meglévö SQL implementációt ismerö
 olvasók számos különbséget fognak észrevenni a jelen fejezet-
 ben leirtak szerinti SQL és a jelenleg implementált SQL között.
 Az alábbiakban vázlatosan megadunk ezen eltérések közül néhá-
 nyat. Megjegyzés: az alábbiakban a DB2 jellemzöiként azonosi-
 tott /rövidség kedvéért/ jellemzök nagy részének megvan a 
 közvetlen megfelelöje sok más SQL termékben.  
  sql.doc Page: 13 
  1. DB2-ben az adat manipulálási müveletek, a CREAT TABLE,
 a CREAT VIEW és a GRANT müveletek /és számos más olyan müvelet
 is, ami a szabványos SQL-ben egyáltalán nem jelenik meg/ min-
 degyike mind interaktiv módon, mind pedig egy programból meg-
 hivható. Szabványos SQL-ben ezze ellentétben:
 /a/ Csak adat manipulálási müveletek hivhatók meg mind inter-
  aktiv módon, mind pedig egy programból;
 /b/ CREATE TABLE, CREATE VIEW és GRANT müveletek csak egy
  "schema" /séma/ szöveg összefüggésében /context/ hivha-
  tók meg - vagyis az adatbázis definició részeként; és
  miközben a szabvány nem irja elö, hogy a rendszerbe ho-
  gyan viszik be az adatbázis definiciót /lásd az alábbi
  következö pontot/ ugy látszik, mintha az adatbázis defi-
  niáló interfész valami olyan volna, amely különbözik
  mind egy hagyományos interaktiv interfésztöl, mind pe-
  dig egy hagyományos programozási interfésztöl. /*/
 ____________________
 * A szabványban a definiáló és manipulativ müveletek szétvá-
 lasztása szándékosan történt: lehetövé tette, hogy a bizottság
 elkerüljön bizonyos olyan problémákat, amelyek abból a lehetö-
 ségböl származnak, hogy ugyanahhoz a táblázathoz a kétfajta
 müveletet egymással "keverve" hajtsák végre. 
  2. Az elözö pontból továbbhaladva: egy séma fogalma mint
 ilyen egyáltalán nem létezik DB2-ben. A DB2 SQL-t mindig arra
 szánták, hogy rendkivül dinamikus legyen - minden müvelet ren-
 delkezésre áll minden összefüggésben /legalábbis minden olyan
 összefüggésben, amelyben értelme van/ és ebbö következik,
 hogy lehetöség van például arra, hogy bármikor interaktiv mó-
 don uj alap táblát hozzanak létre. Ezzel ellentétben a séma
 fogalom meglehetösen statikusnak látszik - jóllehet /mint
 ahogy fent is jeleztük/ az a mechanizmus, amellyel a sémát
 a rendszer számára ismertté teszik /vagyis a "schema language
 processor" /séma nyelv processzor/ nincs elöirva a szabványban
 és ebböl következik, hogy egy dinamikus, DB2-szerü módszer
 lehetösége nincs teljesen kizárva. 
  3. A DB2 támogat néhány további definiciós müveletet
 - ALTER TABLE, DROP TABLE és DROP VIEW /valamint számos na-
 gyobb mértékben fizikailag orientált müveletet, ilyen pél-
 dául a CREATE/DROP INDEX és CREATE/DROP TABLESPACE/. 
  4. A DB2 lehetövé teszi egy többsoros SELECT közvetlen
 interaktiv végrehajtását cursor használata nélkül. 
  5. Egy DB2 cursor deklaráláshoz szükség van FOR UPDATE
 klauzulára, ha egy UPDATE ... WHERE CURRENT müvelet fog vég-
 rehajtódni ezen cursor használatával. 
  6. DB2-ben a konkurencia /egyidejü/ vezérlés zároláson
 /locking/ alapul. Rendszerint a tesztelés, beállitás és zá-
 rolások feloldási müveletei teljesen implicit müveletek, de
 a DB2 támogat egy explicit LOCK TABLE müveletet.  
  sql.doc Page: 14 
  7. DB2-ben az interleaved végrehajtásokra nincs garan-
 tálva, hogy azok sorba rendezhetöek, kivéve ha minden tranz-
 akcióhoz a BIND parancsban elö van irva az RR /"repeatable
 read" /ismételhetö olvasás/ /opció./ Megjegyzés: a BIND egy
 parancs a DB2 SQL compilerhez nem pedig DB2 SQL utasitás.
 Nincs megadva az alkalmazási programban. 
  8. A DB2 támogat egy REVOKE müveletet egy elözöleg meg-
 adott privilégium eltávolitására /megszüntetésére/. A DB2
 ezenkivül nagyszámu további privilégiumot is támogat, a szab-
 ványos SQL által támogatott privilégiumokon tul és azok felett. 
  9. A DB2 támogatja a nem null alapértékeket /a CREATE
 TABLE-ben és ALTER TABLE-ben a NOT NULL WITH DEFAULT megadásán
 keresztül/. Ezek az értékek kerülnek felhasználásra nulla érté-
 kek helyett hiányzó /nem megadott/ oszlopok esetén az INSERT
 müveletekben. A definició szerint az alapértékek a következök:
 nulla /numerikus oszlopokhoz/, space-k /fix hosszuságú karak-
 ter füzér oszlopokhoz/ és az üres karakter füzér /változó
 hosszuságú karakter füzér oszlopokhoz/. Megjegyezzük, hogy
 az SQL szabvány nem támogat változó hosszuságú karakter füzér
 adat tipust. 
  10. DB2-ben az egyértéküség a CREATE INDEX-ben van elö-
 irva, nem pedig a CREATE TABLE-n. Nincs olyan követelmény, hogy
 NOT NULL-nak érvényesnek kell lennie az egyértéküségi speci-
 fikációban emlitett minden oszlopra. 
  11. A DB2 tartalmazza a katalógusnak nevezett rendszer
 táblák halmazát, mely /lényegében/ az adatbázis definiciót
 vagy sémát tartalmazza. A szokásos SQL SELECT utasitások hasz-
 nálhatók a katalógus lekérdezésére.  
 Megjegyzések:
 A következö véleményünket adjuk meg a tárgyalt eltéré-
 sekre vonatkozóan /mindig figyelembe véve azt a feltéte-
 lezett tényt, hogy a szabvány fö célja a program hordoz-
 hatóság/. A megjegyzéseket a fenti 1-11-es szakaszok
 szerint számoztuk. 
  1. Kivánatosabb a DB2 megközelités. Kivánatos az a ké-
 pesség, hogy minden müvelet végrehajtásra kerüljön minden
 olyan szöveg összefüggésben, melynek értelme van /jólle-
 het természetesen esetleg nem nagyon fontos a program
 hordozhatósága szempontjából./ 
  2. Ugyanaz, mint 1. 
  3. Kivánatos az ALTER TABLE, DROP TABLE /stb./ támoga-
 tása. 
  4. Kivánatos cursor használata nélküli interaktiv
 többsoros SELECT végrehajtásának képessége.  
  sql.doc Page: 15 
  5. A FOR UPDATE klauzula egy hiba a DB2-ben; az X3H2-
 nek joga volt arra, hogy ezt eltörölje /de lásd a 6.3 fe-
 jezetben a "pozicionált UPDATE"-re tett megjegyzést./ 
  6. Nincs megjegyzés. 
  7. Kissé szerencsétlen dolog, hogy a DB2 "RR" opció
 a programon kivül van elöirva, mivel ez hatással lehet a
 program logikára /nem lényeges pont/. Egyébként nincs meg-
 jegyzés. 
  8. Kivánatos a REVOKE támogatása. 
  9. Kivánatos az alapértékek /lehetöleg felhasználó de-
 finiálta/ támogatása. Lásd a 11. fejezetet. 
  10. A CREATE INDEX-ben az UNIQUE megadása egy további
 DB2 hiba; az egyértéküség logikai tulajdonság és CREATE
 TABLE-hez tartozik, ez az amit a szabvány megkövetel.
 / A CREATE TABLE-n egy PRIMARY KEY klauzula megkövetelése
 még jobb lenne. Lásd a 11. fejezetet./ 
  11. Miközben nehéz meglátni, hogy az X3H2 hogyan irhatna
 elö egy szabványos katalógus struktúrát, a lényeg az, hogy
 általánositott alkalmazási programoknak legalábbis gyakran
 szükségük van katalógus információk, az általánositott termé-
 szetük miatti pontos, olvasására és értelmezésére. /Az ilyen
 általánositott alkalmazásra példa az IBM saját lekérdezést
 kezelö lehetösége /Query Management Facility, QMF/, amely egy
 ad hoc lekérdezö és jelentést iró "frontend" alrendszer mind
 DB2-höz, mind SQL /DS-hez./ Egy szabványos katalógus struk-
 tura hiánya valószinüleg súlyos korlátozásokat szab meg az
 ilyen alkalmazások hordozhatóságára. 
 Megjegyzések vége.                    
  sql.doc Page: 16 
  3
 -------- ----- ------ ----- ----- ----------------- 
 Elözetes ismeretek 
 3.1 ALAP ADAT TARGYAK  
   1. Az SQL szabvány egy nem definiált fogalommal kezdödik,
 a környezet fogalmával /vagyis az implementációnak kell
 elöirnia pontosan azt, hogy egy adott implementációnak mi
 az, ami egy környezetet alkot/. Minden környezet ugy van
 definiálva, hogy csak egyetlen adatbázist tartalmaz /vagyis
 minden alkalmazási program csak egyetlen adatbázison müködik/.
 Egy adott környezethez az adatbázis ugy van definiálva, hogy
 ez az ebben a környezetben lévö összes séma által definiált
 minden adatot magában foglal. Viszont minden egyes séma alap
 tábla definiciók halmazából, nézet definiciók halmazából és
 privilégium definiciók /GRANT müveletek/ halmazából áll. A
 privilégiumokat a 3.3-as alfejezetben tárgyaljuk; az alap
 táblákat és nézeteket az alábbiakban irjuk le. 
  2. Az adatbázisban lévö adatokat a felhasználó megneve-
 zett táblák gyüjteményeként észleli, melyek közül nincs két
 olyan, amelynek azonos neve lenne. Minden megnevezett tábla
 vagy alap tábla, vagy nézet tábla /röviditve nézet/. Az alap
 tábla "valós" tábla, - vagyis megnevezett, autonóm tábla
 /ahol "automóm" azt jelenti, hogy "semmilyen más táblák
 kifejezéseivel nincs definiálva"/. A nézet "virtuális" tábla
 - vagyis megnevezett, származtatott tábla /ahol "származta-
 tott" azt jelenti, hogy "nem autonóm"/. Az alap táblákat és
 nézeteket CREATE TABLE illetve CREATE VIEW müveletek hozzák
 létre; a szabvány semmilyen eszközt nem ir elö megsemmi-
 sitésükre. Megjegyzés: egy lekérdezés kifejezés /lásd késöbb
 a 9. fejezetben/ kiértékelésének eredménye ugyancsak egy
 származtatott tábla /nézethez hasonló/, de nincs elnevezve.
  Az ilyen tábla megszünik létezni azon utasitás végre-
 hajtásának befejezésekor, amelyik ennek a lekérdezés 
 kifejezésének a kiértékelését eredményezi. 
  3. Egy tábla az oszlop fejrészének sorából, valamint nulla
 vagy több adat érték sorból áll /általában különbözö idö pon-
 tokban különbozö számu adat sorbol/. Egy adott tábla eseten:
 - Az oszlop fejrész sor egy vagy több megnevezett oszlo-
  pot ir le /megadva többek között egy adat tipust minden
  ilyen oszlophoz/. Egy adott táblán belül nem lehet két
  azonos nevü oszlop.
 - Minden adat sor pontosan egyetlen értéket tartalmaz az
  oszlop fejrész sorban megadott minden oszlophoz. Ezen- 
  kivül egy adott oszlopban minden érték azonos adattipusú, 
  nevezetesen az ehhez az oszlophoz az oszlop fejrész
  sorban elöirt adat tipusu. Megjegyzes : Az " data row "
  /adat sor/ kifejezést rendszerint egyszerüen "row"/sor/-
  ra röviditjük.  
  sql.doc Page: 17 
  Megjegyzés: Itt követjük az SQL szabványt azzal, hogy
  a "value" /érték/ nem minösitett kifejezést használjuk
  arra utalásra, amely pontosabban skalár értéknek nevez-
  hetö /vagyis egyedi szám vagy karakter füzér, lásd az
  alábbi 4-es pont alatt/. A nem minösitett "value" /érték/
  használattal kapcsolatban az a probléma, hogy nagyon
  általános kifejezés és nagyon speciális jelentést kap,
  ezért nehézzé teszi, hogy általánosabb, nem skalár
  értékekröl - például egy lekérdezési kifejezés értékéröl
  beszélhessünk.Ebben a könyvben rendszerint a "scalar"
  /skalár/ vagy "scalar value" /skalár érték/ kifejezést
  fogjuk használni annak a ténynek a hangsulyozására, hogy
  a kérdéses érték skalár érték. Megjegyzés vége. 
  Két szempont merül fel a most tárgyalt definicióval kap-
  csolatban.
 - Figyelje meg, hogy nem történik emlités a sorok rendezéséröl.
  Egy tábla sorait nem tekintjük rendezetteknek.
   Lehetöség van, mint ahogyan a 2.3-as
  alfejezetben már láttuk, arra hogy rendezést irjunk elö
  azokra a sorokra, amelyek egy lekérdezésre válaszul 
  visszanyerésre kerülnek, de az ilyen rendezést semmivel
  sem szabad többnek tekinteni, mint ami a felhasználó 
  kényelmét biztositja - a rendezés nem része a "table"
  /tábla/ fogalmának.
 - Az elsö szemponttal ellentétben egy tábla oszlopait
  rendezettnek tekintjük balról jobbra haladva.Például 
  az S táblán /lásd a 2. fejezetben a 2.1 -es ábrát/ az
  SNO oszlop az elsö oszlop, SNAME oszlop a második oszlop
  és igy tovább./Valójában nagyon kevés olyan helyzet 
  van, melyben ez a balról jobbra rendezés jelentös es 
  még ezek is elkerülhetök kis alakitással /discipline/.
  A gyakorlatban általában javasoljuk az ilyen elkerülését. 
  Adott táblázatban a sorok számát ezen táblázat kardina-
  litásának nevezzük. Az oszlopok számát fokszámnak
  nevezzük. 
  4. A skalár értékek két alapvetö tipusuak, karakter fü-
 zérek/röviditve füzérek/ és számok. Megjegyzés: A specifikus
 adat tipusokat a 4.fejezetben tárgyaljuk.
  Ezenkivüla Host változókat és paramétereket
 ugyancsak ugy tekintjük, hogy azok skalár értékeket repre-
 zentálnak és ebböl következik, hogy a következö megjegyzések
 az ilyen változókra és paraméterekre is vonatkoznak; lásd a
 3.2-es alfejezetet.
 - Egy karakter füzér egy vagy több karekterböl álló 
  sorozat. Bármilyen két karakter füzér egymással összehason-
  litható; az ilyen összehasonlitások végrehajtása az imp-
  lementáció definiálta karakter összevetési /collating/
  sorrenddel összhangban történik. Ha két különbözö
  hosszuságu karakter füzért kell összehasonlitani,
  a rövidebbet konceptuálisan feltöltik jobboldalon
  space karakterekkel azért, hogy ugyanolyan hosszuságu
  legyen mint a hosszabb, mielött az összehasonlitás
  sql.doc Page: 18 
  végrehajtásra kerülne.
 - Egy szám vagy pontos vagy megközelitö szám.
  - Egy pontos számnak van egy pontossága /p/ és egy
  skálatényezöje /scale/ /q/, ahol p>=q>0 /és p>0/
  A szám p szignifikáns számjegyböl áll és a következö-
  vel egyenlö értékü
  n * ( 10** (-q))
  ahol n a p szignifikáns számjegy integer értéke /és
  ahol xx hatványra emelést jelent; jegyezzük meg azon-
  ban , hogy a szabványos SQL nem támogat exponenciális 
  operátort.
  - Egy megközelitö számnak van egy pontossága /p/, ahol
  p > 0. Az ilyen szám p szignifikáns számjegyü, elöje-
  les mantisszából /m/ és egy elöjeles exponensböl /e/
  áll és megközelitöleg az alábbival egyenlö értékü
  m * (10** e)   
  Bármilyen két szám összehasonlitható egymással; az ilyen
  összehasonlitások végrehajtása algebrai módon történik.
 - Minden karakter füzér hozzárendelhetö karakter füzér tipusu
  tárgyhoz /objektumhoz/. A forrás karakter füzért 
  konceptuálisan jobboldalon csonkitják vagy jobboldalon
  szóköz karakterekkel feltöltik /szükség szerint/ azért,
  hogy a cél tárgy hosszuságával azonos hosszuságuvá váljék,
  az értékadás végrehajtása elött.
 - Bármilyen szám; pontos vagy megközelitö, megadható meg-
   közelitö numerikus tipusu tárgyhoz.Csak pontos szám ad-
  ható meg pontos numerikus tipusu tárgyhoz. Mindkét esetben
  a forrás számot konceptuálisan átalakitják a cél tárgy
  pontosságára / és skálatényezöjének megfelelöen, ha szükséges/
  az értékadás végrehajtása elött.
 - Megjegyezzük, hogy a számok és karakter füzérek nem ha-
  sonlithatók össze egymással, ugyancsak érvényes az is,
  hogy szám nem adható meg karakter füzér tipus tárgyhoz, va-
  lamint karakter füzér nem adható meg szám tipusu tárgyhoz. 
  5. A null érték /röviditve null/ egy speciális skalár 
 érték, amely oszlop értékként jelenhet meg egy alap táblában
 vagy származtatott /derived/ táblában, de nem jelenhet meg
 Host változó vagy paraméter értékként/legalábbis nem közvet-
 lenül; lásd az m 5.3-as alfejezetet/. A null értéket arra szánták,
 hogy azt jelentse, hogy "hiányzik az iformáció" /például
 "érték ismeretlen" vagy " érték nem érvényes "/. A null rep-
 rezentálását az inplementáció definiálja; azonban ennek olyan-
 nak kell lennie, hogy a rendszer megkülönböztethesse a nullá-
 kat minden "know" /ismert/ /vagyis nem null/ értéktöl. A
 null-t az aritmetikai és skalár összehasonlitható operátorok
 a következöképpen kezelik:
 - Legyen A és B numerikus tipusu tárgyak. Ha A értéke 
  null, akkor a +A és -A kifejezések mindegyike a kiértékelés 
  alapján null.
  Ha A null vagy B null, vagy mindkettö null, akkor a
  következö kifejezések mindegyike
  A + B A - B A x B A / B 
  a kiértékelés szerint null.
  sql.doc Page: 19 
 - Legyen A és B összehasonlitható tárgyak. Ha A null vagy
  B null, vagy mindkettö null akkor /egy WHERE vagy
  HAVING klauzula kontextusában/ a következö kifejezések
   mindegyike
  A = B A < > B A < B A > B A <= B A >= B
  a kiértékelés szerint ismeretlen igaz érték /vagyis a
  kiértékelés eredménye nem az, hogy igaz , és nem az ,hogy
  hamis érték/. Az ismeretlen igaz értéket a következö
  igazság táblázatok definiálkják /T=tru /igaz/,
  F=false /hamis/, ? = ismeretlen/:
  AND | T ? F OR | T ? F NOT |
  ------------- ---------- -----
  T | T ? F T | T T T T | F
  ? | ? ? F ? | T ? ? ? | ?
  F | F F F F | T ? F F | T
  Két speciális operátor , IS NULL és IS NOT NULL, van
  megadva teszteléssel annak megállapitására, hogy egy
  adott skalár érték null vagy nem null. Lásd a 9.fe-
  jezetet. 
 - Az elözö pont dacára két null értéket egymással egyenlönek
  tekintünk /ezzel egyenértéküen megfogalmazva, egymás
  másolatainak tekintünk/ a másodpéldány elhagyás /DISTINCT/
  a csoportositás /GROUP BY/ és a rendezés /ORDER BY/
  céljaira. 
  Megjegyzések:
  1. Egy korábban tett megállapitást megismételve: A
  null-ok reprezentálásának olyannak kell lennie, hogy a
  rendszer megkülönböztethesse ezeket az összes nem-null
  értéktöl.Ebböl azonban nem következik, hogy a /például/
  következö összehasonlitás "A<>3" a kiértékelés szerint
  igaz, ha A null / a már elmagyarázottak szerint/.Ezért
  kissé félrevezetö dolog azt állitani /ahogy a szabvány
  állitja,/ hogy null egy érték; jobb lenne ugy tekinteni 
  ezt, mint egy hely foglalót egy értékhez, olyan érték-
  hez, ami jelenleg ismeretlen.
  2. Tulajdonképpen, az iró véleménye szerint, a
  null értékek /legalábbis az SQL -ben definiáltak szerinti 
  null értékek/ elhibázott dolgot jelentenek és egyáltalán 
  sohasem szabad lett volna bevenni a szabványba.
  Bizonyára elvitathatatlan , hogy az SQL tipusu null-ok
  nagyon furcsa és nem konzisztens viselkedést mutatnak,
  és gazdag hiba források, és zavart okozó források lehetnek
  /ahogyan ez már az elözöekben a WHERE, a HAVING a DISTINCT,
  a GROUP BY és ORDER BY paraméterekre vonatkozó megjegyzésekböl
  is látható/. A gyakorlatban vonzóbb megoldás lehet a hiányzó
  információknak olyan szokásos nem null értékkel történö
  reprezentálása, mint például a szóközök és a -1 /minusz egy/.
  Az SQL tipusu null-ok okozta problémák széles körü
  tárgyalása a szerzönek a Relational Database:
  Selected Writings /relációs adatbázis: válogatott irások
  / Addison - Wesley, 1986 / könyvében találhatók.
   Megjegyzés vége. 
  sql.doc Page: 20 
 3.2 MUDULOK, ELJARASOK, ÉS BEAGYAZOTT SQL 
  1. Az SQL-nek egy szabványos alkalmazói programozási 
 verziója definiálásának kisérlete során az X3H2 bizottság
 egy jelentös /jóllehet nem technikai / problémával került
 szembe: az olyan nyelveknek, mint például a COBOL és a PL/1,
 az ANSI szabványos verziói már definiálva vannak és már
 léteznek ANSI bizottségok /például a COBOL esetében X3J4/ ezen
 szabványos definiciók védelmére. Ezen szabványos nyelvek
 mindegyikének külön-külön kiterjesztése, ugy hogy tartalmazza
 a szükséges SQL függvényt, hatalmas mennyiségü munkával járna
 - ezenkivül olyan munkával, amelynek általában kevés köze
 lenne az adatbázis technológiához - és sok évvel késleltetné
 egy SQL szabvány megjelenését. Ebböl következöen az X3H2
 az ugynevezett modul nyelv megközelitést javasolta. 
  2. A modul nyelv lényegében egy kis nyelvböl áll tiszta
 SQL szintaxis formátumban SQL adat manipulálási müveletek
 kifejezéséhez. A modul nyelvben egy eljárás alapvetöen paraméter 
 deklarációk készletéböl és ezen paraméterek segitségével
 összeállitott egyetlen SQL utasitásból áll. Például:
  PROCEDURE DELETE_PART
  SQLCODE
  PNO_PARAM CHAR(6) ;
   DELETE FROM P WHERE P.PNO = PNO_PARAM ;
 Figyelje meg a /szükséges/ SQLCODE paramétert, melyet az el-
 járást meghivó programhoz egy visszatéritési kód visszaadására
 használunk. A nulla SQLCODE érték azt jelenti, hogy az utasitás
 sikeresen végrehajtódott és semmilyen kivételes állapot nem
 jött létre; +100-as érték azt jelenti, hogy nem volt olyan sor,
 amely kielégitette volna a kérést; negativ érték azt jelenti,
 hogy valamilyen hiba keletkezett.
  A fent bemutatott eljárás a következöképpen hivható meg
 egy PL/I programból:
  DCL RETCODE FIXED BINARY(15) ;
  DCL PNO_ARG CHAR(6) ;
  DCL DELETE_PART ENTRY (FIXED BINARY(15), CHAR(6)) ;
  ........
  PNO_ARG = 'P6' ; /* for example */
  CALL DELETE_PART (RETCODE, PNO_ARG) ;
  IF RETCODE = 0 THEN ...; /* delete operation succeeded */
  ELSE ...; /* some exception occurred */
 ahol:
 for example = például
 delete operation succeeded = törlési müvelet sikerült
 some exception occurred = valamilyen kivételes állapot jött
 létre.
 Megjegyzés: /azoknak az olvasóknak,akik esetleg nem ismerik
 aPL/I-et/: "DCL" egyszerüen a DECLARE-nek a szabványos PL/I
 röviditése; egy "ENTRY" deklaráció egyszerüen egy külsö entry
 pont vagy eljárás definiciója.
  A modul nyelv igy biztositja a képességet, olyan host
 nyelveken irt programok számára, mint például a PL/I,
 COBOL, stb., SQL adat manipulálási müveletek végrehajtására
 anélkül, hogy ezen nyelvek szintaxisában vagy szemantikájá-
  sql.doc  Page: 21 
 ban bármilyen változtatást kellene végrehajtani. Mindössze
 arra van szükség,hogy /a/ a host / befogadó rendszer/ képes
 legyen arra, hogy meghivjon olyan eljárásokat, amelyek más
 nyelven vannak irva és külön vannak compillálva, valamint
 hogy /b/ definiált összefüggés létezzen a host és a modul nyelv
 adat tipusai között argumentum átadási célokra. Más szavakkal
 a host nyelv szabvány és az SQL szabvány közötti összefüggés
 analóg /ténylegesen azonos/ két host nyelv szabvány közötti
 összefüggéssel: a host nyelvü program egy olyan külön compil-
 lált programot /vagyis külsö eljárást/ hiv meg, mely törté-
 netesen SQL -ben van irva, ahelyett, hogy a vizsgált host 
 nyelven vagy valamilyen más host nyelven lenne irva.
  3. Az X3H2 bizottság nem szükségképpen akarja /vagy eset-
 leg nem elsösorban azt akarja/, hogy a felhasználók ténylege-
 sen kódoljanak közvetlen hivásokat a modul nyelvhez, ugy mint
 ez a fenti példában látható. Ehelyett a normál müködési mód-
 szer SQL utasitások közvetlen beágyazása a host nyelvü prog-
 ram szövegébe, ugy mint ahogyan ez a 2. fejezetben a 2.2-es
 és 2.9-es ábrákban látható. A fenti közvetlen hivás példának 
 megfelelö beágyazott SQL példa ugy nézhet ki, mint az alábbi-
 akban látható példa. Megjegyzés: A példa nem teljes; az
 SQLCODE és PNO deklarációkat "EXEC SQL BEGIN DECLARE SECTION;"
 és "EXEC SQL END DECLARE SECTION;" utasitásokkal lehatárolt
 "beágyazott SQL deklaráló részen" belül kell beágyazni.
 /lásd a 10. fejezetet./
  DCL SQLCODE FIXED BINARY(15) ;
  DCL PNO CHAR (6) ;
  ........
  PNO = 'P6' ; /* for example */
  EXEC SQL DELETE FROM P WHERE P.PNO = :PNO ;
  IF SQLCODE = 0 THEN ...; /* delete operation succeeded */
  ELSE ...; /* dome exception occurred */
  ahol:
  for example = például
  delete operation succeeded = törlési müvelet sikerült
  some exception occurred = valamilyen kivételes állapot
  jött létre.
  Figyelje meg, hogy most sincs szükség a DELETE_PART eljárás 
 explicit definiálására. Azonban a "beágyazott SQL" az SQL 
 szabványnak mint olyannak, nem valódi része. Ehelyett a fent
 látható beágyazott SQL kód egyszerüen a korábban látható, köz-
 vetlen hivás verziónak /beleértve az explicit eljárás definiciót
 is/ egyszerüen a szintaktikai röviditéseként van definiálva.
 Egy beágyazott SQL implementálásnak biztositani kell valamilyen
 fajta preprocesszort, melynek hatása egy beágyazott SQL program 
 logikai átalakitása ekvivalens közvetlen hivásu verzióvá.
  Az X3H2 SQL specifikáció a COBOL-hoz, FORTRAN-hoz, Pascal-
 hoz és PL/I-hez az SQL beágyazott verzióit definiáló "mellekletek"
 vagy függelékek halmazát tartalmazza /melyek természetesen
 nem részei a szabványnak./ Az ilyen nyelvekbe az SQL beágyazása
 részleteinek leirását a 10. fejezetre halasztjuk. 
   4. Megjegyezzük, hogy a modul nyelv megközelités nem zárja
 ki eleve a host nyelvek esetleges kiterjesztésének lehetöséget
 ugy, hogy természetes SQL támogatást biztositsanak. Azonban az 
  sql.doc Page:  22 
 SQL szabvány explicit módon nem javasol semmifajta ilyen 
 természetes támogatást a korábbiakban vázolt okok miatt.
  5. A modul nyelv használatára megadunk egy másik példat 
 annak a szempontnak a bemutatására, hogy általában a para-
 méterek olyan mechanizmusként is szolgálnak, mellyel az értékek 
 visszaadhatók a meghivott programnak. Természetesen ezt a
 szempontot a fenti DELETE példa már bemutatta az SQLCODE
 paraméter speciális esetére.  
  PROCEDURE GET_WEIGHT
  SQLCODE
   PNO_PARAM CHAR(6)
  WEIGHT_PARAM DECIMAL(3) ;
  SELECT P.WEIGHT
  INTO WEIGHT_PARAM
  FROM P
  WHERE P.PNO = PNO_PARAM ;
 Lehetséges meghivás PL/I-böl: 
  DCL RETCODE FIXED BINARY (15) ;
  DCL PNO_ARG CHAR (6) ;
  DCL WEIGHT_ARG DECIMAL (3) ;
  DCL GET_WEIGHT ENTRY (FIXED BINARY (15) ;
  CHAR (6) , DECIMAL (3)) ;
  .........
  PNO_ARG = 'P6' ; /* for example  */ 
  CALL GET_WEIGHT RETCODE, PNO_ARG, WEIGHT_ARG ; 
  IF RETCODE = 0 THEN ... ; /* WEIGHT_ARG = retrieved value */
  ELSE ... ; /* some exception occurred */
 ahol:
 for example = például
 retrieved value = visszanyert érték
 some exception occurred = valamilyen kivételes állapot jött
 létre.   
 Beágyazott SQL verzió /ismét kihagyva a szükséges BEGIN és
 END DECLARE SECTION utasitásokat/: 
  DCL SQLCODE FIXED BINARY (15) ;
  DCL PNO CHAR (6) ;
  DCL WEIGHT DECIMAL (3) ;
  ......
  PNO = 'P6' ; /* for example */
  EXEC SQL SELECT P.WEIGHT
  INTO :WEIGHT
  FROM P
  WHERE P.PNO = :PNO ;
  IF SQLCODE = 0 THEN ...; /* WEIGHT = retrieved value */
  ELSE ...; /* some exception occured */
 ahol:
 for example = például
 retrieved value = visszanyert érték
 some exception occurred = valamilyen kivételes állapot jött
 létre. 
  sql.doc  Page: 23 
 3.3 ADAT VÉDELEM, INTEGRITAS ÉS TRANZAKCIO FELDOLGOZAS 
 Adat védelem 
  1. Az SQL szabvány tartalmazza egy meghatalmazás azonosi-
 tó fogalmát, mely informális módon ugy tekinthetö, mint az
 a név, amellyel valamilyen felhasználó a rendszer számára is-
 mert. Altalában a "user" /felhasználó/ kifejezést fogjuk
 használni a "authorization identifier" /meghatalmazást azono-
 sitó/ helyett a rövidség kedvéért; azonban jegyezzük meg,
 hogy a szabvány nem tartalmaz semmilyen ehhez hasonló formális
 "user" /felhasználó/ fogalmat. Minden sémának van egy hozzá-
 tartozó meghatalmazás azonositója; a meghatalmazás azonositó 
 által kijelölt felhasználó a "owner" /tulajdonosa/ az ebben
 a sémában létrehozott minden táblának és nézetnek. A környe-
 zetben nem lehet két olyan séma, melynek azonos a meghatalmazás
 azonositójuk.  
  2. Egy adott tárgyon /objektumon/ egy adott müvelet vég-
 rehajtásához a felhasználónak rendelkeznie kell a szükséges
 privilégiummal a müvelet és a tárgy ezen kombinációjához.
 Azok a tárgyak, amelyekre az ilyen privilégiumok érvényesek 
 az alap táblázatok és nézetek; a megfelelö müveletek a
 SELECT, INSERT, UPDATE, /megadott oszlopok/ és DELETE.Semmi-
 lyen speciális privilégiumra nincs szükség egy séma vagy
 alap tábla létrehozásához. SELECT privilégiumokra van
 szükség /minden hivatkozott táblázatban/ egy nézet létreho-
 zásához vagy egy cursor definiálásához. 
  3. Egy alap tábla tulajdonosa rendelkezik az összes
 privilégiummal ezen alap táblán. Egy nézet tulajdonosa rendel-
 kezik ezen a nézeten az összes olyan privilégiummal, melynek
 "make sense" / van értelme /:
 - Ha a nézet aktualizálható / lásd a 8. fejezetet / és a
  tulajdonos rendelkezik az alapul szolgáló táblán az
  INSERT és/vagy UPDATE és/vagy DELETE privilégiumokkal,
  akkor a tulajdonos a nézeten ugyanezekkel a privilégiumokkal
  rendelkezik.
 - Egyebként a tulajdonos a nézeten csak a SELECT privilégiummal
  rendelkezik. 
  4. Egy tárgy tulajdonosa az ezen tárgyra /objektumra/
 vonatkozó privilégiumokat megadhatja más felhasználóknak a
 GRANT müvelet segitségével /a sémában van megadva/. Ezenkivül
 ha az A felhasználó megad valamilyen P privilégiumot a B fel-
 használónak, akkor az A felhasználónak megvan az a választási
 lehetösége, hogy a P privilégiumot a B felhasználónak a 
 "with the grant opcion" /a grant opcióval/ adja meg /a GRANT
 müveletben a WITH GRANT OPTION /GRANT opcióval/ klauzulán 
 keresztül/. A GRANT opcióval egy privilégium megadása azt
 jelenti, hogy az a személy, aki a privilégiumot megkapja
 ugyancsak átadhatja ugyanezt a privilégiumot - a GRANT op-
 cióval vagy anélkül - valamilyen további felhasználónak.
 Egyik felhasználó sem adhat át olyan privilégiumot, mellyel
 nem rendelkezik.
  sql.doc Page: 24  
  5. Minden modulnak van egy hozzátartozó meghatalmazás
 azonositója /vagyis felhasználója/ is. Az ezen meghatalmazás
 azonositó által reprezentált felhasználónak rendelkeznie
 kell az ebben a modulban lévö összes SQL utasitáshoz tartozó
 minden szükséges privilégiummal. Megjegyezzük, hogy egyetlen
 modul /esetleg még egyetlen SQL utasitás is/ több sémára is
 hivatkozhat. 
  6. A táblákat /alap táblák és nézetek/ U.T. alaku két-
 részes név azonositja, ahol "U" egy felhasználó neve /megha-
 talmazás azonositó/ és "T" egy egyszerü /vagyis nem minösitett/
 azonositó. A különbözö sémákban definiált tábláknak azonos
 nem minösitett nevük lehet; igy például az U1.T. és U2.T nevek
 /ahol U1 és U2 két különbözö felhasználó név/ két különbözö 
 táblát azonosit. 
  7. Egy SQL utasitásban egy táblára való hivatkozás opci-
 onálisan kihagyhatja a név "U." részét /valójában ez a szoká-
 sos eset/. Az "U." rész kihagyása ekvivalens azon séma vagy
 modul meghatalmazás azonositójának megadásával, amelyben a
 referencia megjelenik. 
 Integritás 
  1. Egy alap tábla definiciója opcionálisan tartalmazhat 
 bizonyos integritás követelményeket. Minden aktualizálási mü-
 velet, mely valamilyen elöirt követelményt megszegne, vissza-
 utasitásra fog kerülni; az adatbázis változatlan marad és az
 SQLCODE egy implementáció definiálta negativ értékre áll be.
 A szabvány a következö integritás követelményeket támogatja:
 - NOT NULL: A tábla bármelyik oszlopához megadható. Egy
  ilyen oszlopba null érték bevitelére irányuló minden kisérlet
  figyelmen kivül fog maradni /visszautasitásra kerül/.
  Ha NOT NULL nincs elöirva egy adott oszlophoz, akkor erre
  az oszlopra meg van engedve, hogy null-okat tartalmazhasson.
 - UNIQUE: A tábla bármely oszlopához vagy bármely oszlop
  kombinációjához megadható. Minden ilyen oszlophoz vagy
  minden ilyen oszlop kombinációban lévö oszlophoz a NOT
  NULL-nak is megadottnak kell lennie. Visszautasitásra
  fog kerülni minden olyan kisérlet, melynek során a táblá- 
  ba olyan sort akarnak bevinni, mely a megadott oszlopban
  vagy oszlop kombinációjában ugyanolyan értéket tartalmaz,
  mint valamilyen már létezö sor. Ha az UNIQUE nincs meg-
  adva egy adott oszlophoz /oszlop kombinációhoz/, akkor
  meg van engedve, hogy ez az oszlop /kombináció/ ismétlödö
  értékeket tartalmazzon.
  Megjegyzés: Az integritás követelmények jóval szélesebb
  körének támogatása lenne kivánatos. Vagyis sürgösen
  szükség van elsödleges és idegen kulcsok támogatá-
  sára. Lásd a 11. fejezetet. Megjegyzés vége. 
  2. Egy aktualizálható nézet definiciója /lásd a 8.4-es al-
 fejezetet/ opcionálisan tartalmazhatja a WITH CHECK OPTION
 klauzulát. Egy ilyen nézetbe egy sor beszúrására vagy egy
  sql.doc  Page: 25 
 ilyen nézetben egy sor aktualizálására irányuló minden kisér-
 let, mely olyan, hogy az ujonnan beszurt vagy aktualizált re-
 kord nem elégiti ki a nézetet definiáló "search condition"
 /keresési feltételt/ /lásd a 8. fejezetet/ visszautasitásra
 fog kerülni; az adatbázis változatlan marad és beállitódik az
 SQLCODE egy implementáció definiálta negativ értékre. Megje-
 gyezzük, hogy ha a W nézet a V aktualizálható nézetböl szár-
 maztatott aktualizálható nézet, és a WITH CHECK OPTION meg
 van adva a V nézethez, a WITH CHECK OPTION automatikusan nem
 lép érvénybe a W nézethez, hanem ezt explicit módon elö kell
 irni, /ha kivánatos, azonban nehéz megállapitani azt a hely-
 zetet, amikor nem lenne kivánatos/.
  Megjegyzés: DB2-ben a CHECK opció csak akkor adható meg,
  ha a nézet aktualizálható és a nézet definició nem foglal
  magában al-lekérdezést. Ezt az anomáliát a szabványban
  elkerülik, mivel egy al-lekérdezést magában foglaló néze-
  tek nem aktualizálhatóként vannak definiálva. Azonban
  a szabvány megörzött egy másik DB2 hiányosságot, neveze-
  tesen azt, hogy a check opció nem örökölhetö. Tény, hogy
  a check opció meglehetösen különös jellemzöje a nyelvnek;
  az integritás követelmények megfelelöbb módon illenek
  az alap adatokhoz mint a nézetekhez. Ennek a szem-
  pontnak a további tárgyalása /és különösen a check opció
  tárgyalása/ a szerzönek az An Introduction to Database
  Systems: Volume 1 /adatbázis rendszerek bevezetése: I-es
   kötet/ /4. kiadás, Addison-Wesley, 1985/ könyvében talál-
  ható. Lásd még a jelen könyv 8.4-es alfejezetét is.
  Megjegyzés vége. 
 Tranzakció feldolgozás 
  1. Egy tranzakció olyan SQL /és esetleg egyéb/ müveletek
 sorozata, melyekröl garantálva van, hogy a legelemibb müvele-
 tek /"atomic"/ hiba elháritási és konkurencia vezérlési cé-
 lokra.  
  2. Ha egy program meghiv egy SQL müveletet és éppen
 nincs aktiv tranzakció ehhez a programhoz, akkor automatikusan
 inditásra kerül egy tranzakció. Egy SQL müveletnek ugyanazon
 program által történö minden ezt követö meghivását ugyanezen
 tranzakció részének tekintjük, mindaddig, amig a tranzakció
 be nem fejezödik. A tranzakciók tehát nem ágyazhatók egymásba. 
  3. Egy tranzakció vagy COMMIT müvelet /normál, vagy sike-
 res befejezés/ vagy egy ROLLBACK müvelet /egy rendellenes, vagy
 sikertelen befejezés/ végrehajtásával fejezödik be. A sikeres
 befejezödést "termination with commit" /befejezés a feladat
 teljesitésével/ -nek nevezzük; a sikertelen befejezödést "ter-
 mination with rollback" /befejezödés visszaállitásával/ -nak
 nevezzük. 
  4. Egy adott T1 tranzakció által végrahajtott adatbázis
 aktualizálások nem lesznek láthatóak semmilyen ettöl eltérö
 T2 tranzakció számára mindaddig, amig a T1 tranzakció COMMIT-tal
 /feladat végrehajtással/ be nem fejezödik.
  sql.doc Page: 26 
 A feladat teljesitésével történö befejezödés eredményeként a
 tranzakció végrehajtotta összes aktualizálás láthatóvá válik
 a többi tranzakció számára; az ilyen aktualizálások garan-
 táltan sohasem törölhetök /ez a "committed update"/ végrehaj-
 tott aktualizálás/ definiciója/. A rollback-kal /visszaálli-
 tással/ befejezés eredményeként a tranzakció által végrehaj-
 tott összes aktualizálás törlésre kerül; az ilyen aktualizá-
 lások sohasem lesznek láthatóak más tranzakciók számára. 
  5. Az egyidejü /konkurens/ tranzakciók készletének inter-
 leaved végrehajtása garantáltan sorrendbe rendezhetö abban
 az értelemben, hogy ugyanazt a hatást fogja végrehajtani, mint
 ugyanezen tranzakciók valamilyen /nem elöirt/ soros végrehaj-
 tása. A soros végrehajtás olyan végrehajtás, melyben a tranz-
 akciók végrehajtása egyenként történik, minden tranzakció
 befejezödik, mielött a következö tranzakció indulna.  
 3.4 ALAPVETÖ NYELV ELEMEK 
 Karakterek 
 A legprimitivebb nyelv elemek az alapul szolgáló karakter
 készlet egyes karakterei. Ezeket a karaktereket használjuk
 magasabb szintü /nem primitiv/ nyelv elemek felépitésére,
 valamint karakter füzér adat értékek létrehozására. A karakter
 készlet a nagybetükböl, A, B, .... Z, a kisbetükböl, a, b, ...
 c, a számjegyekböl, 0, 1, 2, ... 9, egy uj sor markerböl, /*/
 és a speciális karaktereknek nevezett egyéb karakterek kész-
 letéböl áll. A speciális karaktereknek legalább a következök
 mindegyikét tartalmaznia kell:
  % , ( ) < > . : = + - * /
 Plusz tartalmazniuk kell egy space /szóköz/ karaktert. A komp-
 lett karakter készlet és ehhez a karakter készlethez az össze-
 válogatási sorrend, egyaránt az implementáció által definiá-
 landó. 
 ----- ----- --------
 * Az uj sor marker opcionális. Az implementáció szabadon
 döntheti el a "end of line" /sor vége/ jelzését egy megkülön-
 böztetett karakter segitségével történö jelöléstöl eltérö
 valamilyen más módon, ha ugy dönt. 
 Literálok 
 A literálok /melyeket konstansoknak is neveznek, jollehet a
 "konstans" nem hivatalos szabványos kifejezés/ kétféle tipu-
 suak; karakter füzér /röviditve füzér/ és numerikus. Egy
 karakter füzér literál aposztrófok közé zárt karakterek soro-
 zatából áll; ilyen literálon belül magát az aposztróf karak-
 tert két egymást közvetlenül követö aposztróf reprezentálja.
 Példák: 
  '123 Main Street' 'PIG' '01234' 'honey don''t' 
  sql.doc  Page: 27 
 A numerikus literálok viszont kétféle tipusuak, pontos és meg-
 közelitö tipusuak. Egy pontos numerikus literál egy opcionális
 elöjelü decimális számból áll, tizedes ponttal vagy anélkül.
 Példák: 
  7.5 12.00 0.001 -4.75 
 Egy megközelitö numerikus literál tizedes ponttal rendelkezö
 vagy tizedes pont nélküli elöjeles vagy nem elöjeles deci-
 mális számból áll, melyet az E betü és egy opcionális elö-
 jelü decimális integer /egész szám/ követ. Példák: 
  4E3 -95.7E46 +364E-5 0,7E1 
 Egy literált ugy tekintünk, hogy a nyilvánvaló adat tipussal,
 hosszúsággal és pontossággal, vagy pontossággal és skálaté-
 nyezövel /az adat tipustól függöen/ rendelkezik ugy, ahogyan
 ezt a literál formátuma jelzi. Ezenkivül ugy tekintjük, hogy
 a literálok a NOT NULL tulajdonsággal is rendelkeznek. 
 Token-ek 
 A token-ek lexikális egységeket reprezentálnak a nyelvben.
 Egy token vagy egy határoló szimbólum vagy egy nem határoló
 szimbólum. Egy határoló szimbólum vagy egy karakter füzér literál,
 vagy a következö speciális szimbólumok valamelyike:
  , ( ) < > . : = + - * / <> <= >= 
 Egy nem határoló szimbólum egy numerikus literál, azonositó
 vagy kulcsszó. Az azonositó 18 karakternél nem hosszabb ka-
 rakter füzér. A karakterei közül az elsönek nagybetünek kell lennie;
 a többi nagybetük, számjegyek és az aláhúzás karakter /_ / bármi-
 lyen kombinációja lehet. A következök mindegyike azonositó:
  authorization identifiers /meghatalmazás azonositók/
  unqualified table names /nem minösitett tábla nevek/
  unqualified column names /nem minösitett oszlop nevek/
  range variable names /tartomány változó nevek/ /vagy "cor-
  relation names" /korreláció nevek/; lásd a 9.5-ös alfeje-
  zetet/
  cursor names /cursor nevek/
   module names /modul nevek/
  procedure names /eljárás nevek/
  parameter names /paraméter nevek/ 
 A kulcsszó egy név, amelynek valamilyen elöirt jelentése
 van magán az SQL nyelven belül. A kulcsszavak fentartott
 szavak /vagyis egyik kulcsszó sem használható azonositóként/.         
  sql.doc Page: 28 
 A kulcsszavak a következök: 
  ALL AND ANY AS
  ASC AUTHORIZATION AVG BEGIN
  BETWEEN BY CHEAR CHARACTER
  CHECK CLOSE COBOL COMMIT
  CONTINUE COUNT CREATE CURRENT
  CURSOR DEC DECIMAL  DECLARE
  DELETE DESC DISTINCT DOUBLE
  END ESCAPE EXEC EXISTS
  FETCH FLOAT FOR FORTRAN
  FOUND FROM GO  GOTO
  GRANT GROUP HAVING IN
  INDICATOR INSERT INT INTEGER
  INTO IS LANGUAGE LIKE
  MAX MIN MODULE NOT
  NULL NUMERIC OF ON
  OPEN OPTION OR ORDER
  PASCAL PLI PRECISION PRIVILEGES
  PROCEDURE PUBLIC REAL ROLLBACK
  SCHEMA SECTION SELECT SET
  SMALLINT SOME SQL SQLCODE
  SQLERROR SUM TABLE TO
  UNION UNIQUE UPDATE USER
  VALUES VIEW WHENEVER WHERE
  WITH WORK 
 Minden token-t opcionálisan bármilyen számu elválasztó kö-
 vethet, ahol az elválasztó egy space, egy uj sor marker, vagy
 egy megjegyzés. Minden nem határoló szimbólum token-t vagy
 egy elválasztónak, vagy egy határoló szimbólum token-nek kell
 követnie. A megjegyzés két egymást követö kötöjelböl /--/
 áll, melyet uj sor marker kivételével karakterek bármilyen
 sorozata, majd pedig egy uj sor marker követ. Megjegyzés:
 A következö alfejezetben bevezetett szintaktikai jelölés
 általában teljes mértékben figyelmen kivül hagyja az elvá-
 lasztókat.
  Egyik token számára sincs megengedve, hogy bármilyen
 space karaktert tartalmazzon, kivéve /természetesen/ egy ka-
 rakter füzér literált, ahol a beágyazott space karakterek
 meg vannak engedve, és szignifikánsak. 
 3.5 JELÖLÉS 
 Az SQL nyelv elemek szintaxisa ebben a könyvben a jól ismert
 BNF jelölés egyik variánsának segitségével van megadva. A
 variánsunk a következöképpen van definiálva:
 - A speciális karaktereket és nagybetüs anyagot pontosan
  ugy kell irni, ahogyan látható. Kisbetüs anyag olyan
  szintaxis kategóriát reprezentál, mely egy másik létreho-
  zási szabály tárgya /*/,
  és ebböl következik ,hogy /végül is/ a felhasználó
  által kiválasztott specifikus értékekkel kell helyettesiteni.  
  sql.doc Page: 29 
 ----- ----- -------
 * Ebben a könyvben azonban a létrehozási szabályok egy része
 a legalacsonyabb részletezési szinten van, ugy hogy az a sza-
 bály, amely egy azonositó felépitését definiálja, nem látható
 explicit BNF stilusban, hanem egyszerüen informális módon van
 leirva a szövegben. 
 - Függöleges vonalakat " | " használunk alternativák elvá-
  lasztására.
 - Szögletes zárójeleket " [ " és " ] " használunk annak jel-
  zésére, hogy az ezen zárójelek közé zárt anyag opcionális;
  vagyis egy vagy több /függöleges vonalakkal elválasztott/
  olyan tételt tartalmazó készletböl áll, melyböl legfeljebb
  egyet kell kiválasztani.
 - A kapcsos zárójeleket, "  " annak jelzésére használ-
  juk, hogy az ezen kapcsos zárójelek közé zárt anyag több
  /függöleges vonalakkal elválasztott/ olyan tételt tartalmazó
  készletböl áll, melyböl pontosan egyet kell kiválasztani.
  A példa kedvéért bemutatunk a "numerikus-literál" /informá-
  lis módon az elözö alfejezetben van definiálva/ szintaxis
  kategóriához egy létrehozási szabály készletet. 
  numeric-literal
   ::= exact-numeric-literal
  | approximate-numeric-literal
  exact-numeric-literal
  ::= [ + | - ] 
  approximate-numeric-literal
  ::= exact-numeric-literal E signed-integer
  signed-integer
  ::= [ + | - ] integer  
  Az "integer" kategória nincs tovább definiálva; vagyis ez
  egy "terminális kategória" ezen egyszerü példa szempontjából.
  Közbevetöleg megjegyezzük, hogy jóllehet a példában látható
  létrehozási szabályok tartalmaznak különbözö beágyazott spa-
  ce-ket olvashatósági okok miatt, egy numerikus literál token-
  -nek /lásd a 3.4-es alfejezetet/ nem szabad tartalmaznia
  semmilyen space-t.
  Mindegyik BNF jelölésünk lényegében ugyanaz volt,
  amit az SQL szabvány dokumentációjában is használtak.
  Azonban bevezetünk két további, saját egyszerüsitö konvenciót
  a következöképpen: 
 - Ha "xyz" egy szintaxis kategória, akkor "xyz-commalist"
   olyan szintaxis kategória, mely egy vagy több "xyz"-t
  tartalmazó listából áll, melyben minden szomszédos "xyz"
  párt egy vesszö választ el egymástól.
 - Ha "xyz" egy szintaxis kategória, akkor "xyz-list" olyan
  szintaxis kategória, mely egy vagy több "xyz"-t tartal-
  mazó listából áll, melyben minden szomszédos "xyz" párt
  legalább egy elválasztó /általában egy space/ választ el.   
  sql.doc Page: 30 
  Ennek a két szabálynak az a "nettó" hatása, hogy csök-
 kenti a szükséges létrehozási szabályok össz hosszuságát és/
 vagy számát. Az alábbiakban megadunk egy példát ezek haszná-
 latának bemutatására /a "sémához" tartozó elsö néhány létre-
 hozási szabály a 4. fejezetböl való/: 
  schema
  ::= CREATE SCHEMA
  AUTHORIZATION user
  [ schema-element-list ] 
  schema-element
  ::= base-table-definition
  | view-definition
  | grant-operation  
  base-table-definition
  ::= CREATE TABLE base-table
  (base-table-element-commalist) 
  base-table-element
  ::= column-definition
  | unique-constraint-definition 
 és igy tovább. 
  Megjegyzés: Világos áttekinthetöség és szabatossági okok
   miatt szándékosan nem mindig ugyanazokat a neveket hasz-
  náljuk a szintaxis kategóriákhoz, mint amit az SQL szab-
  vány. Az SQL szabvány kifejezései nem mindig különösen sze-
  rencsések. Például a szabvány a "tábla definició" /table de-
   finition/ nevet arra használja, hogy arra utaljon, amelyet
  mi az elözöekben "base table" /alap tábla definiciónak/ ne-
  veztünk, mely el akarja rejteni azt a /fontos/ tényt, hogy
  egy nézet is definiált tábla és ebböl következik, hogy egy
   "view definition" /nézet definició/-nak mindössze egy spe-
  ciális "table definition" /tábla definició/ esetnek kell
  lennie. Ezt a legutolsó gondolatmenetet kissé tovább foly-
  tatva: az SQL tulajdonképpen ambivalens a "table" /tábla/
   kifejezés jelentése szempontjából; esetenként vagy egy alap
  táblát vagy egy nézetet jelent, illetve esetenként specifi-
  kusan alap táblát jelent. Ebben a könyvben a "table" /tábla/
  kifejezést ugy használjuk, hogy minden fajta táblát jelent
  és "base table" /alap tábla/-t használunk, amikor specifikusan
  egy alap táblára gondolunk.
  Megjegyzés vége.         
  sql.doc Page: 31 
   4
 -------- ----- ------ -------- ----- ------ -
 Adat definició:
 A séma definiáló nyelv  
 4.1 SZINTAXIS 
 Ebben a fejezetben részletesen megvizsgáljuk az adatbázis
 definiálást. Emlékezzünk vissza a 2. fejezetböl, hogy egy
 adatbázist a séma definiáló nyelv segitségével létrehozott
 egy vagy több séma definiál. Ennek a nyelvnek a szintaxisa
 a következö: 
  schema
  ::= CREATE SCHEMA
  AUTHORIZATION user
  [schema-element-list] 
  schema-element
  ::= base-table-definition
  | view-definition
  | grant-operation  
  base-table-definition
  ::= CREATE TABLE base-table
  (base-table-element-commalist) 
  base-table-element
  ::= column-definition
  | unique-constraint-definition 
  column-definition
  ::= column data-type [NOT NULL [UNIQUE]]  
  unique-constraint-definition
  ::= UNIQUE (column-commalist)  
  view definition
  ::= CREATE VIEW view [(column-commalist)]
  AS query-specification
  [WITH CHECK OPTION 
  grant operation
  ::= GRANT privileges ON table TO grantee-commalist
  [WITH GRANT OPTION] 
  privileges
  ::= ALL [PRIVILEGES] | operation-commalist  
  operation
  ::= SELECT | INSERT | DELETE
   | UPDATE [(column-commalist)] 
  grantee
  ::= PUBLIC | user
  sql.doc Page: 32  
  Amint a szintaxis jelzi, egy séma egy CREATE SCHEMA
 klauzulából, egy AUTHORIZATION klauzulából és nulla vagy több
 CREATE TABLE müveletböl és/vagy CREATE VIEW müveletböl és/vagy   
 GRANT müveletböl áll. Az AUTHORIZATION klauzula azonositja
 az ebben a sémában létrehozott valamennyi alap tábla és/vagy
 nézet tulajdonosát, valamint az ebben a sémában levö valamennyi
 GRANT müvelet által megadott valamennyi privilégium adományo-
 zóját is. A nézetek tárgyalását a 8. fejezetre halasztjuk.
 Az alap táblákat és privilégiumokat a jelen fejezet 4.2-es
 és 4.3-as alfejezeteiben tárgyaljuk. 
  Megjegyzés: Az "CREATE SCHEMA" kifejezés kissé zavaró.
  Konzisztensebb lehettem volna, ha a müveletet /például/
  "CREATE DATABASE"-nek /adatbázis létrehozásnak/ /a
  CREATE TABLE-vel és CREATE VIEW-vel analóg módon/ nevezem.
  Egyébként miért ne lehetne /például/ CREATE TABLE DEFI-
  NITION /tábla definició létrehozás/ és CREATE VIEW DEFI-
  NITION /nézet definició létrehozás/ ? Ugyanilyen okból
  a "schema definition language" /séma definiáló nyelvnek/
  valójáben egyszerüen csak "schema language" /séma nyelv-
  nek/ kell lennie /a modul nyelvvel/ analóg módon.
  Megjegyzés vége. 
  Emlékeztetjük az olvasót arra, hogy a séma definiáló mü-
 veletek nem részei a modul nyelvnek és nem hivhatók meg egy
 hagyományos alkalmazói programból. 
 4.2 ALAP TABLAK 
 Most tárgyaljuk részletesen a CREATE TABLE müveletet. CREATE
 TABLE-t használunk új /üres/ alap táblák létrehozására. A
 szintaxis 
  CREATE TABLE base-table (base-table-element-commalist) 
 ahol "base-table" /alap tábla/ a nem minösitett név az újonnan
 létrehozott alap táblához /*/ és minden egyes alap tábla elem
 vagy egy oszlop definició, vagy egy UNIQUE követelmény defi-
 nició. Egy új alap tábla teljesen minösitett neve U.T, ahol
 U az a meghatalmazás azonositó, amely a CREATE TABLE müvele-
 tet tartalmazó séma AUTHORIZATION klauzulájában van megadva
 és T az ebben a müveletben elöirt azonositó.
 ___________________
 * valójában a név minösitett lehet, de ha ilyen, akkor a
 minösitönek a séma AUTHORIZATION /meghatalmazás/ klauzulában
 megadott meghatalmazás azonositónak kell lennie. 
  Egy oszlop definició viszont a következö alakot veszi
 fel 
  column data-type [ NOT NULL [UNIQUE]] 
 ahol "column" /oszlop/ a kérdéses oszlophoz tartozó nem minö-
 sitett név, "data type" / adat tipus/ az oszlop adat tipusát
  sql.doc Page: 33 
 adja meg, a NOT NULL és UNIQUE pedig a 3. fejezetben /3.3-as al-
 fejezet/ leirtak szerintiek. Az oszlopra az SQL adat manipu-
 lációs müveletekben a T.C névvel lehet hivatkozni, ahol T annak
 az alap táblának a minösitett, vagy nem minösitett neve, ame-
 lyik oszlopot tartalmazza, és C az oszlop definicióban meg-
 adott azonositó. /*/ 
 ___________________
 * Erre R.C névvel is lehet hivatkozni, ahol R egy olyan tar-
 tomány változó /vagy "correlation variable" /korreláció neve/,
 amelyik kiterjed /ranges/ a T egészére /lásd 9.5-ös alfejeze-
 tet/. 
  Egy UNIQUE követelmény definició a következö alakot ölti: 
  UNIQUE (column-commalist) 
 ahol minden "column" /oszlop/ a létrehozandó alap tábla egyik
 oszlopának a nem minösitett neve. Egy UNIQUE követelmény
 definiciójában megemlitett minden oszlopra elöirt NOT NULL-nak
 kell lennie. Ismét elmondjuk, hogy nézze meg a 3.3-as alfeje-
 zetben a további leirást. A következö oszlop definició 
  column-X data-type-X NOT NULL UNIQUE 
 az alábbi specifikáció röviditése  
  column-X data-type-X NOT NULL 
  ..........
  UNIQUE (column-x) 
 Lásd a 2. fejezet 2.3-as ábráját, melyben néhány példát adunk
 meg a CREATE TABLE-re. 
 Adat tipusok 
 A szabványos SQL a következö adat tipusokat támogatja: 
  CHARACTER [(length)]
  NUMERIC [(precision [ , scale])]
  DECIMAL [(precision [ , scale])] 
  INTEGER
  SMALLINT
  FLOAT [(precision)]
  REAL
  DOUBLE PRECISION 
 Megjegyzések:  
  1. A CHARACTER, DECIMAL és INTEGER CHAR-ra, DEC-re ill.
 INT-re rövidithetö. A SMALLINT rövidités nem oldható fel SMALL-
 INTEGER-re. Jegyezze meg azt is, hogy nincs SINGLE PRECISION.   
  sql.doc Page: 34 
  2. A "length" /hosszúság/, "precision" /pontosság/ és
 "scale" /skálatényezö/ mindegyike elöjel nélküli decimális
 integer /"length" és "precision" esetében nagyobb mint nulla/.
 Egy adott NUMERIC vagy DECIMAL oszlop esetén a "precision"
 értékének nagyobbnak mint, vagy egyenlönek kell lennie a
 "scale" értékével. A "length"-hez, "scale"-hez és "precision"-
 hoz az alap értékek 1, 0 illetve implementáció definiálta ér-
 ték. 
  3. Az INTEGER-nek és SMALLINT-nek p1 illetve p2 imple-
 mentáció definiálta pontossága van /mindkét esetben nulla
 scale-vel/, úgy, hogy p1>=p2. 
  4. A tényleges pontosság és skálatényezö /scale/ a NUMERIC-
 hoz a megadott "precision" és "scale". A DECIMAL tényleges pon-
 tosságának nagyobbnak mint, vagy egyenlönek kell lennie a meg-
 adott "precision"-nal a tényleges scale-nek a megadott "scale"-
 nek kell lennie. 
  5. A FLOAT tényleges pontosságának nagyobbnak mint, vagy 
 egyenlönek kell lennie a megadott "precision"-nal. A REAL és a 
 DOUBLE PRECISION p1 illetve p2 implementáció definiálta pon-
 tosságúak, úgy, hogy p1>p2. 
  Megjegyzés: A megadott adat tipusok csak az alapvetöen
  fix hosszúságú karakter füzérek, és a fix és lebegöpontos
  decimális számok. Az adat tipusoknak mindössze ezen né-
  hányra korlátozásának az oka feltételezhetöen az volt,
  hogy csak ezek az adat tipusok azok, amelyek közösek
  minden fö host nyelvhez, /*/ de sajnos a bizottság nem látta
  alkalmasnak, hogy más általánosan szükséges tipusokat is
  bevigyen, ilyenek a dátumok, idöpontok, pénz értékek,
  bináris számok, bit füzérek, logikai értékek, változó
  karakter füzérek, stb. Ami a bevitt /figyelembe vett/ spe-
  cifikus tipusokat illeti, ezek legalábbis kissé zavarónak
  látszanak. Megjegyzés vége. 
 ___________________
 * Ez a kijelentés túlegyszerüsités. Az egyetlen adat tipus,
 amely valóban közös minden host nyelv esetén, valószinüleg 
 a fix hosszúságú karakter füzérek. Igy például ha egy SQL
 tábla tartalmaz egy DECIMAL/5.3/-ként definiált oszlopot,
 akkor ez az oszlop minden probléma nélkül elérhetö egy PL/I
 programból, mivel a PL/I egy pontosan analóg adat tipust tar-
 talmaz. FORTRAN programból is elérhetö, de itt lehetnek prob-
 lémák is, mivel a FORTRAN nem tartalmaz egy pontosan analóg
 adat tipust; igy ezen DECIMAL/5,3/ értékeket át kell majd
 alakitani /például/ REAL értékekre, esetleges átalakitási
 hibákkal.      
  sql.doc Page: 35 
 4.3. PRIVILÉGIUMOK 
 Ha T egy alap tábla vagy egy aktualizálható nézet, a T-n érvé-
 nyes módon végrehajtható müveletek a SELECT, INSERT, UPDATE, 
 /megadott oszlopokon/ és DELETE. Ha T egy nem aktualizálható 
 nézet, az egyetlen müvelet, ami T-n érvényesen végrehajtható a
 SELECT. Ha T egy tábla és O egy olyan müvelet, ami érvényes
 módon végrehajtható egy T-n, akkor az U1 felhasználó rendel-
 kezik azzal a privilégiummal, hogy végrehajtsa az O-t a T-n,
 akkor, és csak is akkor, ha vagy /a/ U1 a T tulajdonosa,
 vagy /b/ az U1-nek explicit módon megadta ezt a privilégiumot 
 más U2 felhasználó, ahol U2 rendelkezik ezzel a privilégium-
 mal "with the grant option"-nal /a grant opcióval/ /lásd 
 lejjebb/. Az U felhasználó végrehajthatja az O müveletet a T
 táblán, akkor, és csak is akkor, ha az U rendelkezik azzal a
 privilégiummal, hogy végrehajtsa az O-t a T-n.
  Semmilyen speciális privilégiumokra nincs szükség egy
 séma vagy egy alap tábla létrehozásához. A SELECT privilégi-
 umra van szükség /minden hivatkozott táblán/ egy nézet létre-
 hozásához.
  A privilégiumok explicit módon vannak megadva /engedé-
 lyezve /az alábbi szintaxisú GRANT müvelet segitségével: 
  GRANT privilegies ON table TO grantee-commalist
   [WITH GRANT OPTION]
 ahol:
 /a/ "privileges" /privilégiumok/ vagy ALL [PRIVILEGES] vagy
  specifikus müveletek egy commalist-je. /SELECT és/vagy
  INSERT és/vagy UPDATE és/vagy DELETE - esetleg nem minö-
  sitett oszlop nevek zárójelek közé zárt commmalist-jével,
  UPDATE esetén/;
 /b/ Az ON klauzula tárgya egy minösitett vagy nem minösitett 
  tábla név /mely egy alap táblát vagy egy nézetet azonosit/ 
  /c/ Minden "grantee" /engedélyes vagy egy meghatalmazás azo-
  nositó, vagy a PUBLIC /*/ speciális kulcsszó. 
 _____ _______ ______ _______
 * A szabvány ténylegesen engedélyesek /grantee/ listáját ad
 meg, nem pedig commalist-et, a TO klauzula tárgyaként. Ez a
 kis ellentmondás látszólag egyszerü figyelmetlenség a bizottság 
 részéröl, és mihelyt lehetséges korrigálni fogják. 
 Néhány példát a 2.6-os alfejezetben a 2.14-es ábrában adunk meg.
  UPDATE esetében az oszlop nevek zárójelek közé helyezett
 commalist-jének kihagyása egyenértékü egy olyam commalist be-
 vitelével, ami a tábla összes oszlopát megadja. ALL a táblában 
 a /grant opcióval rendelkezö, vagy enélküli/ engedélyezö birto-
 kában lévö összes privilégium röviditése. A PUBLIC minden 
 felhasználót /vagyis minden meghatalmazás azonositót/ jelentö 
 rövidités. 
 Megjegyzés: Ha a P privilégium engedélyezve van a PUBLIC számá-
 ra, akkor az U felhasználó automatikusan élvezi a P privilégi-
 umot még abban az esetben is, ha az U felhasználó a rendszer
 számára nem volt ismert az engedély megadásának idején.
  sql.doc  Page: 36 
  A GRANT müveletet kiadó felhasználónak /vagyis a tar-
 talmazó sémához az AUTHORIZATION klauzula által azonositott
 felhasználónak/ vagy /a/ azon tábla tulajdonosának kell lennie,
 amelyen a privilégiumok meg vannak adva /vagyis ennek a táblának
 ugyanazon sémában létrehozottnak kell lennie/, vagy /b/ meg
 kellett kapnia az engedélyt ezen privilégiumok használatára
 valamilyen más felhasználótól "with the grant option"-nal /a
 grant opcióval/ /lásd lejjebb/. Egyik felhasználó sem engedé-
 lyezhet olyan privilégiumot, amely nincs a birtokában. 
 A grant opció 
 Ha az A felhasználó számára meg van engedve, hogy engedélyezzen
 /grant/ valamilyen P privilégiumot a B felhasználó számára,
 akkor /definició szerint/ az A felhasználó számára meg van en-
 gedve, hogy engedélyezze ezt a P privilégiumot a B felhaszná-
 lónak "with the grant option"-nal /a grant opcióval/ /a GRANT
 müveletben a WITH GRANT OPTION klauzula segitségével/. A grant
 opcióval egy privilégium engedélyezése azt jelenti, hogy a pri-
 vilégiumot átvevö is engedélyezheti /megadhatja/ ugyanezt a
 privilégiumot - a grant opcióval vagy anélkül - valamilyen
 további felhasználónak /és igy tovább rekurziv módon/. 
 USER 
 A USER foglalt szó, ami rendszer változónak /system variable/ 
 /vagy nulla argumentumú beépitett függvénynek/ tekinthetö.
 A USER értéke egy karakter füzér, amely azt a meghatalmazás
 azonositót reprezentálja, amely azon modul AUTHORIZATION klau-
 zulájában van elöirva, ami a USER hivatkozást tartalmazó SQL
 utasitásban van. Vizsgáljuk meg a következö példát.
 Séma:
  CREATE SCHEMA
  AUTHORIZATION TED
  ...
  CREATE VIEW MY_PARTS AS
  SELECT * FROM P WHERE P.PNO IN
  (SELECT SP.PNO FROM SP
  WHERE SP.SNO = USER)
  ...
  GRANT ALL ON MY_PARTS TO PUBLIC 
 Modul:
  MODULE M2
  AUTHORIZATION S2
  ...
  SELECT *
  FROM MY_PARTS ; 
 Amikor a SELECT müvelet végrehajtásra kerül az M2-es modul-
 ban, vissza fogja nyerni azon alkatrészekhez tartozó
 alkatrész sorokat, amelyeket az S2-es szállitó szállitott.
  A gyakorlatban a USER-t nagyon valószinü, hogy a
 GRANT-oknak a PUBLIC számára engedélyezésével kapcsolatban
 használják, mint ahogy a példa is sugallja.
   sql.doc Page: 37 
  5
 __________ ______ ____ _____ _______ ______ _____________ 
 Adat manipuláció:
 A modul nyelv 
 5.1 SZINTAXIS 
 Az SQL adatmanipuláló utasitások a host nyelvtöl független mó-
 don vannak megadva olyan modulok és eljárások segitségével,
 amelyek a modul nyelven iródtak. Ennek a nyelvnek a szintaxisa
 a következö:
  Modul definició:
  ::= MODULE [module]
  LANGUAGE 
   AUTHORIZATION user
   [cursor-definition-list]
   procedure-definition-list  
  Cursor definició:
  ::= ....... Lásd a 6. fejezetet.
  Eljárás definició:
  ::= PROCEDURE procedure
   parameter-definition-list ;
   manipulative-statement ;
  Paraméter definició:
  ::= parameter data-type | SQLCODE
  Manipulativ utasitás:
  ::= close-statement
   |commit-statement 
   |delete-statement-positioned
   |delete-statement-searched
   |fetch-statement  
   |insert-statement 
   |open-statement  
   |rollback-statement
   |select-statement 
   |update-statement-positioned
   |update-statement-searched 
  Amint a szintaxis jelzi egy modul egy MODULE klauzulá-
 ból /opcionálisan specifikálva egy modul nevet/, egy LANGUAGE 
 klauzulából, mely azt a host nyelvet adja meg, amelyböl a modul 
 eljárásait meg fogják hivni, egy AUTHORIZATION klauzulából, 
 nulla vagy több cursor definicióból és egy vagy több eljárásból 
 áll. Annak a felhasználónak, akinek a meghatalmazás azonositója 
 az AUTHORIZATION klauzulában meg van adva, birtokolnia kell az 
 összes szükséges privilégiumot a modulban lévö eljárásokban meg-
 adott összes manipulativ utasitáshoz. A cursor definiciók a 6. 
 fejezetben vannak elmagyarázva; az eljárásokat a következö al-
 fejezetben tárgyaljuk.
  Egy adott alkalmazáshoz legfeljebb egy SQL modul tartoz-
 hat. A két modul közötti kapcsolat /asszociáció/ létrehozásához
 a mechanizmus nem meghatározott maradt.   
  sql.doc Page: 38 
 5.2 ELJARARASOK. PARAMÉTEREK ÉS MANIPULATIV UTASITASOK 
 Egy eljárás egy PROCEDURE klauzulából /mely megad egy nevet
 az eljáráshoz/ paraméter definiciók listájából /melyek közül
 pontosan egynek meg kell adnia az SQLCODE speciális paramétert/
 és egyetlen adat manipuláló utasitásból áll. Az eljárás nevek-
 nek egyedieknek kell lenniük az öket tartalmazó modulon belül. 
 Paraméterek 
 Egy eljárásban minden /SQLCODE-tól eltérö/ paraméter definició
 egy paraméter névböl és egy adat tipusból áll. Paramétereket
 használunk a következök reprezentálására:
 /a/ "Targets" /célok/ /vagyis olyan host program változók,
  melyekbe skalár értékeket kell visszanyerni/. Ebben a mi-
  nöségében egy paraméter csak INTO klauzula operandusaként
  jelenhet meg FETCH vagy SELECT utasitásban.
 /b/ A host programból átadott skalár értékek. Ebben a minö-
  ségében egy paraméter egy SQL adat manipuláló utasitás-
  ban bárhol megjelenhet, ahol literál megjelenhet - vagyis
  a következök bármelyikén belül elemként /pontosabban meg-
  fogalmazva a következök bármelyikén belül egy aritmeti-
  kai kifejezésen belüli elemként, ha a kérdéses paraméter
  numerikus/;
 - SELECT klauzula /egy visszanyerendö értéket reprezentá-
  landó minden kifejezésben, mely tartalmaz ilyen klauzu-
  lát /például lekérdezés kifejezésben - lásd a 9. fejeze-
  tet;
 - WHERE klauzula /egy összehasonlitandó értéket reprezentá-
  landó/ SELECT, UPDATE vagy DELETE utasitásban, illetve
  cursor definicióban; 
 - SET klauzula UPDATE utasitásban /egy adatbázis aktualizálá-
  sához használandó értéket reprezentálandó/;
 - VALUES klauzula INSERT utasitásban /a beszúrandó értéket 
  reprezentálandó/ 
  Megjegyzés: Bizonyos okok miatt a szabvány nem enged
  meg müveleti /operational/ kifejezéseket ezen négy eset 
  közül az utolsóban. Például, ha X egy numerikus paraméter,
  akkor az X kifejezés meg van engedve VALUES klauzulában,
  de az X + 1 kifejezés nincs megengedve. 
  Ha a P eljárás tartalmaz egy S adat manipuláló utasitást,
 és S utasitás tartalmaz egy hivatkozást /referenciát/ C osz-
 lopra, és a C nem minösitett név ugyanaz, mint a P-ben defini-
 ált valamelyik paraméter neve, akkor a C-re hivatkozásnak
 minösitettnek kell lennie. Például:  
  PROCEDURE GET_PART
  SQLCODE
  PNO .... ;  
  SELECT * FROM P WHERE P.PNO = PNO ;   
  sql.doc Page: 39 
 Itt "P.PNO" egy hivatkozás/referencia/ a P tábla PNO osz-
 lopára,a "PNO"/nem ninösitett/ egy hivatkozás a PNO pa-
 raméterre. 
 SQLCODE 
 Az SQLCODE paraméternek megfelelö argumentumot használjuk
 visszatérési kod /mondjuk r /vételére,mely azt jelzi,hogy
 mi történt a manipulativ utasitás/mondjuk S/ végrehajtása- 
 kor. Az r értékeit a következökben definiáljuk:
  1.Ha S sikeresen végrehajtodott, akkor:
 /a/ Ha S a következök valamelyike volt:
  - olyan FETCH,melyhez nem volt következö sor 
  -olyan SELECT vagy INSERT...SELECT,melyhez nem találta- 
  tott sor
  -searched/keresett/ UPDATE ,melyhez nem tartozott aktua-
  lizalando sor
  -searched/keresett/ DELETE,melyhez nem tartozott torlen-
  dö sor
  akkor r értéke +100-ra állitodik.
 /b/ Egyébként r értéke 0-ra állitodik.   
  2.Ha S végrehajtása nem volt sikeres,akkor r egy imp-
 lementácio definiálta értékre állitodik/és az adatbázis
 változatlan marad/ 
 Paraméter adat tipusok 
 Egy paraméter adat tipus megadásának/elöirásának/ célja az
 implementáció tájékoztatása arról az adat tipusról, amelyet
 a megfelelö argumentumhoz várhat a host nyelvböl.Teát az
 elöirhato adat tipusok tartománya a kérdéses host nyelv által
 támogatott adat tipusok tartományátol függ; nem minden adat
 tipus adható meg minden host nyelvhez.A következö táblázat
 jelzi ,hogy melyek érvényesek mely hostokhoz.Megjegyzés:
 Ebben a táblázatban az SQLCODE arra a host argumentumra
 vonatkozik,amely az SQLCODE paraméternek megfelel;az ebben
 az oszlopban láthato adat tipusok host adat tipusok.Az 
 egyeb paraméterek oszlopban leirt adat tipusok az SQL 
 szabványban definiált adat tipusok. 
 -------- ----- ------ ----- ----- -----------------
  SQLCODE egyeb paraméterek
 -------- ----- ------ ----- ----- ----------------
 COBOL COMP PIC S9 /pc/ CHARACTER vagy NUMERIC
 FORTRAN INTEGER CHARACTER vagy INTEGER
  vagy REAL vagy DOUBLE
  PRECISION
 Pascal INTEGER  CHARACTER vagy INTEGER
  vagy REAL
 PL1 FIXED BIN /pp/ CHARACTER vagy DECIMAL
  vagy FLOAT
 -------- ----- ------ ----- ----- -----------------
 Megjegyzes: a pc és pp értékeknek 4-nél illetve 15-nél na-
 gyobb vagy ezzel egyenlö értéknek kell lenniük.
  sql.doc Page: 40 
 Manipulativ utasitások  
 Az SQL adat manipulácios utasitások három kategoriába sorol-
 hatok:
  1.Cursor müveletek:
  OPEN
  FETCH
  UPDATE...CURRENT/pozicionált UPDATE/
  DELETE...CURRENT/pozicionált DELETE/
  CLOSE
  2.Nem cursor müveletek:
  SELECT
  INSERT
  UPDATE/keresett UPDATE/
  DELETE/keresett DELETE/
  3.Tranzakcio befejezési müveletek:
  COMMIT
  ROLLBACK 
  A cursor müveleteket és nem cursor müveleteket a 6. ill.
 7. fejezetben tárgyaljuk. A COMMIT-ot és ROLLBACK-ot a jelen 
 fejezet végén, az 5.4-es alfejezetben tárgyaljuk /megfelelöbb
 hely hiányában/.   
 5.3 INDIKATOR PARAMETEREK 
 A null értékek speciális kezelést igényelnek a modulnyelvben
 /mint ahogyan ténylegesen majdnem mindenhol/.Vizsgáljuk meg
 a következö eljáráspéldát, mely tartalmaz egy SELECT utasi-
 tast: 
  PROCEDURE GET_WEIGHT
  SQLCODE
  PNO_PARAM CHAR(6)
  WEIGHT_PARAM DECIMAL(3);
  SELECT P.WEIGHT
  INTO WEIGHT_PARAM
  FROM P
  WHERE P.PNO =PNO_PARAM ; 
 Feltételezzük, hogy lehetöség van arra,hogy a WEIGHT/suly/
 értéke null legyen valamilyen alkatrészhez /mely tulajdon-
 képpen valos eset, mivel NOT NULL nem volt elöirva a WEIGHT
 oszlophoz a 2.3 -as ábra sémájában/.A fent láthato SELECT
 utasitás sikertelen lesz,ha a kiválasztott WEIGHT null;
 az SQLCODE negativ értékre fog állni és a WEIGHT_PARAM
 célparaméter egy implementácio definiálta állapotban fog
 maradni.Altalában, hogy egy visszanyerendö érték null 
 legyen,a programozonak meg kell adnia egy indikátor pa-
 ramétert a normál cél paraméteren kivül ehhez az értékhez
 ugy ,ahogyan most bemutatjuk.   
  sql.doc Page: 41  
  PROCEDURE GET_WEIGHT
  SQLCODE
  PNO_PARAM CHAR(6)
  WEIGHT_PARAM DECIMAL(3)
  WEIGHT_INDIC DECIMAL(5);
  SELECT P.WEIGHT
  INTO WEIGHT_PARAM INDICATOR WEIGHT_INDIC
  FROM P
  WHERE P.PNO=PNO_PARAM; 
 Ha a visszanyerendö érték null és meg volt adva indikátor
 paraméter, akkor ez az indikátor paraméter -1-re/minusz
 egyre/fog beállni;ha a visszanyerendö érték nem null,az
 indikátor paraméter nem nullára fog beállni. /*/ 
 _____ _______ ______ ______
  *Egy kissé túlegyszerüsités. Ha a visszanyerendö érték 
 nem null és n1 karakter füzér hosszuságu és a cél para-
 méter adat tipusa CHARACTER/n2/ és ha n1 nagyobb mint
 n2,akkor az indikátor paraméter n1-re áll be.
 Az indikátor paraméterek a bemutatott modon vannak megadva
 -vagyis a megfelelö szokásos cél paramétert követöen és 
 ettöl a szokásos paramétertöl az INDICATOR kulcsszoval
 elválasztva./pontos számoknak kell lenniük/a pontos adat
 tipust az implementácio definiálja. 
  A Példa bemutatja egy indikátor paraméter használatát
 cél paraméterrel együtt.Indikátor paraméterek szokásos
 paraméterekkel /vagyis olyan paraméterekkel, melyeket
 egyszerüen értékek megadására használunk/ is használ-
 hatok.Például az alábbi utasitás  
  UPDATE P
  SET WEIGHT=WEIGHT_PARAM INDICATOR WEIGHT_INDIC
  WHERE P.CITY='London' 
 minden londoni alkatrészhez a súlyt null értéküre fogja
 állitani,ha a WEIGHT_INDIC értéke negativ/bármilyen nega- 
 tiv érték,nem csak minusz egy/.Természetesen ugyanazt fog- 
 ja tenni az alábbi utasitás is  
  UPDATE P
  SET WEIGHT=NULL
  WHERE P.CITY='London'  
 Megjegyzes:indikátor paraméterek WHERE kauzulában is 
 használhatok,de valoszinüleg nem szabad öket itt hasz-
 nálni.
 Példaul még ha a WEIGHT_INDIC értéke negativ is,a
 küvetkezö utasitás nem fog visszanyerni alkatrész
 számokat olyan alkatrészekhez ,ahol a suly értéke
 null./Feladat az olvaso számára:mi az amit tenni fog?/  
  sql.doc Page: 42  
  SELECT P.PNO
  INTO PNO_PARAM
  FROM P
  WHERE P.WEIGHT=WEIGHT_PARAM INDICATOR WEIGHT_INDIC 
 Az alkatrész számok visszanyerésének helyes módja ,ott
 ahol a súly értéke null, a következö: 
  SELECT P.PNO
  INTO PNO_PARAM
  FROM P
  WHERE P.WEIGHT IS NULL 
  /lásd a 9.fejezetet/  
 5.4 COMMIT ES ROLLBACK  
 COMMIT 
 A COMMIT müvelet az alábbi alakú 
  COMMIT WORK 
 Befejezi az aktuális tranzakciót /normál befejezés/.
 A tranzakció által végrehajtott minden aktualizálás 
 megtörténik.Minden megnyitott cursor lezárodik.  
 ROLLBACK 
 A ROLLBACK muvelet a kovetkezö alaku: 
  ROLLBACK WORK 
 Az aktuális tranzakcio befejezödik./rendellenes befejezés/.
 A tranzakcio által végrehajtott minden aktualizálás tör-
 lödik.Minden megnyitott cursor lezárodik.               
  sql.doc Page: 43   
  6
 -------- ----- ------ ----- ----- -----------------
 Adat manipulácio
 Cursor müveletek 
 6.1 BEVEZETES 
 Az adatbázishoz a cursoron alapulo hozzáférés általános is-
 mereteit a 2.fejezet 2.4-es alfejezetében magyaráztuk el;
 nézze át ezt az alfejezetet,ha szüksége van arra,hogy az
 általános ismeretekre felfrissitse emlékezetét.Ebben a fe-
 jezetben részletesebben vizsgáljuk meg a cursor müvelete-
 ket.Ezek a müveletek a következök/az 5.2-es alfejezetböl
 megismételve/:  
  OPEN
  FETCH
  UPDATE...CURRENT/pozicionált UPDATE/
  DELETE...CURRENT/pozicionált DELETE/
  CLOSE 
  A 6.2-es alfejezet elmagyarázza,hogy pontosan mi is
 egy cursor és mi az,ami szerepet játszik egy cursor defi-
 niálásában. A 6.3-as fejezet ezt követöen részletesen tár-
 gyalja az öt cursor müveletet.Megjegyzés:oktatási okok mi-
 att számos egyszerüsitö feltételezést teszünk ebben a 
 fejezetben mindenhol,nevezetesen a következöket:
 - elöször is feltételezzük,hogy minden tábla alaptábla;
  a nézetekre érvényes speciális szempontok ismertetését
  a 8.fejezetre halasztjuk
 - másodszor feltételezzük,hogy a felhasználó rendelkezik 
  az összes olyan privilégiummal, melyre szükség van a 
  kérdéses müveletek végrehajtásához
 - harmadszor,/nagyrészt/ figyelmen kivül hagyjuk a hibák
  lehetöségét;vagyis figyelmen kivül hagyjuk azt a lehe-
  töséget, hogy bármilyen integritási elöirás megszegés
  bekövetkezhet;vagyis feltételezzük,hogy semmilyen ki-
  sérlet nem történik null érték bevitelére, olyan osz- 
  lopba, melyhez null-ok nincsenek megengedve, vagy olyan
  sor bevitelére, ami megszegi egy oszlop egyedi jellegére 
  vonatkozo követelményt,vagy egy oszlopba olyan érték 
  bevitelére, melynek az adat tipusa nem megfelelö
 - végül nem teszünk kisérletet arra,hogy elmagyarázzuk
  nagy általánosságban a lekérdezés kifejezéseket /lásd
  a következö alfejezetben a cursor definiálás cimü leirást/
  ezt a magyarázatot a 9. fejezetre halasztjuk       
  sql.doc Page:  44  
 6.2 CURSOROK 
 Egy cursor lényegében egyfajta pointer,mely sorok rendezett
 gyüjteményén futtathato végig;amely gyüjteményben a sorok 
 mindegyikére sorban rámutat és igy a sorok számára egyenkénti
 cimezhetöséget biztosit.Ha a C cursor az R sorra mutat,azt
 mondjuk,hogy az R sorra van pozicionálva.Az R sor ilyenkor
 aktualizálható vagy törölhetö az UPDATE és DELETE müveletek
 pozicionált alakján keresztül/UPDATE/DELETE...WHERE CURRENT 
 OF C/.Más szavakkal fogalmazva a pozicionált UPDATE vagy
 DELETE esetén a cursornak on /aktiv/ állapotban kell lennie.
 /Ez a megjegyzés természetesen feltételezi, hogy elöször is
 az aktualizálások meg legyenek engedve a cursoron keresztül;
 lásd késöbb a jelen fejezetben/.
 Minden cursorhoz tartozik egy lekérdezés/query/,mely a cur-
 sort definiáló müvelet részeként van megadva.A lekérdezés
 paraméteresithetö.Például: 
  DECLARE X CURSOR
  FOR SELECT SP.SNO,SP.QTY
  FROM SP
  WHERE SP.PNO=PNO_PARAM
  ORDER BY SP.SNO 
  Ez a DECLARE definiál egy X nevü cursort a hozzátartozo
 lekérdezéssel együtt úgy, ahogyan ezt a "SELECT...PNO_PARAM"
 /ahol PNO_PARAM egy paraméter/ kifejezés definiálja.Ennek 
 a lekérdezésnek a végrehajtása ekkor még nem történik meg;
 a DECLARE CURSOR tisztán deklarativ müvelet.A lekérdezés
 tényleges végrehajtása akkor történik,amikor az X cursort
 megnyitják/lásd a 6.3 -as fejezetet/;ha a lekérdezés pa-
 raméteresitve van,az ezen paramétereknek megfelelö argu-
 mentumokat abban az eljárásban kell megadni,amelyik az
 OPEN-t végrehajtja.A lekérdezés végrehajtásábol származó
 sorok gyüjteménye az OPEN uán kapcsolatban van a cursorral
 és ez igy is marad mindaddig,amig a cursor ujra le nem
 zárodik/lásd a 6.3-as fejezetet/.
 Ezenkivül a sorok ezen gyüjteménye "rendezett"./lásd az
 ORDER BY leirását a jelen alfejezet végén/.
  Ezért tehát miközben nyitott egy cursor sorok bizonyos
 rendezett gyüjteményét jelöli ki, valamint egy bizonyos
 specifikus poziciót is kijelöl ezen rendezéshez viszonyit-
 va.A lehetséges poziciók a következök:
 - valamilyen specifikus soron/on/-/on állapot/
 - valamilyen specifikus sor elött/before/-/before állapot/
 - az utolso sor után/after/-/after last állapot/
  Az OPEN a cursort az elsö sor elé helyezi.A FETCH a 
 cursort a következö sorra,vagy ha nincs következö sor az
 utolso sor utáni helyre helyezi.Ha a cursor valamelyik
 soron van vagy valamelyik sor elött van és ez a sor
 törlödik a cursor a következö sor elé vagy ha nincs 
 következö sor az utolso sor után helyezödik át.
 Megjegyezzük,hogy a cursor az elsö sor elött vagy 
 az utolso sor után lehet elhelyezve,még abban a speci-
  sql.doc Page: 45 
 ális esetben is,amikor a sorok gyüjteménye üres. 
  Megjegyzés:ez a szakasz a szabvány által elöirt 
 helyváltoztatásokkal/pozició áthelyezés/ foglalkozik.
 Lehetségesek mások is ,vagy egyáltalán nem emliti a
 szabvány vagy legjobb esetben implementácio definiálta
 állapotként hagyja. Megjegyzés vége. 
  Minden cursor lezárt /zárt/ állapotban van a tranzakcio
 elején és zárt állapotban/ha nyitva van/ kényszeritödik a
 tranzakcio befejezésekor.Azonban a tranzakcio inditás
 és tranzakcio befejezés között ugyanaz a cursor számos
 alkalommal megnyithato és lezárhato/estleg külömbözö
 alkalmakkor eltérö paraméter értékekkel és ezért külömbözö 
 kapcsolatba hozott sorgyüjteményekkel/.  
 Cursor definiálása 
 Emlékezzünk vissza az 5. fejezetre,ahol a cursorok egy
 modul specifikácio részeként vannak definiálva/bármilyen
 eljárás elött,mely ezen cursorokat használhatja/.Egy adott
 modulban minden egyes cursor definiciohoz pontosan egy
 eljárásnak kell tartoznia ebben a modulban,melynek a
 feladata a kérdéses cursor OPEN-je/megnyitása/.Egy cursor
 definialásának szintaxisa: 
  DECLARE cursor CURSOR FOR query-expression
   /order-by-clause/ 
  Már megadtunk egy példát a jelen alfejezethez.A 
 query-expression részleteit lásd a 9. fejezetben;ebben 
 a fejezetben általánosságban feltételezni fogjuk, hogy
 ez egyszerüen egy SELECT /lekérdezés/ anélkül,hogy
 kisérletet tennénk arra,hogy formálisan definiáljuk ezt
 a kifejezést/,plusz egy opcionális ORDER BY klauzula.
 A lekérdezés kifejezés célja azon sorok gyüjteményének
 /együttesének/definiálása,amelyek elérhetöek lesznek
 a cursoron keresztül,amikor a cursor meg van nyitva.A
 sorok ezen gyüjteménye a cursoron keresztül aktualizál- 
 ható lesz/vagyis úgymond a cursor aktualizalható lesz/
 the cursor will be updatable/,hogy egy pontatlan,de
 általánosan elterjedt kifejezést használjunk/,akkor
 és csakis akkor ,ha az alábbi a/,b/,c/ pontok közül
 mind a három érvényes:
 a/ A lekérdezés kifejezés nem tartalmaz UNION-t,más
  szavakkal ez lényegében egy lekérdezés specifikácio
  /query specification//lásd a 9.2 fejezetet/;
 b/ Ez a lekérdezés specifikácio egy aktualizálhato né- 
  zetet definiálna,ha egy nézet definicio környezetében
  jelenne meg/lásd a 8.4-es alfejezetet/;
 c/ A cursor definicio nem tartalmaz ORDER BY-t.
  Amikor a cursor megnyitásra kerül /és nem elötte/
 a SELECT /lekérdezés/ kifejezés kiértékelödik és ál-
 talában egy többsoros táblát eredményez.Az ORDER BY
  sql.doc Page: 46 
 klauzula elöir egy rendezést a létrejött tábla sora-
 ihoz;ha nincs megadva ilyen klauzula ,a sorok rende-
 zését az implementácio definiálja.Az alábbiakban meg-
 adunk egy példát egy eljárásra amely egy cursort nyit
 meg:/lásd továbbá a 6.3-as alfejezetben/: 
  PROCEDURE OPENX
  SQLCODE
  PNO_PARAM CHAR(6);
  OPEN X ;
  Jegyezze meg,hogy egy adott cursor definiciojában 
 szereplö minden paraméternek definiáltnak kell lennie 
 abban az eljárásban, ami ezt a cursort megnyitja. 
 Az ORDER BY klauzula 
 Az ORDER BY klauzula a következöképpen van definiálva: 
  order-by-clause
  ::= ORDER BY ordering-specification-commalist 
  ordering-specification
  ::= (integer | column reference ) ( ASC | DESC) 
  Az oszlop referencia egyszerüen egy minösitett vagy
 nem minösitett oszlop név,az ORDER BY klauzulában a ren- 
 dezési elöirások balról jobbra sorrendje megegyezik a
 nagyobbtól kisebb felé rendezéssel,a szukásos konvenciok-
 kal összhangban.Rendszerint minden ilyen specifikácio 
 /megadás/ oszlop névböl, opcionális minösitöböl és
 ASC vagy DESC / ASC növekvö sorrendet és DESC csökkenö
 sorrendet jelent;ASC az alapértelmezés/opcionális spe-
 cifikáciojábol áll.Más változatként egy rendezési elö-
 irás elöjel nélküli integerböl is állhat,mint a követ-
 kezö példában: 
  DECLARE Y CURSOR
  FOR SELECT SP.PNO.AVG (SP.QTY)
  FROM SP
   GROUP BY SP.PNO
  ORDER BY 2 
  Az integer az eredmény táblában az oszlop sorrend 
 szerinti/balról jobbra/ helyére utal. Ez a jellemzö le-
 hetövé teszi az eredmény tábla rendezését olyan eredmény
 oszlop alapján,amely egy egyszerü megnevezett oszloptol
 eltérö valami másbol származik,és ebböl következöen nincs
 saját neve.A példában a "2" az átlagok oszlopára utal.
 Megjegyzés:a rendezési elöirásoknak integereknek,nem
 pedig neveknek kell lenniük,ha a cursor definicio UNION-t
 tartalmaz /lásd a 9. fejezetet/. 
  Megjegyezzük, hogy /mint ahogy már jeleztük/ minden egyes 
 rendezési elöirásnak azonositania kell az eredmény tábla
 / result table/ egy oszlopát. Igy például az itt következö 
  sql.doc  Page: 47 
 *** ILLEGAL *** /nincs megengedve/: 
  DECLARE Z CURSOR
   FOR SELECT S.SNO
   FROM S
    ORDER BY S.CITY 
 6.3 CURSORON ALAPULO MANIPULACIOS 
 OPEN 
 Az OPEN utasitás a következö alakú 
  OPEN cursor 
 ahol "cursor" azonosit egy cursort /mondjuk C-t/. A C cur-
 sornak zárt állapotban kell lennie. A C definicio-
 ban lévö lekérdezés kifejezés kiértékelödik, aktuális érté-
 keket használva az ezen lekérdezés kifejezésben hivatkozott
 minden paraméterhez, a sorok gyüjteményének elöállitására.
 Ez a gyüjtemény /készlet/ rendezett a 6.2-es alfejezet vé-
 gén leirtak szerint. A C cursor nyitott állapotu lett
 és ezen rendezett gyüjtemény /halmaz elsö sora
 elé mutat (van pozicionálva).
 Példa:
  OPEN X 
 FETCH 
 A FETCH utasitás a következö alakú 
  FETCH cursor INTO target-commalist  
 ahol "cursor" azonosit egy cursort /mondjuk C-t/, és minden
 "target" /célnak/ az alábbi alaku 
  parameter [ [ INDICATOR ] parameter ] 
 /vagyis egy cél paraméterböl áll egy opcionálisan hozzá-
 tartozo indikátor paraméterrel együtt - lásd az 5.3-as
 alfejezetet/. A cél commalist-nek pontosan egy célt kell
 tartalmaznia a C cursor definiciojában a SELECT klauzulá-
 ban lévö minden kifejezéshez. A célok commalist-jében az
 i-edik bejegyzés által azonositott cél a C cursor defini-
 ciójában a SELECT klauzulában az i-edik kifejezésnek felel
 meg.
  A C cursornak nyitottnak kell lennie. Ha
 nincs köcetkezö sor az éppen a C cursorhoz tartozó sorok
 rendezett gyüjteményében /ezen rendezésben a C aktuális
 poziciojához viszonyitva/ semmilyen adat visszanyerés nem törté-
 nik; egyébként a C cursor a következö sorra pozicionálodik,
 ebböl a sorbol az értékek visszanyerödnek és a célokhoz (paraméterek)
 értékadások történnek az INTO kauzulában lévö elöirások-
 kal összhangban.
  Jegyezze meg, hogy a FETCH logikailag egy "fetch next"
  sql.doc Page: 48 
 /következö betöltése/ müvelet. Azt is jegyezze meg, hogy 
 "fetch next" az egyetlen cursor elmozditási müvelet; nem le-
 hetséges a cursornak /például/ "három pozicioval elöre" vagy
 "két pozicioval hátra" vagy "közvetlen az n-edik sorhoz",
 stb. mozgatása /de nézze át a 12. fejezetet/.
 Példa:
  FETCH X INTO SNO_PARAM, QTY_PARAM INDICATOR QTY_INDIC 
 UPDATE /pozicionált/ 
 A pozicionált UPDATE utasitás a következö alaku 
  UPDATE table
  SET assignment-commalist
  WHERE CURRENT OF cursor 
 ahol "table" egy táblát /mondjuk T/ azonosit és "cursor" egy
 cursort /mondjuk C-t/ azonosit és minden értékadás 
  column =  
 alakú. Minden ilyen értékadás baloldalán a "column"-nak /osz-
 lopnak/ a T tábla egy oszlopa nem minösitett nevének kell len-
 nie. A C cursornak nyitottnak, "aktualizálható"-nak kell lennie,
 és a T táblázat egyik sorára kell pozicionálódnia. A SET klauzu-
 lában minden egyes értékadáshoz a skalár kifejezés kiszámitásá-
 nak eredménye, vagy nulla érték, ha NULL van elöirva rendelödik
 hozzá a jelzett oszlophoz. A skalár kifejezésben a T tábla 
 oszlopaira történö hivatkozások a cursor poziciója által ki-
 jelölt sor megfelelö oszlopában az eredeti /az UPDATE végre-
 hajtása elötti/ értéket jelentik. 
  Megjegyzés: A "scalar expression" /skalár kifejezés/
 szintaxisát a 9. fejezetben /9.3-as alfejezet/ adjuk meg. 
 A 3. fejezetben leirtak szerint ennek általános célja vala-
 milyen skalár érték kijelölése. A most tárgyalt speciális 
 összefüggésben, az ilyen kifejezésnek nem szabad tartalmaz-
 nia semmilyen hivatkozást a beépitett függvények /COUNT,
 SUM, AVG stb./ egyikére sem.
 Példa: 
  UPDATE SP
  SET QTY = SP.QTY + INCR_PARAM
  WHERE CURRENT OF X 
  Megjegyzés: a szabvány nem adja meg, mi történik, ha a
  pozicionált UPDATE megváltoztatja az aktualizált sor
  helyzetét a cursorhoz tartozo rendezéshez viszonyitva.
  A példában például mi történik, ha SP sorokat történe-
  tesen növekvö QTY értékek szerint kell rendezni? Meg-
  jegyzés vége.    
  sql.doc Page: 49  
 DELETE /pozicionált/ 
 A pozicionált DELETE utasitás a következö alakú 
  DELETE
  FROM table
  WHERE CURRENT OF cursor 
 ahol "table" azonosit egy táblát /mondjuk T/ és "cursor" 
 azonosit egy cursort /mondjuk C/. A C cursornak nyi-
 tottnak kell lennie, "aktualizálhatonak" kell lennie és a
 T tábla egyik sorára kell pozicionálodnia. Ez a sor törlödik.
 Példa: 
  DELETE
  FROM SP
  WHERE CURRENT OF X 
 Az X cursor ezután közvetlenül az éppen törölt sort követö sor
 elött fog elhelyezkedni, vagy az utolso sor után, ha nem
 létezik ilyen közvetlenül követö sor. 
 CLOSE 
 A CLOSE utasitásnak az alábbi alakja van 
  CLOSE cursor 
 ahol "cursor" egy cursort /mondjuk C/ azonosit. A C cursort
 /amelynek nyitottnak kell lennie/ zárt állapotba
 helyezi.
 Példa: 
  CLOSE X 
 6.4 EGY GLOBALIS PÉLDA 
 A fejezetet egy képzeletbeli, de átfogó példával /6.1-es ábra/
 fejezzük be, amely bemutatja, hogy az ebben a fejezetben /és
 a korábbi fejezetekben bevezetett elgondolások közül számos
 elgondolás hogyan illeszkedik egymáshoz. A host program
 /mely PL/I-ben van irva/ négy input értéket fogad: alkatrész-
 számot /GIVENPNO/, város nevet /GIVENCIT/, állapot növek-
 ményt /GIVENNINC/ és állapot szintet /GIVENLVL/. A program
 letapogatja /átvizsgálja/ az összes olyan alkatrész szálli-
 tóját, melyet a GIVENPNO azonosit. Minden ilyen szállitóhoz, 
 ha a szálitóhoz tartozó város GIVENCIT, az állapotot meg-
 növeli a GIVENINC-vel; egyébként ha az állapot kisebb, mint 
 GIVENLVEL, törli a szállitót, az ehhez a szállitóhoz tartozó
 összes szállitmánnyal együtt. Minden esetben listázza a
 szállitó információit a nyomtatón, annak jelzésével, hogy
 a kérdéses szállitót hogyan kezelte a program.
  1. megjegyzés: Mindenhol figyelmen kivül hagytuk azt a
 lehetöséget, hogy valamilyen visszanyerendö érték null le-
   sql.doc Page: 50 
 het. Ezt az egyszerüsitést tisztán a példa méretének a csök-
 kentésére vezettük be.
  2. megjegyzés: A bemutatott utasitások közül néhányat 
 eddig még nem tárgyaltunk részletesen. Vagyis az UPDATE és
 DELETE utasitások "keresett" változatok, nem pedig "pozici-
 onált" változatok. Az ilyen utasitások általános leirása a
 2. fejezetben található; a részleteket a 7. fejezet adja meg.
  3. megjegyzés: Figyelje meg, hogy az aktuális S sor
 aktualizálásához/törléséhez az UPDATE és DELETE utasitások-
 nak /lásd az UPDATE_PROC és a DELETE_S_PROC eljárásokat/
 a keresett változatnak kell lenniük, nem pedig a pozicionált
 változatnak, jóllehet tulajdonképpen a Z cursor pontosan azon
 a soron helyezkedik el, amelyet aktualizálni/törölni óhajtunk.
 Ennek az az oka, hogy a Z cursor "nem aktualizálható"; vagyis
 a Z cursor definiciója olyan, hogy megtiltja a Z-n keresztüli 
 aktualizálásokat /mivel ez tartalmaz egy al-lekérdezést/.
 Lásd a 6.2 fejezetet.
  4. megjegyzés: bbbbbbb-t használunk hét blankból álló fü-
 zér reprezentálására. /6.1-es ábra, az eljárás kód 15. sora/,
 6.1. ábra. Globális /átfogó/ példa
 /A program megjegyzéseknek csak a forditása látható, a forditó
 megjegyzése/ 
 PLIEX: PROC OPTIONS (MAIN) ;
  /* program input */
  DCL GIVENPNO CHAR(6);
  DCL GIVENCIT CHAR(15);
  DCL GIVENINC DECIMAL(3);
  DCL GIVENLVL DECIMAL(3);
  /* célok a "FETCH SUPPLIER"-hez */
  DCL SNO CHAR(5);
  DCL SNAME CHAR(20);
  DCL STATUS DECIMAL(3);
  DCL CITY CHAR(15);
  /* housekeeping változók */
  DCL DISP CHAR(7)
  DCL MORE_SUPPLIERS BIT (1);
  /* SQL visszatérési kód változó */
  DCL RETCODE FIXED BINARY(15);
  /* SQL belépési pont deklarációk, alfabetikus sorrendben */
  DCL CLOSE_PROC ENTRY (FIXED BINARY(15));
  DCL COMMIT_PROC ENTRY (FIXED BINARY(15));
  DCL DELETE_S_PROC ENTRY (FIXED BINARY(15), CHAR(5));
  DCL DELETE_SP_PROC ENTRY (FIXED BINARY(15), CHAR(5));
  DCL FETCH_PROC ENTRY (FIXED BINARY(15), CHAR(5);
  CHAR(20),
   DECIMAL(3),
   CHAR(15));
  DCL OPEN_PROC ENTRY (FIXED BINARY(15), CHAR(6));
  DCL ROLLBACK_PROC ENTRY (FIXED BINARY(15), ;
  DCL UPDATE_PROC ENTRY (FIXED BINARY(15), CHAR(5),
   DECIMAL(3));
  /* adatbázis kivételes állapot kezelö */
  ON CONDITION (DBEXCEPTION)
  BEGIN ;
  sql.doc Page: 51 
   PUT SKIP LIST (RETCODE) ;
  CALL ROLLBACK_PROC (RETCODE) ;
  PUT SKIP LIST (RETCODE) ;
  GO TO QUIT ;
  END ;
  /* fö program logika */
  GET LIST (GIVENPNO, GIVENCIT, GIVENINC, GIVENLVL) ;
  CALL OPEN_PROC (RETCODE, GIVENPNO) ;
  IF NOT (RETCODE = 0)
  THEN SIGNAL CONDITION (DBEXCEPTION) ;
  MORE_SUPPLIERS = '1'B ;
  DO WHILE (MORE_SUPPLIERS) ;
  CALL FETCH_PROC (RETCODE, SNO, SNAME, STATUS, CITY) ;
  SELECT ; /* PL/I SELECT, nem pedig SQL SELECT */
  WHEN (RETCODE = 100)
  MORE_SUPPLIERS = '0'B ;
  WHEN NOT (RETCODE = 100 | RETCODE = 0)
  SIGNAL CONDITION ( DBEXCEPTION );
  WHEN (RETCODE = 0)
  DO ;
  DISP = 'bbbbbbb' ;
   IF CITY = GIVENCIT
  THEN
  DO ;
  CALL UPDATE_PROC (RETCODE,SNO, GIVENINC) ;
  IF NOT (RETCODE = 0)
  THEN SIGNAL CONDITION (DBEXCEPTION );
  DISP = 'UPDATED' ;
  END ;
  ELSE
  IF STATUS < GIVENLVL
  THEN
  DO ;
   CALL DELETE_SP_PROC (RETCODE, SNO);
  IF NOT (RETCODE = 0 | RETCODE = 100)
  THEN SIGNAL CONDITION (DBEXCEPTION );
  CALL DELETE_S_PROC (RETCODE, SNO) ;
  IF NOT ( RETCODE = 0 )
  THEN SIGNAL CONDITION (DBEXCEPTION);
  DISP = 'DELETED' ;
   END ;
   PUT SKIP LIST
   (SNO, SNAME, STATUS, CITY, DISP);
  END ;  /* WHEN RETCODE = 0 ... */
  END ; /* PL/I SELECT */
  END ; /* DO WHILE */
   CALL CLOSE_PROC (RETCODE);
  CALL COMMIT_PROC (RETCODE);
  QUIT: RETURN ;
  END ; /* PLIEX */
  MODULE SQLEXMOD LANGUAGE PLI AUTHORIZATION CJDATE
   DECLARE Z CURSOR FOR
   SELECT S.NO, S.NAME, S.STATUS, S.CITY
   FROM S
   WHERE S.SNO IN
  sql.doc Page: 52 
    (SELECT SP.SNO
   FORM SP
   WHERE SP.PNO = PNO) -- PNO egy paraméter
  PROCEDURE CLOSE_PROC
  SQLCODE ;
    CLOSE Z ;
  PROCEDURE COMMIT_PROC
    SQLCODE ;
   COMMIT WORK ;
  PROCEDURE DELETE_S_PROC
   SQLCODE
   SNO CHAR(5);
   DELETE FROM S WHERE S.SNO = SNO ; -- "keresett DELETE" 
  PROCEDURE DELETE_SP_PROC
   SQLCODE
   SNO CHAR(5);
   DELETE FROM SP WHERE SP.SNO = SNO -- "keresett DELETE"
  PROCEDURE FETCH_PROC
   SQLCODE
   SNO CHAR(5)
   SNAME CHAR(20)
   STATUS DECIMAL(3)
   CITY CHAR(20);
   FETCH Z INTO SNO, SNAME, STATUS, CITY ;
  PROCEDURE OPEN_PROC
   SQLCODE
   PNO CHAR(6);
   OPEN Z ;
  PROCEDURE ROLLBACK_PROC
   SQLCODE ;
   ROLLBACK WORK ;
  PROCEDURE UPDATE_PROC
   SQLCODE
   SNO CHAR(5)
   GIVENINC DECIMAL(3);
   UPDATE S
   SET  STATUS = S.STATUS + GIVENINC
   WHERE S.SNO = SNO ; -- "keresett UPDATE"                 
  sql.doc Page: 53  
  7
 -------- ----- ------ -------- ----- ------ ---- 
 Adat manipuláció:
 Nem cursor müveletek 
 7.1 BEVEZETÉS 
 A nem cursor manipulativ müveletek a következök:
  SELECT
  INSERT
  UPDATE /keresett/
  DELETE /keresett/
  Ugyanúgy, mint a 6. fejezetben, számos feltételezést
 teszünk /lényegében ugyanazokat, mint abban a fejezetben/ az
 elöadás mód egyszerüsitése érdekében:
 - Minden tábla alap tábla
 - A felhasználó rendelkezik az összes szükséges privilé-
  giummal
 - Nem fordulnak elö hibák.
 A lekérdezés kifejezések és az azzal kapcsolatos dolgok magya-
 rázatát továbbra is a 9. fejezetre halasztjuk. 
 7.2. SELECT 
 Elöször is néhány figyelmeztetö szó azoknak az olvasoknak
 célozva, akik esetleg már valamennyire ismerik az SQL nyel-
 vet: a nem cursoros SELECT müvelet a szabványos SQL-ben nem a
 teljesen általános /SET szintü/ SELECT müvelet, amelyet már
 valószinüleg ismernek. Ehelyett ez az amit esetenként "szingli"
 SELECT-nek nevezünk, vagyis olyan SELECT, ami legfeljebb
 egy sort nyer vissza. Például: 
  SELECT P.WEIGHT, P.COLOR
  INTO WEIGHT_PARAM, COLOR_PARAM
  FROM P
  WHERE P.PNO = 'P4' 
 Hiba, ha a tábla, mely a SELECT-FROM-WHERE kiértékeléséböl
 származik, egynél több sort tartalmaz. Az alábbiakban meg-
 adunk további érvényes példákat: 
  SELECT *
  INTO SNO_PARAM, SNAME_PARAM, STATUS_PARAM, CITY_PARAM
  FROM S
  WHERE S.SNO = 'S1' 
  SELECT AVG (SP.QTY)
  INTO AVG_QTY_PARAM
  FROM SP 
  SELECT MAX (SP.QTY) - MIN (SP.QTY)
  INTO ARITH_PARAM
  FROM SP 
  sql.doc Page: 54 
  WHERE SP.PNO = 'P4' 
  Az általános szintaxis: 
  SELECT [ALL | DISCINT] selection
  INTO target-commalist table-expression
 ahol:
 /a/ Ha sem DISTINCT sem pedig ALL nincs megadva, alapértel-
  mezés szerint ALL használata történik.
 /b/ Legyen T! a megadott tábla kifejezés kiértékeléséböl
  /kiszámitásából származó tábla; legyen T2 az a tábla,
  amelyik a T1-hez megadott "selection" /kiválasztás/
  kiértékelésével a T1-böl származik; és legyen T3 az a
  tábla, amelyik a T2-böl származik /ha DISTINCT
  meg van adva/ a redundáns ismétlödö sorok kihagyásával,
  vagy egyébként egy olyan tábla, amely azonos T2-vel.
   A T3 táblának legfeljebb egy sort szabad tartalmaznia.
 /c/ Ha T3-as tábla tartalmaz egy sort, visszanyeri ezt a
  sort. Ha T3-as tábla nem tartalmaz sort, "not found"
  /nem található/ kivételes állapot jön létre /SQLCODE
  plusz 100-ra állitódik. Ha a T3-as táblázat egynél több
  sort tartalmaz, hiba keletkezik /SQLCODE negativ érték-
  re áll/.
 /d/ A "selection" /kiválasztás/ vagy skalár kifejezések
  commalist-je /mindegyik általában, de nem szükségképpen,
  a T egy vagy több oszlopát tartalmazza/, vagy egyetlen
  csillag /"*"/. A csillag olyan commalist röviditése,
  mely a T1 tábla minden oszlopát megadja ezen táblán belül
  balról jobbra sorrendben. /Más szavakkal ebben az eset-
  ben a T2-es tábla azonos T1-es táblával/.
 /e/ Az INTO klauzula pontosan ugyanaz, mint FETCH esetén
  /lásd a 6.3-as alfejezetet/.
 /f/ A tábla kifejezés egy FROM klauzulából és egy opcioná-
  lis WHERE klauzulából áll. Megjegyzés: általában egy
  táblakifejezés GROUP BY klauzulát és/vagy HAVING klau-
  zulát is tartalmazhat /lásd a 9.5-ös alfejezetet/, de ebben
  a speciális környezetben ezek a klauzulák nincsenek
  megengedve. 
  Megjegyzések:
  1. Az SQL szabvány a "table expression" /tábla kife-
  jezés/-t használja arra, hogy a következö alaku kons-
  trukcióra hivatkozzon
  FROM ...
  [WHERE ...]
  [GROUP BY]
  [HAVING ...]
  Azonban félrevezetö dolog tábla kifejezésnek nevezni
  ezt a konstrukciót, mivel ez azt sugallja, hogy egy
  ilyen kifejezés az egyetlen konstrukció a nyelvben,
  amely tábla értéket reprezentál. Tulajdonképpen minden
  lekérdezés tábla értékü /ez a tény a relációs
  modell jól ismert lezárási /closure/ tulajdonságából
  következik és nagyon fontos. Vagyis egy "selest-expres-
  sion" /SELECT kifejezés/ tábla értékü. /*/ Egy SELECT-
  sql.doc Page: 55 
  expression egyszerüen speciális esete egy lekérdezés
  kifejezésnek; egy SELECT klauzulából áll, melyet tábla
  kifejezés /ezen kifejezés fenti - kifogásolt - értelmé-
  ben/ követ. Más szavakkal megfogalmazva, a teljes
  SELECT utasitás alapvetöen egyszerüen egy SELECT-expres-
  sion /kifejezés/ és mint ilyen természetesen tábla ér-
   tékü. 
 ----- ----- -----
 * Emlékezzen vissza a 6. fejezetböl arra, hogy a "SELECT-
 expression" /SELECT kifejezés/ nincs /és nem is lesz/ formá-
 lisan definiálva. Egyszerüen csak olyan informális kifejezés-
 ként használjuk, melynek a jelentését intuitiv módon nyil-
 vánvalónak vesszük. Ezt a megközelitést egyszerüen azért al-
 kalmazzuk, hogy elkerüljük azt, hogy a könyvben tul korán
 merüljünk bele a lekérdezés kifejezések teljes bonyolultságába. 
  2. Jegyezze meg, hogy a "selection" vagy skalár kife-
  jezések commalist-jéböl vagy egyetlen csillagból áll,
  nem pedig ezek együtteséböl. Igy a következö
  *** ILLEGAL *** /nincs megengedve/:
  SELECT *, (SP.QTY / 12)
  INTO ...
  FROM SP
  WHERE SP.SNO = 'S1'
  AND SP.SNO = 'P1'
  DB2-ben ez meg van engedve /mint ahogyan ennek igy is
  kell lennie/.
  3. Jegyezze meg, hogy a csillag nem lehet minösitett.
  Igy például a következö *** ILLEGAL *** /nincs megen-
  gedve/ :
  SELECT S.*, SP.QTY
  INTO ...
  FROM S.SP 
  WHERE S.SNO = 'S1'
  AND SP.SNO = 'S1'
  AND SP.PNO = 'P1'
  DB2-ben ez meg ven engedve /ennek igy is kell lennie/.
  4. Nincs megengedve, hogy egy SELECT klauzula tartal-
  mazza a DISTINCT kulcsszót egynél többször /tekintet
  nélkül arra, hogy a klauzula SELECT utasitásban, vagy
  bármilyen más környezetben jelenik meg/. Igy például a
  következö meg van engedve :
  SELECT DISTINCT SP.PNO ...
  és az alábbi is meg van engedve
  SELECT SP.PNO, SUM (DISTINCT SP.QTY) ...
  de a következö *** ILLEGAL *** nincs megengedve:
  SELECT DISTINCT SP.PNO, SUM DISTINCT SP.QTY ...
  és az alábbi sem:
  SELECT SUM (DISTINCT SP.QTY), AVG (DISTINCT SP.QTY)...
  Megjegyzés vége.   
   sql.doc Page: 56  
 7.3 INSERT 
 Az INSERT utasitást egy táblához uj sorok hozzáadására hasz-
 náljuk. Az alábbiakban két példát adunk meg: az elsö egyetlen
 sort szur be /insert/, a második több sort szur be. A máso-
 dik példához feltételezzük, hogy van egy további TEMP nevü
 táblánk, SNO és CITY oszlopokkal /ahol a TEMP.SNO és TEMP.CITY
 oszlopok adat tipusai kompatibilisek az S.SNO illetve S.CITY
 oszlopok adat tipusaival/. 
  INSERT
  INTO S (SNO, CITY, SNAME)
  VALUES (SNO_PARAM, NULL, SNAME_PARAM) 
  INSERT
  INTO TEMP (SNO, CITY)
  SELECT S.SNO, S.CITY
  FROM S
  WHERE S.STATUS > STATUS_PARAM 
 Az általános szintaxis: 
  INSERT INTO table[(column-commalist)] source 
 ahol "table" /tábla/ azonositja a cél táblát, a zárójelek
 közé zárt azonositók azonositják ezen tábla oszlopai közül
 valamelyiket, vagy mindegyiket /a nem minösitett oszlop ne-
 veikkel/ és a "source"-t /forrást/ az alábbiakban magyarázzuk
 el. Az oszlopnevek zárojelek közé helyezett "commalist"-
 jének kihagyása egyenértékü a cél tábla minden oszlopa meg-
 adásával, a táblán belüli balról jobbra sorrendben.
  Egy INSERT utasitásban a "source" vagy egy lekérdezés
 specifikáció /nem pontosan megfogalmazva, egy SELECT kifeje-
 zés; a részleteket lásd a 9, fejezetben/, vagy a következö
 alaku VALUES klauzula
  VALUES (insert-atom-commalist)
 ahol viszont az egyes "insert atom"-ok értéke vagy egy expli-
 cit null érték /melyet a NULL kulcsszó reprezentál/, vagy egy pa-
 raméter /opcionális indikátor paraméterrel/. /*/ 
 ----- ----- ------
 * EZ az USER "system variable" /rendszer változó/ is lehet
 /Lásd a 4.3 alfejezetet/. 
 Magyarázat: 
  1. Ha egy INSERT utasitás oszlop nevek olyan explicit
 commalist-jét tartalmazza, mely egy vagy több oszlopot ki-
 hagy a T cél táblából, akkor bármely sor, melyet ez az utasi-
 tás visz be a T-be, egy null értéket fog tartalmazni minden ilyen
 kihagyott oszlop helyen.
  2. Ha az INSERT utasitás tartalmaz egy VALUES klauzulát,
 akkor egyetlen sor kerül beszurásra a cél táblába. A VALUES
 klauzulában az i-edik "atom" azon i-edik bejgyzés által azo-
  sql.doc Page: 57 
 nositott oszlop helyre tevödik el, amely az INTO klauzulá-
 ban lévö oszlop nevek commalist-jében van /explicit vagy im-
 plicit módon/. 
 3. Ha az INSERT utasitás tartalmaz egy lekérdezés speci-
 fikációt, akkor a cél táblába /általában/ több sort szur be.
 A lekérdezési elöirás /specifkáció/ kiértékelésre kerül az
 R közbensö eredmény tábla létrehozására. Az R minden sora
 viszont ugy kezelödik, mintha az ebben a sorban lévö skalár ér-
 tékek "atomokként" lennének megadva az INSERT utasitás egy so-
 ros verziójában egy VALUES klauzulában. 
  Megjegyzés: Felhivjuk az olvasó figyelmét két megszigo-
  ritásra /mindkettö az IBM SQL-böl származó maradvány/:
  1. Elöször figyelje meg, hogy /mint ahogyan az 5.2-es
  alfejezetben megjelenitettük/ az olyan müveleti kifeje-
  zések, mint például PARAM + 1 nincsenek megengedve VALUES
  klauzulában.
  2. Ha az INSERT utasitás tartalmaz egy lekérdezés spe-
  cifikációt, az INSERT T cél táblájára nem szabad hivat-
  kozni semmilyen FROM klauzulában ezen lekérdezés specifi-
  káción belül. Igy például a következö *** ILLEGAL ***
  /nem megengedett/ : 
  INSERT
  INTO T
  SELECT *
  FROM T 
  /Még akkor is, ha a T tábla megengedi az ismétlödö sorokat/.
  Megjegyzés vége. 
 7.4 KERESETT UPDATE 
 A keresett UPDATE utasitást használjuk sorok aktualizálására
 egy táblában cursor használata nélkül. Az aktualizalas több
 soros /általában/; vagyis az utasitás egyetlen müveletben
 nulla, egy, kettö ... vagy bármilyen számu sort aktualizál.
 Az alábbiakban megadunk egy példát /a 2. fejezetböl vett példa
 egy variációja/:  
  UPDATE S
  SET STATUS = 2 * S.STATUS
  WHERE S.CITY = CITY_PARAM 
  Az általános szintaxis:
  UPDATE table
  SET assigment-commalist
  [WHERE search-condition] 
 ahol "table" a cél táblát azonositja, az értékadások comma-
 listje pontosan ugyanolyan, mint a pozicionált UPDATE esetén
 /lásd az 6.3-as alfejezetet/ és a "search condition" /keresési
 feltétel/ azonositja a cél tábla azon sorait, amelyeket aktu-
 alizálni kell. /A keresési feltételeket részletesen a 9. fe-
  sql.doc Page: 58 
 jezetben tárgyaljuk./ A WHERE klauzula kihagyása azt jelenti,
 hogy az UPDATE-t a céltábla minden sorához alkalmazni kell.
  Az UPDATE konceptuonális végrehajtása ugy történik, mint
 ha egy rejtett cursort /mondjuk H/ használnánk az aktualizá-
 landó sorokon történö végigfuttatásra és egy megfelelö pozicionált
 UPDATE ... WHERE CURRENT OF H-t alkalmaznánk egymást követöen
 minden ilyen sorhoz. 
  Megjegyzés: A keresett UPDATE müvelet az elözö alfejezet-
  ben az INSERT alatt megemlitett két megszoritás közül
  a másodikhoz hasonló megszoritástól "szenved": Ha az
  UPDATE utasitás tartalmaz egy WHERE klauzulát, akkor az
  UPDATE T cél táblázatára nem szabad hivatkozni a WHERE
  klauzulán belüli semmilyen FROM klauzulában /az egymásba
  ágyazás semmilyen szintjén - lásd a 9. fejezetet/. Igy
  például a következö *** ILLEGAL *** /nem megengedett/: 
  UPDATE S
  SET CITY = CITY_PARAM
  WHERE S.STATUS <
  (SELECT AVG (S.STATUS)
  FROM S) 
  Ez a megszigoritás az IBM SQL-böl származó további marad-
  vány. Megjegyzés vége. 
 7.5 KERESETT DELETE 
 A keresett DELETE utasitást használjuk sorok törlésére egy
 táblában cursor használata nélkül. A törlés több soros /álta-
 lában/; vagyis az utasitás nulla, egy, kettö ... vagy bármi-
 lyen számu sort töröl egyetlen müveletben. Az alábbiakban meg-
 adunk egy példát /a 2. fejezetböl vett példa egy variációja/: 
  DELETE
  FROM P
  WHERE P.WEIGHT > WEIGHT_PARAM 
  Az általános szintaxis: 
  DELETE
  FROM table
  [WHERE search-condition]   
 ahol "table" a cél táblát azonositja és "search condition" /ke-
 resési feltétel/ azonositja a cél tábla azon sorait, amelyeket
 törölni kell. /A keresési feltételeket részletesen a 9. feje-
 zetben tárgyaljuk./ A WHERE klauzula kihagyása azt jelenti,
 hogy a DELETE-t a cél tábla minden sorára alkalmazni kell. 
  A DELETE konceptuálisan úgy kerül végrehajtásra, mint ha
 egy rejtett cursort /mondjuk H/ használnánk a törlendö sorokon
 történö végigfuttatásra és egy megfelelö pozicionált DELETE ...
 CURRENT OF H-t alkalmaznánk egymást követöen minden ilyen sor-
 hoz. 
  sql.doc Page: 59  
  Megjegyzés: A keresett DELETE az elözö alfejezetben az
  UPDATE alatt megemlitett megszigoritáshoz hasonló megszi-
  goritástól szenved: ha a DELETE utasitás tartalmaz egy
  WHERE klauzulát, akkor a DELETE T cél táblájára nem sza-
   bad hivatkozni ezen WHERE klauzulán belül semelyik
  FROM klauzulában /semilyen beágyazási szinten - lásd
  a 9. fejezetet/. Igy például a következö *** ILLEGAL ***
  /nincs megengedve/: 
  DELETE
  FROM S
  WHERE S.STATUS <
   (SELECT AVG (S.STATUS)
  FROM S) 
  Ismét érvényes, hogy ez a megszigoritás az IBM SQL-böl
  származó maradvány. Megjegyzés vége.                                     
  sql.doc Page: 60  
  8
 -------- ----- ------ ----- ----- --------- ----- -------
 N é z e t e k 
 8.1 BEVEZETÉS 
 A 6. és 7. fejezetekben az egyszerüség kedvéért mindenhol
 szándékosan feltételeztük, hogy minden tábla alap tábla.
 Most figyelmünket azokra a speciális szempontokra irányit-
 juk, amelyek a nézetekre /vagy "viewed tables" /nézet táblák-
 ra, hogy a hivatalos szabvány kifejezéseit használjuk/, ér-
 vényesek. Emlékezzünk vissza a 2. fejezetböl, hogy egy nézet
 egy virtuálistábla - vagyis olyan tábla, ami nem létezik
 saját jogán, de a felhasználó számára ugy látszik, mintha
 létezne. /Ezzel ellentétben egy alap tábla valós tábla, abban
 az értelemben, hogy egy ilyen tábla minden sorához ténylege-
 sen tartozik ezen sor valamilyen tárolt megfelelöje a fizikai
 tárolóban./
  A nézeteket nem támogatják saját, fizikailag külön,
 megkülönböztethetö módon tárolt adataik. Mindaz ami bekö-
 vetkezik, amikor egy nézetet definiálnak csupán az, hogy a né-
 zetnek más táblák kifejezéseivel történö definicióját a
 rendszer valamilyen módon megjegyzi /ténylegesen a definiciónak a
 rendszer katalógusba történö tárolásával - de természetesen egy ka-
 talógus fogalma az SQL szabvány hatályán kivül van/. Megadunk
 erre egy példát: 
  CREATE VIEW GOODSUPPS (SNO, STATUS, CITY)
  AS SELECT S.SNO, S.STATUS, S.CITY
  FROM S
  WHERE S.STATUS > 15 
  Figyelje meg a hasonlóságot egy cursor definiálásával: egy
 cursor definiálásához hasonlóan egy nézet definició is tar-
 talmaz egy SELECT kifejezést, mely definiál bizonyos érvé-
 nyességi kört; /*/ és ugyanúgy mint a cursor definició esetén
 a SELECT kifejezés kiértékelése nem történik meg a definiá-
 lás idején. Azonban a felhasználó számára olyan, mintha
 valóban létezne egy tábla az adatbázisban a megadott névvel.
 A példában olyan, mintha valóban volna egy GOODSUPPS nevü
 tábla a 8.1-es ábra nem árnyékolt részein /csak ezeken a ré-
 szeken/ látható sorokkal és oszlopokkal. 
 ----- ----- --------------
 * Azonban jegyezze meg, hogy a nézet definiciók egy sémán 
 belül jelennek meg, ugyanakkor a cursor definiciók modulon
 belül jelennek meg. Ennek következtében egy nézet definició
 nem tartalmazhat semmilyen hivatkozásokat paraméterekre.      
  sql.doc  Page: 61  
 8.1 ábra. GOODSUPPS az S alap tábla nézeteként /nem árnyé-
  kolt részek/
  --- ----- ------ ------
  GOODSUPPS SNO SNAME STATUS CITY
  --- ----- ------ ------
  S1 Smith 20 London
  S2 Jones 10 Paris
  S3 Blake 30 Paris
  S4 Clark 20 London
  S5 Adams 30 Athens  
  Megadunk a GOODSUPPS-vel kapcsolatos SELECT müveletre
 egy példát: 
  SELECT *
  FROM GOODSUPPS
  WHERE GOODSUPPS.CITY <> 'London' 
  A rendszer le fogja forditani ezt a SELECT-et az alapul 
 szolgáló alap táblában, /vagy alap táblákban, többes számban,
 lásd a 8.2-es alfejezetet/ egy ekvivalens müveletre. 
 A forditás ugy történik, hogy a felhasználó által kiadott SELECT-et
 "összefésülik" a katalógusban megörzött SELECT-vel; lényegé-
 ben helyettesitve a nézetre hivatkozásokat a nézet definici-
 ójával. Ebben a példában eredményként létrejövö müvelet: 
  SELECT S.SNO, S.STATUS, S.CITY
  FROM S
  WHERE S.CITY <> 'London'
  AND S.STATUS > 15 
  Megjegyzés: Ebben a példában /ismét GOODSUPPS nézet/ a
 SELECT több soros és ebböl következik, hogy nem hajtható
 végre egy SELECT utasitásként, legalábbis a szabvány elöirása
 szerint nem. Ehelyett komponensként kell bevinni le-
 kérdezés kifejezésen vagy lekérdezés specifikáción, vagy
 más bonyolultabb nyelv konstrukción belül /például egy cursor
 definicióján belül/. A részleteket lásd a 9. fejezetben.
 Azonban az egyszerüség kedvéért kényelmes dolog feltételezni,
 hogy több soros SELECT-ek közvetlenül végrehajthatók és okta-
 tási okok miatt ezt a feltételezést fogjuk megtenni a jelen
 fejezet hátralevö részének nagy részében.
  A most bemutatott forditási folyamat az aktualizálási mü-
 veletekre is érvényes. Például a következö müvelet 
  UPDATE GOODSUPPS
  SET CITY = 'New York'
  WHERE S.STATUS.CITY = 'Paris' 
 az alábbira van leforditva 
  UPDATE S
  SET CITY = 'New York'
  WHERE S.CITY = 'Paris'
  sql.doc Page: 62 
  AND S.STATUS > 15 
  Az INSERT és DELETE müveletek kezelése ugyanilyen általá-
 nos módon történik. Például az alábbi INSERT müvelet 
  INSERT
  INTO GOODSUPPS (SNO, STATUS, CITY)
  VALUES ('S6',25, 'Madrid')  
 a következöre forditódik le: 
  INSERT
  INTO S (SNO, STATUS, CITY)
  VALUES ('S6', 25, 'Madrid') 
 /tehát jegyezze meg, hogy az SNAME null értéküre lesz állitva a be-
 szurt sorban/. Ehhez hasonlóan a DELETE müvelet 
  DELETE
  FROM GOODSUPPS
  WHERE GOODSUPPS.CITY = 'New York' 
 leforditódik az alábbira: 
  DELETE
  FROM S
  WHERE S.CITY = 'New York'
  AND S.STATUS > 15 
  Magyarázat: Szigorúan megvizsgálva a jelen alfejezet magya-
  rázatait, melyek arra vonatkoznak, hogy egy V nézetre hi-
  vatkozásokat ugy dolgozzák fel, hogy /konceptuálisan/ he-
  lyettesitik ezeket egy V definiciójával, kissé spekulativ-
  nak kell tekinteni. A hivatalos SQL szabvány valójában
  egyáltalán nem adja meg, hogy a nézetek hogyan vannak fel-
  dolgozva! Az egyetlen útmutatás, amit a szabvány megad,
  egy szabály ami közli, hogy egy V nézet értéke "az a tábla,
  ami akkor jön létre, ha a [ V definiciója ] végrehajtás-
  ra kerülne" egy olyan kijelentéssel együtt mely kimondja,
  hogy tekintet nélkül arra, hogy a V materializálva van-e
  vagy sem, ezt az implementáció definiálja. Azonban a né-
  zetekre vonatkozó számos korlátozások közül sok /lásd a
  8.3-as és 8.4-es alfejezeteket/ világosan annak valószinü-
  ségéböl származik, hogy a nézeteken müveleteket való-
  jában a fent leirt összefésülési /merging/ folyamat imp-
  lementálja. Magyarázat vége. 
 8.2 NÉZET DEFINICIO 
 A CREATE VIEW általános szintaxisa: 
  CREATE VIEW view [(column-commalist)]
  AS query-specification
  [WITH CHECK OPTION] 
  sql.doc Page: 63 
 ahol "view" /nézet/ az ujonnan létrehozott nézet nem minösitett
 neve /*/, az azonositók opcionális commalist-jében az azonosi-
 tók a nézet oszlopainak nem minösitett nevei, a lekérdezési
 specifikáció egy olyan SELECT kifejezés, amely a nézet érvé-
 nyességi körét definiálja /nem szigoruan megfogalmazva - a
 részleteket lásd a 9. fejezetben/ és a WITH CHECK OPTION klau-
 zulát a 8.4-es alfejezetben magyarázzuk el. Lásd az alábbi 
 elsö példában annak tárgyalását, hogy az oszlopnevek comma-
 list-je mikor hagyható ki. A nézet teljesen minösitett neve
 U.V, ahol U annak a sémának az AUTHORIZATION klauzulájában meg-
 adott meghatalmazás azonositó, amelyik a CREATE VIEW müveletet
 tartalmazza és a V ebben a müveletben /"view"-ként/ megadott
 azonositó.
 ----- ----- --------
 * Ténylegesen a név minösitett lehet, de ha minösitett, akkor
 a minösitönek a séma AUTHORIZATION klauzulában megadott megha-
 talmazás azonositónak kell lennie. 
 A CREATE VIEW-ben a lekérdezés specifikáció nem tartalmaz-
 hat semmilyen paraméter hivatkozásokat.
  Az alábbiakban megadunk néhány példát a CREATE VIEW-re. 
  1. CREATE VIEW REDPARTS (PNO, PNAME, WT, CITY)
  AS SELECT P.PNO, P.PNAME, P.WEIGHT, P.CITY
  FROM P
  WHERE P.COLOR = ' Red' 
 Ennek az utasitásnak a hatása a REDPERTS nevü uj nézet létre-
 hozása, négy oszlopppal, amelyek PNO, PNAME, WT, és CITY, az
 alapul szolgáló tábla négy oszlopának, a PNO-nak
 PNAME-nak, WEIGHT-nak illetve CITY-nek megfelelöen. A példa
 kedvéért explicit módon megadtuk az ujonnan létrehozott nézet
 oszlopainak neveit jóllehet a neveknek van egy nyilvánvaló
 készlete /PNO, PNAME, WEIGHT, CITY/, mely az alapul szolgáló
 táblázatból örökölhetö. Altalában az oszlop explicit megadá-
 sára csak akkor van szükség, ha valami másból származik, mint
 a FROM tábla /táblák/ /egyikének/ egyszerü oszlopából és/vagy
 a kép oszlopok közül kettö egyébként azonos nevü lenne. Meg-
 jegyezzük, hogy ezen utolsó két esetben explicit neveket kell
 megadni minden nézet oszlophoz, még akkor is, ha ezen oszlo-
 pok közül néhánynak nyilvánvaló örökölt neve van. 
  2. CREATE VIEW LREDPARTS
  AS SELECT REDPARTS.PNO, REDPARTS.WT
  FROM REDPARTS
  WHERE REDPARTS.CITY = 'London' 
 Tökéletesen lehetséges egy nézet definiálása más nézetek kife-
 jezéseivel, mint ahogyan ez a példa mutatja. Az LREDPARTS-hez
 az oszlopnevek PNO és WT /az REDPARTS-ból örökölve/. 
  3. CREATE VIEW CITYPARTS (SCITY,PCITY)
  AS SELECT S.CITY, P.CITY
  FROM S,SP P
  WHERE S.SNO = SP.SNO
  sql.doc Page: 64 
  AND SP.PNO = P.PNO 
 Ennek a nézetnek az a jelentése, hogy egy város név pár
 /X,Y/ fog megjelenni a nézetben, akkor és csakis akkor, ha egy
 szállitó, melynek telephelye x városban van, olyan alkatrészt
 szállit, amelyet y városban tárol. Például az S1 szállitó P1
 alkatrészt szállit; az S1 szállitó telephelye Londonban van
 és a P1 alkatrészt Londonban tárolja; és igy a /London,London/
 pár jelenik meg a nézetben. Jegyezze meg, hogy ennek a nézet-
 nek a definiciója tartalmaz egy összekapcsolást /valójában
 "három utas" összekapcsolás/ ugy hogy az egy olyan nézetre
 példa, amely több alapul szolgáló táblázatból származik. Azt is
 jegyezze meg, hogy a nézet oszlopaihoz tartozo örökölt nevek
 közül mindkettö CITY és ebböl az következik, hogy explicit
 módon uj oszlopneveket kell megadni az alábbiakban láthatóak 
 szerint 
  4. CREATE VIEW PQ (PNO, TOTQTY)
  AS SELECT SP.PNO, SUM(SP.QTY)
  FROM SP
  GROUP BY SP.PNO 
 Ebben a példában nincs olyan név, amely a "teljes mennyiség"
 oszlophoz örökölhetö, mivel ez az oszlop egy beépitett függ-
 vényböl származik; ebböl következik, hogy /ismét/ explicit
 módon uj oszlop neveket kell megadni a bemutatottak szerint.
 Azt is figyelje meg, hogy jóllehet ez a nézet egyetlen, alapul
 szolgáló alap táblából származik, nem csak egyszerüen sor és
 oszlop részhalmaza ennek az alap táblának /a korábban bemuta-
 tott REDPARTS és GOODSUPPS nézetekkel ellentétben/. Ehelyett 
 ezen alapul szolgáló tábla egyfajta statisztikai összefoglalá-
 sának és tömöritésének tekinthetö.  
 8.3 VISSZANYERESI MUVELETEK 
 Körvonalban már elmagyaraztuk /a 8.1-es alfejezetben/, hogy
 egy nézetlen visszanyerési müveletek hogyan vannak leforditva
 az alapul szolgáló alap táblán /táblákon/ ekvivalens müveletekre.
 Sok esetben ez a forditási eljárás /folyamat/ teljesen nyil-
 vánvaló /egyenes úton halad/ és tökéletesen jól müködik,
 anélkül, hogy bármilyen meglepetést okozna a felhasználónak.
 Esetenként azonban meglepetések keletkezhetnek. Vagyis prob-
 lémák merülhetnek fel azzal kapcsolatban, amit "csoportosi-
 tott nézeteknek" nevezünk. A PQ nézet /az elözö alfejezet-
 böl a 4-es példa/ példa egy csoportositott nézetre. Altalá-
 ban minden olyan nézet, melynek definiciója közvetlenül tar-
 talmaz egy GROUP BY klauzulát /vagy HAVING klauzulát - lásd
 a 9. fejezetet/ egy csoportositott nézet. Egy csoportositott
 nézet nézetét /vagyis olyan nézetet, melynek a definicioja
 közvetlenül tartalmaz egy csoportositott nézetre hivatkozó
 FROM klauzulát/ is csoportositott nézetnek tekintjük - és
 igy tovább, bármilyen számú szintig.
  A csoportositott nézetekre különbözö megszigoritások
 vonatkoznak. Elöször is, egy FROM klauzula számára, mely
  sql.doc Page: 65 
 hivatkozást tartalmaz csoportositott nézetre /akármilyen
 összefüggésben/ nincs megengedve, hogy bármilyen más táblára
 hivatkozzon; más szavakkal egy csoportositott nézet nem kap-
 csolható semmilyen más táblához. Ezenkivül egy csoportositott
 nézetre hivatkozó FROM klauzula számára nincs megengedve,
 hogy egy ehhez tartozó WHERE klauzulát, GROUP BY klauzulát, 
 vagy HAVING klauzulát tartalmazzon. A következö leirás az 
 ilyen megszoritások mögötti okfejtés vázlatos ismertetését
 reprezentálja. Vegyük szemügyre a következö példát.
  Nézet definició /megengedett/:  
  CREATE VIEW PQ (PNO, TOTQTY)
  AS SELECT SP.PNO, SUM (SP.QTY)
  FROM SP
  GROUP BY SP.PNO  
 /a 8.2-es alfejezetböl a 4-es példa ismétlése/.
   Megkisérelt lekérdezés /*** ILLEGAL ***/ /nem megengedett/:  
  SELECT PQ.PNO
  FROM PQ
  WHERE PQ.TOTQTY > 500 
  Ha a 8.1-es alfejezetben leirt egyszerü forditási eljárást
 alkalmazzuk ennek a kifejezésnek azzal a nézet definicióval
 egyesitésére /kombinálására/, amelyre a rendszer emlékezik,
 valami olyant kapunk, ami hasonlit a következöhöz: 
  SELECT SP.PNO
  FROM SP
  WHERE SUM (SP.QTY) > 500
  GROUP BY SP.PNO 
 És ez nem érvényes SELECT kifejezés. Nincs megengedve, hogy
 egy WHERE klauzulában lévö prédikátumok olyan beépitett függ-
 vényekre hivatkozzanak, mint például a SUM. Az amire az
 eredeti kifejezést át kell alakitani, valami olyasmi, ami a
 következö sorokban látható: 
  SELECT SP.PNO
  FROM SP
  GROUP BY SP.PNO
  HAVING SUM (SP.QTY) > 500  
 Azonban az SQL nem képes arra, hogy végrehajtson ilyen fordi-
 tást.
  Az alábbiakban megadunk egy másik példát olyan helyzetre,
 amelyben a forditás nem müködik /ismét a PQ "statisztikai
 összefoglaló" nézetet használva/. A megkisérelt lekérdezés: 
  SELECT AVG (PQ.TOTQTY)
  FROM PQ   
  sql.doc Page: 66  
 "Leforditott" alak: 
  SELECT AVG (SUM (SP.QTY))
  FROM SP
  GROUP BY SP.PNO 
 Ez ismét nem megengedett. Az SQL nem engedi meg, hogy a be-
 épitett függvények igy legyenek egymásba ágyazva. 
  Magyarázat: A megadott példák nem meritik ki a lehetö-
  ségeket. Hasonló kellemetlen meglepetések fordulhatnak
  elö, ha a nézet definició tartalmaz DISTINCT-et, vagy
  olyan oszlopot, amely egy müveleti kifejezésböl /például
  A + B/ származik, vagy pedig olyan oszlopot, amely egy
  beépitett függvényböl /még GROUP BY nélkül is/ származik.
  Ezenkivül nem könnyü pontosan jellemezni az ilyen "meg-
  lepetések" teljes halmazát. A legjobb, ami egy általános 
  irányelv segitségével megfogalmazhatónak látszik: az ere-
  deti lekérdezés leforditott alakjának mindig megengedett
  SQL SELECT-kifejezésnek kell lenni. A nézetek teljes terü-
  lete /különösen a visszanyerési szempont/ az SQL nyelv
  "legkomiszabb" részeinek egyike. Magyarázat vége. 
 8.4 AKTUALIZALASI MÜVELETEK 
 Egy adott nézet lehet, hogy aktualizálható, de lehet, hogy nem.
 Ezt a kijelentést a 8.1 illetve 8.2 alfejezetböl vett két nézet,
 a GOODSUPPS és CTYPAIRS segitségével mutatjuk be. A kényelmes 
 kezelés mód érdekében megismételjük ezek definicióit az alábbi-
 akban: 
  CREATE VIEW GOODSUPPS (SNO, STATUS, CITY)
  AS SELECT S.SNO, STATUS, S.CITY
  FROM S
  WHERE S.STATUS > 15  
  CREATE VIEW CITYPAIRS (SCITY, PCITY)
  AS SELECT S.CITY, P.CITY
  FROM S, SP, P
  WHERE S.SNO = SP.SNO
  AND SP.PNO = P.PNO 
  Ezen két nézet közül a GOODSUPPS logikailag aktualizál-
 ható, miközben a CITYPAIRS logikailag nem aktualizálható.
 Tanulságos dolog megvizsgálnunk, hogy miért van ez igy. A
 GOODSUPPS esetében:
 /a/ Beszúrhatunk /INSERT/ egy új sort a képbe - mondjuk a 
  /S6,40,Rome/ sort - a megfelelö sornak /S6,NULL,40,Rome/
  tényleges beszúrásával az alapul szolgáló alap táblába.
 /b/ Törölhetünk /DELETE/ egy meglévö sort a nézetböl - mond-
  juk a /S1,20,London/ - az alapul szolgáló alap táblából
  a megfelelö sor /S1,Smith,20,London/ tényleges törlésével.
 /c/ Aktualizálhatunk /UPDATE/ a nézeten egy meglévö értéket
  - mondjuk az S1 szállitóhoz tartozó CITY értéket /neve-
  sql.doc Page: 67 
  zetesen London-t/ megváltoztatjuk Rome-ra - úgy, hogy
  az alapul szolgáló alap táblában ténylegesen végrehajtjuk 
  a változtatást a megfelelö értékre. 
  Most vizsgáljuk meg a CITYPAIRS nézetet. Mint ahogyan a
 8.2-es alfejezetben elmagyaráztuk, ebben a nézetben a sorok
 közül az egyik /London,London/ sor. Tételezzük fel, hogy le-
 hetséges ennek a sornak a DELETE-je /törlése/. Mit kellene
 egy ilyen DELETE-nek jelölnie? - Vagyis az alapul szolgáló ada-
 tokon milyen aktualizálásoknak /DELETE-k vagy mások/ kellene
 egy ilyen DELETE-nek megegyeznie? Az egyetlen lehetséges vá-
 lasznak annak kell lennie, hogy "nem tudjuk"; egyszerüen nincs 
 mód /általában/, hogy eljuthassunk lefelé egészen az alapul
 szolgáló alap táblákhoz és itt végrehajthassuk az aktualizá-
 lások megfelelö halmazát. Tulajdonképpen még nem is létezik
 ilyen "megfelelö aktualizálás halmaz"; nincs olyan aktuali-
 zálás halmaz /készlet/, mely az alapul szolgáló adatokra al-
 kalmazható /általában/, melynek pontosan az lenne a hatása,
 hogy eltávolitaná a megadott sort a nézetböl, miközben minden
 mást változatlanul hagyna a nézetben. Más szavakkal megfogal-
 mazva, az eredeti DELETE a lényegéböl adódóan nem támogatható
 müvelet. Hasonló érvelések tehetök meg annak bemutatására,
 hogy /általában/ az INSERT és UPDATE müveletek ugyancsak
 a lényegükböl adódóan nem támogathatók ezen a nézeten.
  Igy látjuk, hogy néhány nézet a jellemzöiböl adódóan
 aktualizálható, ugyanakkor mások a jellemzöikböl adódóan nem.
 Figyelje meg itt a "jellemzöiböl adódó" /inherently/ szót.
 Nemcsak egyszerüen az a probléma, hogy néhány rendszer képes
 arra, hogy támogasson bizonyos aktualizálásokat, mig mások
 nem képesek erre. Nincs olyan rendszer, amelyik konzisztens
 módon támogathat aktualizálásokat segitség nélkül egy néze-
 ten, mint például a CITYPAIRS /"segitség nélkül" alatt " vala-
 milyen emberi felhasználótól érkezö segitség nélküli" esetet
 értünk/.
  Annak további leirását, hogy melyek azok a nézetek, ame-
 lyek elméletileg aktualizálhatók és melyek, amelyek nem, az
 olvasónak a szerzö Relational Database: Selected Writings
 /relációs adatbázis: válogatott irások/ /Addison-Wesley
 1986/ könyvében kell megnéznie. Azonban itt nem foglalkozunk
 túl sokat azzal, hogy mi az ami elméletileg lehetséges, hanem
 inkább azzal, hogy mi az amit az SQL meg fog engedni /ami na-
 gyon különbözö dolog/. SQL-ben egy nézet aktualizálható, akkor
 és csakis akkor, ha a következö feltételek /a/-/f/, mindegyike
 ki van elégitve a nézet definicióban /vagyis a nézetet defi-
 niáló SELECT kifejezésben/:
 /a/ Nem tartalmazza a DISTINCT kulcsszót.
 /b/ A SELECT klauzulában minden tétel az alapul szolgáló tábla
  egy oszlopára történö egyszerü hivatkozásból áll /vagyis
  nem konstans, nem olyan müveleti kifejezés, mint például
  C + 1, és nem hivatkozás egy olyan beépitett függvényre,
  mint például az AVG/.
 /c/ A FROM klauzula pontosan egyetlen táblát azonosit és ez
  a tábla viszont aktualizálható.
 /d/ A WHERE klauzula nem tartalmaz al-lekéredezést.
 /e/ Nincs GROUP BY klauzula.
  sql.doc  Page: 68 
 /f/ Nincs HAVING klauzula. 
  Végül /hogy a nyilvánvaló dolgot is megemlitsük/: az
 INSERT, UPDATE és DELETE müveletek egy SQL nézetre csak 
 akkor alkalmazhatók, ha ez a nézet aktualizálható a fent def-
 iniáltak szerint. 
  Magyarázat: Ezek a korlátozások nagyon nagy megszo-
  ritások. Ezen kivül néhány esetben logikailag is szük-
  ségtelenek. A DB2 SQL kissé kevésbé korlátozó hatású
  /jóllehet nem nagy a különbség/; DB2-ben a fenti /b/
  és /d/ szabályok kissé lazithatók, a következöképpen.
 /b/ DB2-ben, ha a nézet egy oszlopa egy beépitett függvény-
  böl származik, akkor a nézet nem aktualizálható. Ha 
  konstansból vagy olyan müveleti kifejezésböl származik,
  mint például C + 1, akkor az INSERT müveletek nincsenek 
  megengedve és az UPDATE müveletek sincsenek megengedve
  ebben az oszlopban. Azonban a DELETE müveletek meg vannak
  engedve és az UPDATE müveletek is meg vannak engedve más
  oszlopokon. 
 /d/ DB2-ben, ha a WHERE klauzula tartalmaz egy al-lekérde-
  zést és ebben az al-lekérdezésben a FROM klauzula arra
  az alap táblára hivatkozik, amelyben a nézet definiálva 
  van, akkor a nézet nem aktualizálható.
  Az alap probléma /mind a szabványos SQL-vel, mint a
   DB2-vel/ az, hogy a nyelv nagyon ad hoc állapotú: tele
  van orthogonalitás /=normalizáltság(itt)/ hiány esetekkel
  és nem veszi figyelembe a relációs modellböl az elsöd-
  leges és idegen kulcs alapvetö szemantikai elképzelése-
  it. Lásd a 12. fejezetben az "orthogonalitás" kifejezés 
  magyarázatát. Magyarázat vége. 
 A Check opció 
 Végül még egyszer visszatérünk a GOODSUPPS nézetre azért,
 hogy megtárgyaljunk egy utolsó kérdést. Mint ahogyan ennek
 az alfejezetnek az elején már elmagyaráztuk, ez a nézet ak-
 tualizálható. Azonban vizsgáljuk meg a következö UPDATE-t: 
  UPDATE GOODSUPPS
  SET STATUS = 0
  WHERE GOODSUPPS.SNO = 'S1' 
  Elfogadható ez az UPDATE ? Ha igen, az lesz a hatása,
 hogy eltávolitja az S1 szállitót a nézetböl, mivel az S1 sor
 a továbbiakban már nem fogja kielégiteni a /"S.STATUS > 15"/
 nézet definiáló feltételt. Ehhez hasonlóan az alábbi INSERT
 müvelet 
  INSERT
  INTO GOODSUPPS (SNO, STATUS, CITY)
  VALUES ('S8', 7, 'Stockholm')
 /ha elfogadásra kerül/ létre fog hozni egy új szállitó sort,
 de ez a sor azonnal el fog tünni a nézetböl. A check opció
  sql.doc Page: 69 
 /a 8.2-es fejezetben van megemlitve/ van kijelölve arra, hogy
 az ilyen helyzetekkel foglalkozzon. Ha az alábbi klauzula 
  WITH CHECK OPTION 
 szerepel egy nézet definiciójában, akkor ezen nézethez kiadott
 minden INSERT-et és UPDATE-t ellenörizni fog annak biztositá-
 sára, hogy az újonnan INSERTed /beszúrt/ vagy UPDATEd /aktua-
 lizált/ sor valóban kielégiti-e a nézet - definiáló feltételt.
 Ha nem elégiti ki, akkor a müvelet visszautasitódik.
  A check opció csak akkor adható meg, ha a nézet aktuali-
 zálható. 
  Magyarázatok:
  1. DB2-ben a check opció csak akkor adható meg, ha a
  nézet aktualizálható és a definiciója nem tartalmaz 
  al-lekérdezést. Ha a nézet olyan, hogy UPDATE-k csak bi-
  zonyos oszlopokon vannak megengedve /és INSERT-ek egyál-
  talán nincsenek megengedve/, akkor a check opció csak
  ezeken az oszlopokon UPDATE-kre érvényes.
  2. Jegyezzük meg, hogy /mint ahogy a 3.3-as alfejezet-
  ben is emlitettük, a check opció nem örökölhetö. Vagyis,
  ha V nézet definiciója tartalmaz WITH CHECK OPTION-t és
  W nézet a V nézet segitségével van definiálva, akkor a 
  W nézeten keresztüli V nézet aktualizálásokat nem ellen-
  örzi a V nézet check opciójával. A dolgok ilyen állása
  az IBM SQL-böl származó további "maradvány". Jobb lenne,
  ha olyan check opció lenne, amelyet a V nézetböl automa-
  tikusan örökölne az összes olyan W aktualizálható nézet,
  melyek V nézet kifejezéseivel vannak definiálva.
  3. Tulajdonképpen a check opció valamifajta általá-
  nos anomália. Különös dolog, hogy létezik egy ilyen 
  opció nézetekhez, de nem létezik alap táblákhoz. Megje-
  gyezzük, hogy egy "check opció alap táblákhoz" hatás
  elérhetö egy olyan nézet definiálásával, amely azonos
  a kérdéses alap táblával. Például: 
  CREATE VIEW V
  AS SELECT *
  FROM P
  WHERE P.WEIGHT > 0
  WITH CHECK OPTION 
  Ha P.WEIGHT oszlopon minden INSERT és P táblán minden
  INSERT végrehajtása ténylegesen V nézeten keresztül tör-
  ténik, akkor az SQL valójában az "alkatrész súlyoknak
  nullánál nagyobbnak kell lenniük" alap tábla követelményt
  lépteti érvénybe.
  Magyarázat vége.      
  sql.doc Page: 70  
   9
 -------- ----- ------ -------- ----- ------  
 Altalános nyelvkonstrukciók 
 9.1 LEKÉRDEZÉS KIFEJEZÉSEK 
 Ebben a fejezetben /végül is/ elmagyarázunk számos fontos 
 SQL konstrukciót, ilyen például a "keresési feltétel",amely-
 re nagyon sokszor hivatkoztunk az elözö fejezetben, de
 eddig még nem volt megfelelöen definiálva. A kérdéses
 konstrukciók számos különbözö kontextusban jelennek meg a
 nyelven belül. A "lekérdezés kifejezés" konstrukcióval kezd-
 jük, mivel sokféle szempontból tekintve ez a konstrukció te-
 kinthetö annak a konstrukciónak, amelyik a szintaxis fa tete-
 jén van. Bemutatjuk a BNF definicióját: 
  query-expression
  ::= query-term
  |query-expression UNION [ ALL ] query-term
  query-term
  ::= query-specification| (query-expression) 
  A "lekérdezés kifejezés" konstrukció csak cursor defini-
 ción belül jelenik meg /Azonban jegyezze meg, hogy UNION nincs
 megengedve SELECT utasitásban vagy INSERT ... SELECT-ben, vagy
 nézet definicióban./ /lásd a 6. fejezetet/. Amint a nyelvtan 
 jelzi, egy lekérdezés kifejezés alapvetöen egyszerüen egy le-
 kérdezés specifikáció, vagy két vagy több olyan lekérdezés 
 specifikáció /megadás/ együttese, melyeket UNION-ok kapcsolnak
 össze - ha eltekintünk attól, hogy a nyelvtan az UNION-t tisztán
 bináris müveletnek tekinti, ugy, hogy /például/ a három lekérde-
 zés specifikációt - x, y és z - tartalmazó lekérdezés kifejezést
 x UNION (y UNION z)-ként, vagy (x UNION y) UNION z-ként kell
 irni, nem pedig egyszerüen x UNION y UNION z-ként. A látszó-
 lag felesleges zárójelekre szükség van, mivel fennáll az a
 lehetöség, hogy az UNION-ok közül egy vagy több tartalmazhat 
 ALL-t /lásd lejjebb/; például az x UNION ALL (y UNION z) és
 (x UNION ALL y) UNION z kifejezések nem ekvivalensek. 
  Magyarázat: Követjük az SQL szabványt a "lekérdezés ki-
  fejezés" /query expression/ és "lekérdezés specifikáció"
  /query specification/ kifejezéseinek használatában, jól-
  lehet nem nagyon jól irják le azokat a konstrukciókat,
   amelyekre hivatkoznak. Az "UNION-kifejezés" / UNION-ex-
  pression/ és "SELECT-kifejezés" /SELECT-expression/ sorok
  menti kifejezések kielégitöbbek lehetnének. Magyarázat
  vége. 
  Legyen A és B két tábla, melyek /általában/ két lekérde-
 zés megadásból /specifikációból/ származnak. Pillanatnyilag
 feltételezzük, hogy az alábbi lekérdezés kifejezés
  A UNION [ ALL B ]
 meg van engedve /lásd lejjebb/. Ekkor ennek a kifejezésnek
  sql.doc Page: 71 
 az értéke egy tábla, mely tartalmaz egy sort minden olyan
 sorhoz, amelyik benne van az A táblában, vagy B táblában,
 vagy mindkét táblában. A redundáns ismétlödö sorok megörzödnek,
 pontosan akkor, ha az ALL kulcsszó meg van adva. Bemutatunk
 egy példát: 
  SELECT P.PNO FROM P WHERE P.WEIGHT > 16
  UNION
  SELECT SP.PNO FROM SP WHERE SP.SNO = 'S2' 
 Ennek a kifejezésnek az értéke a /P1, P2, P3, P6/ alkatrész 
 számok halmaza - vagyis az ismétlödések kimaradtak. Ha ALL
 meg lett volna adva, az értéknek /P1, P2, P2, P3, P6/- nek kellett
 volna lennie - vagyis az ismétlödéseket meg kellett volna
 örizni. Figyelje meg a különbséget az UNION és SELECT között
 az ismétlödés kihagyás szempontjából: SELECT-tel a felhasz-
 náló irhatja elö az ALL-t vagy DISTINCT-et és ALL az alap-
 értelmezés; UNION esetén a felhasználó csak az ALL-t adhatja 
 meg explicit módon /a megadás kihagyása olyan, mintha
 "DISTINCT-et" adnának meg /és "DISTINCT" /ha nincs más meg-
 adva/ az alapértelmezés.
  Visszatérve az érvényesség kérdésére /arra, hogy mi az
 ami meg van engedve/: Az alábbi lekérdezés kifejezés
  A UNION [ ALL B ]
 csak akkor van megengedve, ha minden i-hez, az A i-edik osz-
 lopa és a B i-edik oszlopa azonos leirásúak, vagyis leirásuk
 pontosan ugyanazt az adattipust és pontosan ugyanazt a hosz-
 szúságot /vagy pontosság, vagy pontosság és skála tényezö, az
 adott helyzetnek megfelelöen, /tartalmazza. Jegyezze meg, hogy
 például CHAR(4) nem ugyanaz, mint CHAR(5) és DECIMAL(5,2) nem
 ugyanaz, mint NUMERIC(5,2), vagy DECIMAL(6,2). Ezenkivül, ha 
 NOT NULL van bármelyik oszlopra elöirva, akkor mindkettöre
 elöirva kell lennie. 
  Magyarázat: Ezek a nagyon szigorú korlátozások az IBM
  SQL-böl származó további sajnálatos maradványt képvi-
  selnek. Az UNION müveletnek a gyakorlatban a használatát
  nagyon nehézkessé teszik. Magyarázat vége. 
  Mint ahogyan korábban már jeleztük, a "lekérdezés kife-
 jezés" konstrukció csak egy cursor definicióján belül jele-
 nik meg. A célja annak a lekérdezésnek a definiálása, amelyik
 a cursorhoz kapcsolódik és ebböl következöen azon sorok halma-
 zának a meghatározása, melyek ezen cursor-on keresztül feldol-
 gozhatók, amikor a cursor meg van nyitva. 
 9.2 LEKÉRDEZÉS SPECIFIKACIóK 
 Egy lekérdezés specifikáció úgy jelenik meg, mint egy komponense
 egy lekérdezés kifejezésnek. Ezenkivül az INSERT utasitás
 többsoros formátumában /lásd a 7. fejezetben/ és egy nézet
 definicióban /lásd 8. fejezetben/ is megjelenik. Szintak-
 tikailag azonos egy SELECT utasitással, eltekintve attól,hogy a 
 SELECT utasitás tartalmaz INTO klauzulát. Azonban szemantikailag
 eltér a SELECT utasitástól abban, hogy az értéke /általában/
  sql.doc Page: 72 
 többsoros tábla, ugyanakkor a SELECT utasitásnak legfeljebb
 egy sort kell visszaadnia /legalábbis a szabványos SQL-ben/.
 A szintaxis a következö: 
  query specification
  ::= SELECT [ ALL | DISTINCT ] selection
  table-expression 
 ahol az ALL, a DISTINCT és a "selection" /kiválasztás/ pontosan
 ugyanaz, mint egy SELECT utasitásban /lásd a 7.2-es alfeje-
 zetet/ és "table-expression" /tábla kifejezés/ a 9.5-ös
 alfejezetben van definiálva. Megjegyzés: Mint ahogyan a
 7.2-es alfejezetben elmagyaráztuk, a "selection" konstruk-
 ció alapvetöen "scalar expressions" /skalár kifejezések/
 commalist-je. A skalár kifejezések a 9.3-as alfejezetben
 vannak definiálva.
  Az alábbiakban bemutatunk egy eléggé bonyolult példát
 lekérdezés specifikációra: 
  SELECT P.PNO 'Weight in grams =', P.WEIGHT * 454, P.COLOR
  'Max shipped quantity =', MAX (SP,QTY)
  FROM P, SP
  WHERE P.PNO = SP.PNO
  AND (P.COLOR = 'RED' OR P.COLOR = 'Blue)
  AND SP.QTY > 200
  GROUP BY P.PNO, P.WEIGHT, P.COLOR
  HAVING SUM (SP.QTY) > 350 
 Ezt a példát részletesen a 9.5-ös alfejezetben tárgyaljuk.  
 9.3 SKALAR KIFEJEZÉSEK 
 Skalár kifejezések sok kontextusban megjelennek. Ezeket a 
 kifejezéseket egyedi skalár /vagyis karakter lánc vagy nume-
 rikus/ értékek reprezentálására használjuk. Az általános
 szintaxisuk a következö: 
  scalar-expression
  ::= term
  |scalar-expression (+|-) term 
  term
  ::= factor
  |term (*|/) factor 
  factor
  ::= (+|-) primary 
  primary
  ::= atom
  |column-reference
  |function-reference
  |(scalar-expression) 
  sql.doc Page: 73  
  Amint a BNF mutatja, egy saklár kifejezés alapvetöen
 aritmetikai kifejezés, mely "primaries" /elsödlegesek/ gyüj-
 teményét tartalmazza - ahol egy elsödleges /primary/ atom,
 oszlop hivatkozás vagy függvény hivatkozás. A kifejezés
 tartalmazhatja a + és - prefixum /elötag/, valamint a +,-,*, 
 és / infixum (beékelési) operátorokat, illetve zárójeleket tar-
 talmazhat a kiértékelés kivánt sorrendjének kikényszeritésére. 
 Megjegyzés: Az aritmetikai operátorok nem alkalmazhatók karakter-
 füzér tipusú elsödlegesekre. A függvényeket a következö alfe-
 jezetben tárgyaljuk. Az egyéb "elsödleges" /primary/ tárgyakat,
 nevezetesen az atomokat és oszlop hivatkozásokat, az alábbiakban
 irjuk le. 
  atom
  ::= parameter-reference
  |literal
  |USER 
  parameter-reference
  ::= parameter[[INDICATOR]parameter] 
 Az atom egy paraméter hivatkozás /az 5. fejezetben tárgyaltuk/
 vagy literal /a 3. fejezetben tárgyaltuk/, vagy USER rendszer
 változó /a 4. fejezetben tárgyaltuk/. 
  column-reference
  ::= [column-qualifier . ]column 
 Egy oszlop hivatkozás /column reference/ egy /esetleg minö-
 sitett/ oszlop név. 
  Magyarázat: 
  1. Figyelje meg, hogy a NULL nem atom; igy például
  nem lehetséges SELECT NULL /null kiválasztás/.
  2. Azt is figyelje meg, hogy egy SELECT kifejezés
  nem skalár kifejezés, még akkor sem, ha valójában ska-
  lár értéket ad vissza. Igy például nem lehetséges
  /egyetlen UPDATE utasitáson belül/ valamilyen értéket
  aktualizálni /UPDATE/ olyan értékkel helyettesitve, me-
  lyet az adatbázisban lévö valamilyen másik helyröl 
  származik.
  3. Az SQL szabvány tartalmaz szabályokat egy skalár
  kifejezés eredményének adat tipusához, pontosságához,
  stb. /jóllehet nem a "nem nullságot" /NOT NULL/ vagy
  ehhez hasonlót/. Aznban sok esetben mindaz amit a
  szabály mond, az hogy "implementáció definiálta" - ez
  egy sajnálatos helyzet, figyelembe véve az ilyen ügyek
  kritikus szemre vételezesét bizonyos kontextusokban
  /lásd a 9.1-es alfejezetben az UNION leirását/. Nem tö-
  rödünk most azzal, hogy a szabályokat itt részletesen
  megfogalmazzuk.
  Magyarázat vége. 
  sql.doc Page: 74  
 9.4 FÜGGVÉNYEK 
 A szabványos SQL öt beépitett függvényböl álló készletet
 ad meg: COUNT, SUM, AVG, MAX, és MIN (*). A COUNT (*) speciális
 esetétöl eltekintve - lásd késöbb - ezeknek a függvényeknek 
 mindegyike valamilyen tábla /rendszerint származtatott tábla,
 vagyis adott alap táblákból valamilyen módon létrehozott
 tábla/ egyik oszlopában lévö skalár értékek gyüjteményén
 /együttesén/ fejtik ki a hatásukat és eredményként egyet-
 len skalár értéket hoznak létre, mely a következöképpen van
 definiálva: 
  COUNT skalárok száma az oszlopban
  SUM skalárok összege az oszlopban
  AVG skalárok átlaga az oszlopban
  MAX legnagyobb skalár az oszlopban
  MIN legkisebb skalár az oszlopban. 
 Egy függvény hivatkozás a skalár kifejezés speciális esete. 
 ---------- 
 * Az EXISTS /lásd a 9.8-as alfejezetet/ is függvénynek te-
 kinthetö; azonban az EXISTS eltér a jelen alfejezetben tár-
 gyalt függvényektöl, annyiban, hogy /a/ az argumentuma más szin-
 taktikai stilusban van megadva /valójában logikusabb stilus-
 ban/ és /b/ igaz értéket ad vissza, nem pedig egy számot vagy
 karakter füzért, az igaz értékek pedig nem SQL tipusuak.  
 A szintaxis a következö: 
  function-reference
  ::= COUNT(*)
  |distinct-function-reference
  |all-function-reference 
  distinct-function-reference
  ::= 
   (DISTINCT column-reference) 
  all-function-reference
  ::= 
  (ALL scalar-expression) 
  SUM és AVG esetén az argumentumnak numerikus tipusunak
 kell lennie. Altalában, ahogyan ezt a nyelvtan jelzi, 
 az argumentumot opcionálisan megelözheti a DISTINCT kulcsszó,
 annak jelzésére, hogy a redundáns ismétlödö értékeket ki kell
 hagyni a függvény alkalmazása elött /a DISTINC-hez az alter-
 nativa az ALL; ALL az alap értelmezés, ha semmi más nincs
 megadva. COUNT esetén DISTINCT-nek is megadottnak kell lennie;
 a COUNT(*) speciális függvény - DISTINCT nincs megengedve - 
 egy táblában az összes sor megszámlálásához van biztositva, minden-
  sql.doc Page: 75 
 féle ismétlödés kihagyás nélkül. Ha DISTINCT meg van adva,
 akkor /ismét a BNF-ben jelzettek szerint/ az argumentumnak
 csak egy egyszerü oszlop referenciából szabad állnia; ha DISTINCT
 nincs megadva, az argumentum olyan müveleti kifejezésböl állhat,
 mint például P.WEIGHT*454. Azonban még ha a DISTINCT nincs is
 megadva, az argumentum akkor sem tartalmazhat semmilyen függvény
 hivatkozást - vagyis függvény hivatkozások nem lehetnek
 egymásba ágyazva.
  Az argumentumból minden null mindig kihagyásra kerül /ki-
 iktatódik/ a függvény alkalmazása elött, tekintet nélkül arra,
 hogy a DISTINCT meg van-e adva, kivéve, COUNT(*) esetében, ahol
 a null-ok kezelése éppugy történik, mint a nem null értékeké.
 Ha az argumentum történetesen üres halmaz, a COUNT nulla ér-
 téket ad vissza; a többi függvény mindegyike null értéket
 ad vissza. 
  Magyarázat: Mindezen különbözö speciális szabály és kor-
  látozás, melyek az olyan dolgokkal kapcsolatosak, mint
  például a DISTINCT és a függvény argumentum közötti kölcsön-
  hatás /stb./ mégegyszer újra az IBM SQL-böl származó
  maradvány. Egyébként azt is jegyezzük meg, hogy ténylege-
  sen nincs értelme annak, hogy DISTINCT-et MAX-val vagy
  MIN-vel adjuk meg, mivel ennek nem lehet semmilyen lo-
  gikai hatása. Magyarázat vége. 
  Megadunk néhány példát a függvények hasznalatára. A kö-
 vetkezö példák közül mindegyik szingli SELECT utasitás alap-
 jául szolgálhat, vagy beágyazható valamilyen bonyolultabb
 kifejezésbe, ilyen például egy lekérdezés kifejezés
 /lásd a 9.1-es alfejezetet/. Megjegyzés: Ha egy függvény hi-
 vatkozás megjelenik SELECT klauzulán belül és a SELECT kifeje-
 zés nem tartalmaz GROUP BY klauzulát, akkor a SELECT klauzu-
 lának csak függvény hivatkozásokból szabad állnia. Például,
 a következö *** ILLEGAL *** /nincs megengedve/: 
  SELECT SP.PNO,AVG(SP.QTY)
  FROM SP 
 1. példa: Keressük meg a szállitók össz-számát: 
  SELECT COUNT(*)
  FROM S 
 Eredmény: 5 /vagyis egy tábla, mely egyetlen megnevezett
 oszlopból és az 5-ös egyedüli értéket tartalmazó egyetlen
 sorból áll/. 
 2. példa: Keressük meg azoknak a szállitóknak az össz-számát,
 akik jelenleg alkatrészeket szállitanak. 
  SELECT COUNT ( DISTINCT SP.SNO )
  FROM SP 
 Eredmény: 4. 
  sql.doc  Page: 76  
 3. példa. Keressük meg a P2-es alkatrészhez a szállitmányok
 számát. 
  SELECT COUNT(*)
  FROM SP
  WHERE SP.PNO = 'P2' 
 Eredmény: 4. Figyelje meg, hogy az a tábla, amelyhez a COUNT*
 alkalmazva van, ebben a példában, egy származtatott tábla,
 nevezetesen az a tábla, melyet az alábbi kifejezés reprezentál
  SP WHERE SP.PNO = 'P2'
 /az SP tábla sorainak egy részhalmaza/. 
 4. példa: Keressük meg a leszállitott P2 alkatrész teljes meny-
 nyiségét. 
  SELECT SUM (SP.QTY)
  FROM SP
  WHERE SP.PNO = 'P2' 
 Eredmény: 1000. 
 5. példa: Keressük meg azon szállitókhoz tartozó szállitó szá-
 mokat, melyek állapot értéke kisebb, mint a jelenlegi maximális állapot
 érték az S táblában. 
  SELECT S.SNO
  FROM S
  WHERE S.STATUS<
  (SELECT MAX (S.STATUS)
  FROM S) 
 Eredmény: Egyoszlopos /SNO oszlop nevü/ tábla; az S1, S2 és
 S4 értékeket tartalmazza. 
 6. példa: Keressük meg azon szállitókhoz tartozó szállitó
 számokat, melyek állapota nagyobb mint, vagy egyenlö a váro-
 saikhoz tartozó átlaggal. 
  SELECT SX.SNO
  FROM S SX
  WHERE SX.STATUS>=
  (SELECT AVG (SY.STATUS)
  FROM S SY
  WHERE SY.CITY = SX.CITY) 
 Eredmény: Egyoszlopos /SNO oszlop nevü/ tábla, mely S1, S3,
 S4, és S5 értékeket tartalmazza. Megjegyzés: Ez a példa bemutatja
 mind egy függvény használatát egy "al lekérdezésben", mind
  pedig a "tartomány változók" /range variables/ /SX és SY/ hasz-
 nálatát. Lásd a 9.8-as illetve 9.5-ös /7-es példa/ alfejezetek-
 ben ezeknek a fogalmaknak a magyarázatait.  
  sql.doc Page: 77  
 9.5 TABLA KIFEJEZÉSEK 
 A tábla kifejezés(*) a következö alakú kifejezés 
  from-clause
  [where-clause]
  [group-by-clause]
  [having-clause] 
 ----- ----- -----------
 * Lásd a 7.2-es alfejezetben leirt megjegyzest arra, hogy a 
 "tábla kifejezés" /table expression/ miért nem nagyon jó
 elnevezés ehhez a konstrukcióhoz. 
  Tábla kifejezéseket használunk SELECT utasitásokban és
 lekérdezés megadásokban /valamint al-lekérdezésekben, melyek
 egy lekérdezés megadás speciális esetének tekinthetök - lásd
 a 9.8-as alfejezetet/. Azoknak a különbözö klauzuláknak, melyek
 egy tábla kifejezést felépitenek, a következö a szintaxisuk: 
  from-clause
  ::= FROM table-reference-commalist 
  table-reference
  ::= table [range-variable] 
  Itt a "table" /tábla/ /egy minösitett vagy nem minösitett/
 tábla név, mely vagy egy alap táblát, vagy egy nézetet azono-
 sit. Lásd a 7. példában a jelen alfejezet késöbbi részében,
 az opcionális "range-variable" /tartomány változó/ magyaráza-
 tát. 
  where-clause
  ::= WHERE search-condition 
 A keresési feltételeket részletesen a következö alfejezetben
 tárgyaljuk. 
  group-by-clause
   ::=GROUP BY column-reference-commalist 
 Mint ahogyan a 9.3-as alfejezetben elmagyaráztuk, egy oszlop
 hivatkozás egyszerüen minösitett, vagy nem minösitett oszlop
 név. 
  having-clause
  ::= HAVING search-condition 
 Ismét elmondjuk, hogy a keresési feltételeket a következö
 alfejezetben tárgyaljuk.
  Az alábbiakban megadunk néhány példát a tábla kifejezé-
 sekre. Ezek nagyrészét további magyarázat nélkül adjuk meg;
 azonban megjegyezzük, hogy a 3-7-es példák mindegyike a relá-
 ciós összekapcsolási müveletet mutatja be /nézze át a 2. fe-
  sql.doc Page: 78 
 jezetet, ha szüksége van arra, hogy felfrissitse az emlékeze-
 tét az összekapcsolásokkal kapcsolatban/. Megjegyzés: azért
 hogy a példákat kissé valósabbá tegyük, mindegyik elé elhe-
 lyezünk egy megfelelö SELECT klauzulát /igy tulajdonképpen
 átalakitjuk ezeket lekérdezés megadásokká, ahelyett hogy tisz-
 tán tábla kifejezések lennének/. De világosan meg kell érteni,
 hogy természetesen a SELECT klauzula nem része a tábla kife-
 jezésnek. 
 1. példa: Keressük meg az alkatrész számokat az összes leszál-
 litott alkatrészhez. 
  SELECT SP.PNO
  FROM SP 
 Vagy ha az ismétlödések kihagyására van szükség: 
  SELECT DISTINCT SP.PNO
  FROM SP 
 2. példa: Keressük meg azon párizsi szállitók szállitó számait,
 melyek állapota >20. 
  SELECT S.SNO
  FROM S
  WHERE S.CITY = 'Paris'
  AND S.STATUS >20 
 3. példa: Keressük meg az összes olyan szállitószám/alkatrész
 szám kombinációt, amelyeknál a kérdéses szállitó és alkatrész
 ugyanabban a városban található. 
  SELECT S.SNO, P.PNO
  FROM S, P
  WHERE S.CITY = P.CITY 
 4. példa: Keressük meg az összes olyan szállitószám/alkatrész
 szám kombinációt, amelynél a szállitó városa ABC szerinti
 sorrendben követi az alkatrész városát. 
  SELECT S.SNO, P.PNO
  FROM S, P
  WHERE S.CITY > P.CITY 
 5. példa: Keressük meg az összes olyan szállitó szám/alkatrész
 szám kombinációt, amelynél a szállitó és a kérdéses alkatrész
 ugyanabban a városban található, de kihagyva a 20-as állapotú 
 szállitókat. 
  SELECT S.SNO, P.PNO
  FROM S, P
  WHERE S.CITY = P.CITY
  AND S.STATUS<>20   
  sql.doc Page: 79  
 6. példa: Keressük meg az összes olyan város név párt, ame-
 lyiknél az elsö városban levö szállitó a második városban
 tárolt alkatrészt szállit. 
  SELECT DISTINCT S.CITY, P.CITY
  FROM S, SP, P
  WHERE S.SNO = SP.SNO
  AND SP.PNO = P.PNO 
 Megjegyezzük, hogy ez a példa három tábla összekapcsolását
 foglalja magában. 
 7. példa: Keressük meg a szállitó számok minden olyan párját,
 amelyeknél az érintett két szállitó ugyanabban a városban ta-
 lálható. 
  SELECT FIRST.SNO, SECOND.SNO
  FROM S FIRST, S SECOND
  WHERE FIRST.CITY = SECOND.CITY 
 Ez a példa magában foglalja az S tábla önmagával /megegyezö
 városokon keresztüli/ összekapcsolását ugy, ahogyan ezt most
 elmagyarázzuk. Egy pillanatra feltételezzük, hogy az S tábla
 két külön példányával rendelkezünk, az "elsö" példánnyal és
 a "második" példánnyal. Ekkor a lekérdezés logikája a követ-
 kezö: képesnek kell lennünk arra, hogy megvizsgaljuk a szál-
 litó sorok minden lehetséges párját, egyet az S elsö példá-
 nyából és egyet a másodikból, és hogy visszanyerjük a két
 szállitó számot az ilyen sor párból, amikor a város értékek
 egyenlöek. Ezért képesnek kell lennünk arra, hogy egyidejü-
 leg hivatkozzunk két szállitó sorra. Azért, hogy különbséget
 tegyünk a két hivatkozás között, bevezetünk két tartomány
 változót, a FIRST-et és SECOND-ot, melyek közül mindkettö az
 S tábla fölötti tartomány /"ranges over"/ a kifejezést
 tartalmazó kiértékelés végrehajtásának idejére. Bármely adott
 idöpontban a FIRST valamilyen sort reprezentál az S tábla
 "first" /elsö/ másolatából /példányából/ és "second" valami-
 lyen sort reprezentál a SECOND /második/ példányból. A le-
 kérdezés eredménye ugy kapható meg, hogy meg kell vizsgálni
 a FIRST/SECOND értékek összes lehetséges párját és minden
 esetben ellenörizni kell a WHERE feltételt.
   --- ---
  SNO SNO
  --- ---
  S1 S1
  S1 S4
  S2 S2
  S2 S3
  S3 S2
  S3 S3
  S4 S1
  S4 S4
  S5 S5
  Rendezhetjük ezt az eredményt a WHERE klauzula kiterjesz-
   sql.doc Page: 80 
 tésével a következöképpen: 
  SELECT FIRST.SNO, SECOND.SNO
  FROM S FIRST, S SECOND
  WHERE FIRST.CITY = SECOND.CITY
  AND FIRST.SNO 20
 A tartomány változó itt SX és az S táblára terjed ki, 
 ----- ----- ---------
 * A példák jelen sorozatában ez igy is van. Egy másik példa
 található a 9.4-es alfejezetben. /6-os példa/.  
  Valójában az SQL mindig megköveteli, hogy a lekérdezések
 tartomány változók kifejezéseiböl legyenek összeállitva (kia-
 lakitva). Ha nincs explicit módon megadva ilyen változó, ak-
 kor SQL feltételezi az olyan implicit változók létezését,
 melyeknek ugyanaz a nevük (neveik), mint a megfelelö táblá-
 nak (tábláknak). Például az alábbi lekérdezést 
  SELECT T.C
   FROM T
  ..... 
 az SQL úgy kezeli, minha a következöképpen lett volna kife-
 jezve:
  sql.doc Page: 81  
  SELECT T.C
  FROM T T
  ..... 
 - más szavakkal "T" önmaga egy alapértelmezés szerinti tar-
 tomány változónév, mely azon T nevü tartomány változót reprezen-
 tálja, amely a T nevü táblára terjed ki.
  Megjegyzés: Az SQL szabvány a "correlation variable" (kor-
 relációs változó) kifejezést használja a hagyományosabb ki-
 fejezés, a "range variable" (tartomány változó) helyett. Egy
 olyan névre, mint például a fenti példában lévö SX "correla-
 tion name"-ként (korrelációs névként) hivatkozik. Azonban,
 ebben a könyvben általában ragaszkodni fogunk a "range variab-
 le"-hez (tartomány változóhoz). 
 8. példa. Minden egyes leszállitott alkatrészhez keresse meg
 az alkatrész számot és az ehhez az alkatrészhez tartozó tel-
 jes szállitási mennyiséget. 
  SELECT PNO, SUM ( SP.QTY )
  FROM SP
  GROUP BY SP.PNO 
 Eredmény: --- ---
   PNO
  --- ---
  P1 600
  P2 1000
  P3 400
  P4 500
  P5 500
  P6 100 
  A GROUP BY operátor konceptuálisan átrendezi a FROM klau-
 zula (és a WHERE klauzula, ha meg van adva) által reprezentált
 táblát minimális számú particióba vagy csoportba úgy,
 hogy bármely adott csoporton belül minden sor azonos értéket
 tartalmazzon a GROUP BY oszlophoz. A példában az SP tábla úgy
 van csoportositva, hogy egyetlen csoport tartalmazza a P1 al-
 katrészhez tartozó összes sort, egy másik tartalmazza a P2 al-
 katrészhez tartozó összes sort, és igy tovább. Az eredmény egy
 csoportositott tábla. (A csoportositott nézetek, ezeket már
 tárgyaltuk a 8.3 alfejezetben, a csoportositott tábla speciá-
 lis esete.) 
  Ha egy csoportositott táblához SELECT klauzulát alkalmaz-
 nak (mint ebben a példában), akkor ebben a "SELECT klauzulában
 a "selection"-ban (kiválasztásban) minden kifejezésnek (lásd a
 7.2 fejezetet) csoportonként egy értékünek kell lennie; va-
 gyis ez egy hivatkozás lehet magára a GROUP BY oszlopra (vagy
 egy aritmetikai kifejezés, amely tartalmazza ezt az oszlopot)
 vagy literál, vagy olyan függvény lehet, mint például a SUM,
 ami egy csoporton belül egy adott oszlopban lévö minden érték-
 re kifejti a hatását , és ezeket az értékeket egyetlen skalár 
  sql.doc Page: 82 
 értékére redukálja. 
  Egy tábla az oszlopai bármilyen kombinációja szerint cso-
 portositható. 
 9.példa. Minden leszállitott alkatrészhez keressÜk meg ezen
 alkatrésznek az alkatrész számát, a leszállitott maximális meny-
 nyiséget és minimális mennyiséget, kizárva az S1 szállitó ál-
 tal szállitott szállitmányokat.  
  SELECT SP.PNO, MAX ( SP.QTY ), MIN (SP.QTY )
  FROM SP
  WHERE SP,SNO <> 'S1'
  GROUP BY SP.PNO
  --- --- ---
  Eredmény : PNO
  --- --- ---
  P1 300 300
  P2 400 200
  P4  300 300
  P5 400 400 
 Kimaradtak azok a sorok , amelyek nem elégitik ki a WHERE klau-
 zulát, mielött bármilyen csoportositás történt volna. 
 10.példa: Keressük meg az alkatrész számokat minden olyan al-
 katrészhez , melyet egynél több szállitó szállitott. 
  SELECT SP.PNO
  FROM SP
  GROUP BY SP.PNO
  HAVING COUNT(*)>1 
 A HAVING klauzula "egy WHERE klauzula csoporthoz"; vagyis 
 HAVING-ot használunk csoportok kihagyására éppúgy, mint ahogy
 WHERE-t használunk sorok kihagyására. Igy, ha HAVING meg van
 adva, GROUP BY-nak is megadottnak kell lennie.*
 Egy HAVING klauzulában a kifejezéseknek csoportonként egy ér-
 téküeknek kell lenniük (a gyakorlatban ezek majdnem mindig 
 függvény hivatkozások, éppúgy , mint a példában.    
 -----
 * Tulajdonképpen lehetséges ,jóllehet szokatlan,HAVING-ot megad-
 ni és GROUP BY-t nem; a hatás egyszerüen az, hogy a teljes
 táblázat úgy tekintödik , mintha egyetlen csoport lenne.       
  sql.doc Page: 83  
 Egy átfogó példa
 ----- ----- ------ 
 A jelen alfejezetet egy átfogó példával fejezzük be, ami bemu-
 tatja, hogy a fent tárgyalt jellemzök közül sok (semmi eset-
 re sem az összes) hogyan használható együtt, egyetlen kifeje-
 zésben. Ezen kivül egy konceptuális algoritmust (vagyis for-
 mális definició vázlatot) is megadunk a tábla kifejezések ál-
 talános kiértékeléséhez. 
 Példa: Minden vörös és kék alkatrészhez , úgy,hogy a leszálli-
 tott teljes mennyiség 350-nél nagyobb legyen (kizárva a teljes
 leszállitásból az olyan szállitmányokat, melyekhez a mennyiség
 200-nál kisebb, vagy 200-zal egyenlö, keressük meg ezen alkat-
 résznek az alkatrész számát, a súlyát grammban, a szinét és a
 maximális leszállitott mennyiségét. (Ez az a példa, amelyik
 a 9.2 alfejezet végén látható. A példa kedvéért feltételezzük,
 hogy a súly értékek a P táblában fontokban vannak megadva).  
  SELECT P.PNO, 'Weight in grams = ', P.WEIGHT * 454 ,P.COLOR,
  'Max shipped quantity = ' , MAX ( SP.QTY ) 
  FROM P,SP
  WHERE P.PNO = SP.PNO
  AND ( P.COLOR = 'Red' OR P.COLOR = 'Blue' )
  AND SP.QTY >200
  GROUP BY P.PNO, P.WEIGHT, P.COLOR
  HAVING SUM ( SP.QTY ) > 350   
  Magyarázat:Egy SELECT kifejezés klauzulái azon kifejezés
 által sugallt sorrendben kerülnek alkalmazásra,amelyben irva 
 vannak - maga a SELECT klauzula kivételével, melynek az alkal-
 mazása utoljára történik. Ezért a példában úgy képzelhetjük 
 el, hogy az eredmény felépitése a következöképpen történik. 
 1. FROM: A FROM klauzula kiértékelése olyan új táblát ad ,a-
 mely a P és SP táblák "Descartes szorzata" .Megjegyzés: A
 T1, T2,... (ebben a sorrendben ) táblák halmazának Descartes 
 szorzata egy tábla, amely az összes lehetséges t sorból áll úgy
 hogy t az összeláncolásaként adódik t1 sornak a T1-töl, t2 
 sornak a T2-töl, stb. 
 2. WHERE: Az 1. lépés eredményét csökkenti az összes olyan sor
 kihagyása , amely nem elégiti ki a WHERE klauzulát.A példában 
 azok a sorok ,melyek nem elégitik ki a következö feltételt, 
  P.PNO = SP.PNO AND
   ( P.COLOR = 'Red' OR P.COLOR = 'Blue' ) AND 
  SP.QTY > 200   
 kimaradnak. 
  sql.doc Page: 84  
 3. GROUP BY: A 2. lépés eredményét a GROUP BY klauzulában meg-
 nevezett oszlop(ok) értékei szerint csoportositja. A példában
 ezek az oszlopok a P.PNO , a P.WEIGHT, és a P.COLOR. 
 4. HAVING: Azok a csoportok, amelyek nem elégitik ki az aláb-
 bi feltételt 
  SUM ( SP.QTY ) > 350 
 kimaradnak a 3. lépés eredményéböl. 
 5. SELECT: A 4. lépés eredményében lévö minden csoport egyet-
 len eredmény sort hoz létre a következöképpen. Elöször az al-
 katrész szám, súly,szin és maximális mennyiség eltávolitása 
 történik a csoportból. Másodszor a súly átalakitódik grammra.
 Harmadszor a két literál karakterfüzér "Weight in grams ="
 (súly grammban) és "Max sipped quantity = "(maximális le-
 szállitott mennyiség) behelyezödik a sorba a megfelelö he-
 lyeken. 
  Megjegyzés: Egy pillanatra menjünk vissza a GROUP BY klau-
  zulához: Elméletben P.PNO-nak egyedül elegendönek kellene
  lennie , mint a csoportositó oszlopnak ,ebben a példában,
  mivel P.WEIGHT és P.COLOR maguk is egyértéküek alkatrész
  számonként. Azonban az SQL-nek nincs tudomása erröl az     
  utobbi tényröl és hibaállapotot fog életbeléptetni, ha
  P.WEIGHT és P.COLOR kimarad a GROUP BY klauzulából, mivel
  ezek megvannak emlitve a SELECT klauzulában.Az alap prob-
  léma itt az , hogy az SQL nem támogatja az elsödleges kul-
  csokat .Lásd a 11. fejezet .Megjegyzés vége. 
 9.6 KERESÉSI FELTÉTELEK 
 ----- ----- ------------- 
 A WHERE és HAVING klauzulákban keresési feltételeket haszná-
 lunk az ezt követö feldolgozáshoz meghatározott sorok ( vagy
 sorok csoportjai , HAVING esetében ) minösitésére vagy ki-
 zárására .Adott sor (vagy csoport) esetén adott keresési
 feltétel kiértékelése igaz , hamis vagy ismeretlen eredményt
 ad. A minösitett sorok (vagy csoportok) pontosan azok ,amelyekhez
 a feltétel kiértékelése igaz értéket ad. 
 Egy keresési feltétel szintaxisa a következö : 
  search-condition
  ::= boolean-term
  : search-condition OR boolean-term 
  boolean-term
  ::= boolean-factor 
  : boolean-term AND boolean-factor 
  sql.doc Page: 85  
  boolean-factor
  ::= [ NOT ] boolean-primary  
  boolean-primary
  ::= predicate : ( search-condition )  
 Igy egy keresési feltétel alapvetöen olyan predikátumok gyüj-
 teménye (együttese) , melyeket az AND , OR és NOT logikai ope-
 rátorok és a kiértékelés kivánt sorrendjének jelzésére záró-
 jelek használatával kombináltak egymással. A predikárum vi-
 szont a következök valamelyike: 
 - összehasonlitás predikátum
 - BETWEEN predikátum
 - LIKE predikátum
 - null teszt
 - IN predikátum
 - minden vagy valami predikátum
 - létezés teszt 
 (nem mindegyik hivatalos szabványos kifejezés). A fenti elsö
 öt kategóriára nem kvantoros predikátumokként, a többi kettö-
 re kvantoros predikátumokként hivatkozunk( ezek ismét nem hi-
 vatalos kifejezések). A 9.7 alfejezet foglalkozik a nem kvan-
 toros predikátumokkal és a 9.8 és 9.9 alfejezetek foglalkoznak
 a kvantoros predikátumokkal. 
 9.7 NEM KVANTOROS PREDIKATUMOK
 ----- ----- --------- ----- ------ 
 Összehasonlitás predikátumok 
 Az összehasonlitás predikátumok két különbözö formátumban je-
 lennek meg: Az elsö: 
  scalar-expression comparison scalar-expression 
 ahol "comparison" (összehasonlitás) az = , <>(nem egyenlö),>
 <,<= vagy >= skalár összehasonlitó operátorok valamelyike.
 Ha az összehasonlitó predikátum egy WHERE klauzulában 
 jelenik meg ,akkor a skalár kifejezéseknek nem szabad
 tartalmazniuk semmilyen fuggvény hivatkozást.  
 A második formátum :  
  scalar-expression comparison subquery 
 Ahol egy "subquery" (al-lekérdezés) lényegében egyszerüen egy
 zárójelek közé elhelyezett lekérdezés megadás (lásd a 9.2 fe-
 jezetet) azzal a kivétellel, hogy a lekérdezés megadásnak mind-
 össze egyetlen oszlopos /*/ táblát kell reprezentálnia és ugyan-
 akkor - ebben a speciális kontextusban - legfeljebb egy soros
  sql.doc Page: 86 
 táblát kell reprezentálnia. 
 ------
 * Kivéve EXIST kontextusában (lásd a 9.9 alfejezetet).  
 Az alábbiakban megadunk egy példát ennek az összehasonlitás 
 predikátum formátumnak a használatára: 
  SELECT S.SNO
  FROM S
  WHERE S.CITY =
  ( SELECT S.CITY
  FROM S
  WHERE S.SNO = 'S1' ) 
 ("Azokhoz a szállitókhoz tartozó szállitó számok, melyek ugyan-
 abban a városban vannak , mint az S1 szállitó"). Egy összeha-
 sonlitás predikátumban egy al-lekérdezésnek (mint ahogy már 
 jeleztük) csak egyetlen skalár értékét szabad visszaadnia.
 Ha ehelyett egyáltalán nem ad vissza értéket , a predikátum ki-
 értékelés ismeretlen eredményt ad; ha több értéket ad vissza,
 hiba keletkezik. 
  Megjegyzés: számos további korlátozás van egy összeha-
  sonlitás predikátumon belül az al-lekérdezések haszná-
  latára:
  1. az összehasonlitás predikátumot a bemutatott módon kell
  irni úgy ,hogy az al-lekérdezés az összehasonlitó operátor
  után jelenjen meg , ne pedig az elött. Például a következö
  ***ILLEGAL*** ( NINCS MEGENGEDVE ):  
  SELECT S.SNO
  FROM S
  WHERE ( SELECT S.CITY
  FROM S
  WHERE S.SNO = 'S1' ) = S.CITY 
  2. Nincs lehetöség két al-lekérdezés összehasonlitására.
  3. Jólehet, az al-lekérdezések általában tartalmazhatnak
  GROUP BY és HAVING klauzulákat, ezek a klauzulák nincsenek
  megengedve ebben a kontexusban.   
  4. A FROM klauzulának az al-lekérdezésben nem szabad 
  csoportositott nézetre hivatkoznia. 
  Jegyezze meg azt is ,hogy az "al-lekérdezés" (subquery)
  nem szerencsés kifejezés ,mivel az eredmény táblának egyet-
  len oszlopának kell lennie (EXIST kontexus kivételével -
  lásd a 9.9 alfejezetet) ugyanakkor egy általános lekérde-
  zés több oszlopos táblázatot ad vissza." column expression"
  (oszlop kifejezés) jobb kifejezés lehetne. Megjegyzés vége. 
  sql.doc Page: 87  
 BETWEEN Predikátumok 
 EGY BETWEEN predikátum szintaxisa: 
  scalar-expression [NOT] BETWEEN scalar-expression
  AND scalar-expression 
 A BETWEEN predikátum 
  y BETWEEN x AND z 
 a definició szerint szemantikailag egyenértékü az alábbival: 
  x <= y AND y <= z 
 Az alábbi BETWEEN predikátor 
  y NOT BETWEEN x AND z 
 a definició szerint szemantikailag egyenértékü a következö-
 vel: 
  NOT(y BETWEEN x AND z) 
 Példa: 
  SELECT P.PNO
  FROM P
  WHERE P.WEIGHT BETWEEN 16 AND 19 
 LIKE predikátumok 
 A LIKE predikátumot minta illesztéshez szánták- vagyis egy
 adott karakterfüzér tesztelésére ; annak megállapitására,hogy
 összhangban van-e valamilyen elöirt mintával (mely atomkémt 
 van megadva, nem pedig általános skalár kifejezésként). A szin-
 taxis: 
  column-reference [NOT] LIKE atom [ESCAPE atom] 
 A "column reference"-nek ( oszlop referenciának) karakterfüzér
 tipusú oszlopot kell azonositania. Megadunk erre egy példát: 
  SELECT P.PNO, P.PNAME
  FROM P
  WHERE P.PNAME LIKE 'C%' 
 (azoknak az alkatrészeknek az alkatrész számai és nevei ,ame-
 lyek nevei C betüvel kezdödnek") 
 Eredmény: --- -----
  PNO PNAME
  --- -----
  P5 Cam
  sql.doc Page: 88 
  P6 Cog 
  A LIKE-t követö atomnak egy karakterfüzért kell reprezentál-
 nia. Feltéve, hogy nincs megadva ESCAPE klauzula, ezen ka-
 rakterfüzéren belüli karakterek értelmezése a következöképpen
 történik. 
 - Az aláhúzás karakter (_)jelentése: valamilyen egyedülálló
  karakter.
 - A százalék karakter (%) jelentése: valamilyen n karakter-
  böl álló sorozat (ahol n lehet nulla).
 - Minden más karakter önmagát jelenti. 
  Ezért a példában a SELECT-kifejezés (expression ) a P táblá-
 ból azokat a sorokat fogja visszaadni, melyeknél a PNAME érték
 P nagybetüvel kezdödik és melyek nulla vagy több karakter bár-
 milyen sorozatát tartalmazzák ezen C-t követöen.Megadunk erre 
 néhány további példát: 
  ADRESS LIKE '%BERKELEY%' - A kiértékelése igaz értéket fog
  adni, ha az ADRESS belsejében
  barhol megjelenik a "Berkeley"
  karakterfüzér.    
  SNO LIKE 'S__' - A kiértékelése igaz értéket fog
  adni, ha SNO pontosan három ka-
  rakter hosszú és az elsö karak-
  ter "S".
  PNAME LIKE '%C__' - A kiértékelése igaz értéket fog
  adni, ha PNAME négy karakter
  vagy ennél több karakter
   hosszúságú és a harmadik karakter
  "C".
  STRING LIKE '\__%' - A kiértékelése igaz eredményt fog
  adni ,ha a STRING egy aláhúzás 
  ESCAPE '\' karakterrel kezdödik (lásd lej-
  jebb) 
  Ebben a utolsó példában az "\" forditott ferde törtvonal
 karakter escape karakterként volt megadva, ami azt jelenti,
 hogy az "_"és "%" karakterek számára megadott speciális ér-
 telmezés letiltható, ha ezt kivánják,úgy , hogy el kell helyez-
 ni az ilyen karakterek elé egy forditott ferde törtvonal ka-
 raktert. Egy ESCAPE klauzulában az atomnak egyetlen karaktert
 kell reprezentálnia. 
  Végül , a LIKE predikátum  
  x NOT LIKE y [ESCAPE z] 
 a definició szerint szemantikailag egyenértékü a következövel: 
  sql.doc Page: 89 
  NOT (x like y [ESCAPE z] )
 Null tesztjei 
 Emlékezzünk vissza a 3.fejezetböl arra ,hogy legalábbis a 
 WHERE és HAVING céljaira, semmit sem tekintünk úgy ,hogy
 null-al egyenlö - még magát a null-t sem. Ehhez hasonlúan,
 semmit sem tekintünk úgy, hogy null-nál kisebb vagy null-nál
 nagyobb, vagy...,stb. Más szavakkal megfogalmazva,amikor egy
 null összehasonlitódik valamilyen értékkel, egy összehason-
 litás predikátum kiértékelésében, akkor az eredmény sohasem    
 igaz (még akkor is igy van, ha ez a másik érték szintén null)
 ;hanem ehelyett az eredmény minden esetben az ismeretlen igaz-
 ság érték. A három igazság érték közötti kölcsonhatást a kö-
 vetkezö igazság táblázatok definiálják (a 3. fejezetböl meg-
 ismételve): 
  NOT: AND :T :? :F OR :T :? :F 
  ....:.... .....:..:..:.. ....:.....:.. 
  T : F T :T :? :F T :T :T :T
  ? : ? ? :? :? :F ? :T :? :?
  F : T F :F :F :F F :T :? :F 
 A következö alakú speciális predikátum:
  column-reference IS NULL
 van biztositva null-ok jelenlétének teszteléséhez. Például: 
  SELECT S.SNO
  FROM S
  WHERE S.STATUS IS NULL 
  Megjegyezzük , hogy az "S.STATUS = NULL" szintaxis nem meg-
 engedett,mivel (mint ahogyan már elmagyaráztuk) semmi sem ,
 még maga a null sem ,tekinthetö úgy ,hogy egyenlö legyen a 
 null-lal, a WHERE vagy HAVING céljaihoz. 
  Az alabbi predikátum  
  x IS NOT NULL 
 definició szerint szemantikailag ekvivalens a következövel. 
  NOT ( x IS NULL )  
 IN PREDIKATUMOK 
 Az összehasonlitás predikatumokhoz hasonlóan az IN predikátu-
 mok is két különbözö formátumban jelennek meg . Az elsö való-
 jában egyszerüen a röviditése az összehasonlitó predikátumok
 valamilyen kombinációjának. 
  sql.doc Page: 90 
  scalar-expression [NOT] IN (atom-commalist ) 
 A commalist-nek legalább két atomot kell tartalmaznia.mega-
 dunk egy példát egy ilyen predikátum használatára (elsö for-
 mátum) : 
  SELECT P.PNO
  FROM P
  WHERE P.WEIGHT IN (12,16,17) 
 Az alábbi IN predikátum  
  x IN ( a,b ...,z ) 
 a definiciú szerint ekvivalens a következövel: 
  x = a OR x = b OR ...OR x = z 
 Az IN predikátum második formátuma : 
  scalar-expression [NOT] IN subquery 
  Ez a formátum (a NOT nélkül) úgy van definiálva, hogy sze-
 mantikailag azonos az alábbival: 
  scalar-expression = ANY subquery  
 (lásd a 9.8 alfejezetet). Azonban ,az IN esetleg intuitiv mó-
 don könnyebben érthetö, mint = ANY. Megadunk egy példát IN hasz-
 nálatára al-lekérdezéssel: 
  SELECT S.SNAME
  FROM S 
  WHERE S.SNO IN 
  ( SELECT SP.SNO
  FROM SP
  WHERE SP.PNO = 'P2' 
 ("Azoknak a szállitóknak a nevei, akik P2 alkatrészt szállita-
 nak").Ennek a formátumnak további tárgyalását lásd a következö
 alfejezetben. 
  Végül , az alábbi IN predikátum
  x NOT IN rhs 
 ("ahol "rhs" vagy atomok zárójelek közé tett commalist-je, vagy
 egy al-lekérdezés") a definició szerint szemantikailag egyenér-
 tékü a következövel:
  NOT (x IN rhs )      
  sql.doc Page: 91  
 9.8 AL-LEKÉRDEZÉSEK
 ----- ----- --------- 
 Az al-lekérdezés szintaxisa : 
  (SELECT [ALL : DISTINCT ] selection table-expression ) 
 ahol a"table-expression"-nak (tábla kifejezésnek ) egy
 oszlopos táblát kell reprezentálnia (kivéve EXISTS kontexusá-
 ban- lásd a 9.9 alfejezetet ). Egy al-lekérdezés szemantikája
 azonos a lekérdezés specifikáció szemantikájával (lásd a 
 9.2 alfejezetet) az egy-oszlop korlátozás kivételével jegyez-
 ze meg, hogy a határoló zárójelek az al-lekérdezések szintaxisa
 részének tekintendök.Al-lekérdezéseket használunk: 
 - Összehasonlitás predikátumokban( lásd a 9.7 alfejezetet)
 - IN predikátumokban( lásd a 9.7 alfejezetet )
 - Minden vagy valami predikátumokban (lásd a 9.9 alfejezetet)
 - létezés tesztekben (lásd a 9.9 alfejezetet ) 
  Al-lekérdezéssel az IN használatára egy egyszerü példa a
 9.7 alfejezet végén szerepelt .Most megadunk egy bonyolultabb
 példát , amely egy al-lekérdezésnek egy másikba ágyazását mu-
 tatja be. 
 1.Példa: Keressük meg azon szállitóknak a szállitó neveit, a-
 kik legalább egy vörös alkatrészt szállitanak. 
  SELECT S.SNAME
  FROM S
  WHERE S.SNO IN
  ( SELECT SP.SNO
  FROM SP
  WHERE SP.PNO IN
  ( SELECT P.PNO
  FROM P
   WHERE P.COLOR = 'Red' ) )  
  Az érdekesség miatt , megadjuk ezt a példát úgy , hogy ki-
 hagyjuk az összes explicit tábla név minösitöt : 
  SELECT SNAME
  FROM S
  WHERE SNO IN
  ( SELECT SNO
  FROM SP
  WHERE PNO IN
  ( SELECT PNO
  FROM P
  WHERE COLOR = 'Red' ) )  
  Ebben a "megfogalmazásban" minden nem minösitett oszlopne-
 vet implicit módon minösit egy táblanév (vagy tartomány válto-
 zó név) a "legközelebbi" alkalmazható FROM klauzulából. (Az
  sql.doc Page: 92 
 implicit minösitök meghatározási módjának további részletei
 megismerésére az olvasónak a hivatalos szabványos dokumentá-
 ciót kell átnéznie. A gyakorlatban explicit minösitést javaso-
 lunk , ha esetleg bármilyen kétely felmerülne). 
 2. példa : Keressük meg azoknak a szállitóknak a szállitó neveit ,
 akik P2 alkatrészt szállitanak. 
  SELECT S.SNAME
  FROM S
  WHERE 'P2' IN
  ( SELECT SP.PNO
  FROM SP
  WHERE SP.SNO = S.SNO ) 
 Ez a példa abban tér el az elözö példáktól , hogy a belsö al-le-
 kérdezés nem értékelhetö ki egyszer , s mindenkorra a külsö le-
 kérdezés kiértékelése elött , mivel ez a belsö al-lekérdezés
 függ egy változótól , nevezetesen az S.SNO-tól , melynek az ér-
 téke változik , amint a rendszzer az S tábla különbözö sorait 
 vizsgálja. Konceptuálisan ezért a kiértékelés a következökép-
 pen megy végbe : 
 (a) A rendszer megvizsgálja az S tábla elsö sorát ; feltételez-
  zük , hogy ez az S1-hez tartozó sor. Az S.SNO változónak
  igy a jelenlegi értéke S1 , ezért a rendszer kiértékeli a
  belsö al-lekérdezést  
  ( SELECT SP.PNO
  FROM SP
  WHERE SP.SNO = 'S1' ) 
  azért , hogy megkapja a (P1,P2,P3,P4,P5,P6) halmazt. Most
  befejezheti az S1-hez feldolgozását; ki fogja választani
  az SNAME értéket S1-hez , nevezetesen Smith-et , akkor , és
  csakis akkor , ha P2 van a halmazban (természetesen ez igy
  van). 
 (b) Ezután a rendszer továbbhalad , megismétli az ilyen fajta
  feldolgozást a következö szállitóhoz és igy tovább , mind-
  addig , amig az S tábla minden sorával már foglalkozott. 
  Egy olyan al-lekérdezést , mint például az ebben a példában
 lévö , korrelált al-lekérdezésnek nevezzük. A korrelált al-le-
 kérdezés olyan al-lekérdezés , melynek az értéke valamely olyan
 változótól függ , amely az értékét valamilyen külsö lekérdezés-
 ben kapja meg; az ilyen al-lekérdezés tehát ismétlödöen kiérté-
 kelendö (a kérdéses változó minden értékéhez egyszer) , ahelyett
 hogy a kiértékelés egyszer , s mindenkorra megtörténjen. Meg-
 jegyzés : Egy korrelált al-lekérdezésre másik példát már meg-
 adtunk a 9.4 alfejezetben (6. példa). 
 3.példa : Keressük meg azoknak a szállitóknak a szállitó szá-
 mait , akik legalább egy olyan alkatrészt szállitanak , mint
 amelyet az S2 szállitó szállit.
  sql.doc Page: 93  
  SELECT DISTINCT SPX.SNO
  FROM SP SPX
  WHERE SPX.PNO IN
  ( SELECT SPY.PNO
  FROM SP.SPY
  WHERE SPY.SNO = 'S2' ) 
 Ez a példa két külön hivatkozást tartalmaz az SP táblára ,
 azért a kettö közül legalább az egyiknek explicit tartomány-
 változó név segitségével történö hivatkozásban kell lennie
 (lásd a 9.5 alfejezetben , a 7. példában a tartományváltozók
 leirását ). A szabatos megfogalmazás érdekében , explicit tar-
 tományváltozókat (SPX és SPY ) használtunk mindkét hivatkozás-
 hoz. 
 9.9. KVANTOROS PREDIKATOROK  
 Minden vagy valami predikátumok 
 A minden vagy valami predikátumnak a következö az általános for-
 mátuma  
  scalar-expression quantified-comparison subquery 
 ahol egy "quantified comparison" (kvantoros összehasonlitás)
 az =,<>,<,>,<=,>=, normál skalár összehasonlitók bármelyike,
 de csak egy , melyet az ALL vagy ANY (vagy SOME; a SOME tulajdon-
 képpen ugyanaz , mint az ANY , de másképpen kifejezve) kulcs-
 szavak közül egyet követ. Minden vagy valami ALL-or-ANY) pre-
 dikátum kiértékelése igaz értéket ad , ha a megfelelö össze-
 hasonlitás predikátum , az ALL,(illetve ANY) nélkül, 
  scalar-expression comparasion scalar-value 
 kiértékelése igaz értéket ad az azon oszlopban lévö skalár ér-
 tékek mindegyikéhez (illetve valamelyikéhez), melyet az al-le-
 kérdezés reprezentál. Megadunk erre egy példát : 
  SELECT DISTINCT SP.SNO
  FROM SP
  WHERE SP.QTY > ALL
  ( SELECT SP.QTY
  FROM SP
  WHERE SP.SNO = 'S1' )
 ("azoknak a szállitóknak a szállitó számai , akik legalább
 egy alkatrészt nagyobb mennyiségben szállitanak , mint minden
 olyan mennyiség , melyben az S1 szállitó alkatrészt szállit") 
  Megjegyzés : A minden vagy valami predikátum hibára hajla-
  mos (érzékeny). Az itt tárgyalt lekérdezésnek egy nagyon 
  természetesen angol-nyelvü megfogalmazása az "any" (vala- 
  mi) szót használná "every" (minden) helyett , ami könnyen
  a "hibás" > ANY kvantoros összehasonlitás használatára ve-
  zethet > ALL helyett. Ezen kivül a minden vagy valami pre-
  sql.doc  Page: 94 
  dikátumok teljesen szükségtelenek , mivel létezés tesztek
  formájában mindenképpen mindig átfogalmazhatók (lásd az
  alábbi definiciókat).  
  Jelölje a "$" szimbólum az =,<> , stb. skalár összehason-
 litás operátorok valamelyikét , de csak egyet. Ekkor a minden
 vagy valami predikátum 
  x $ANY ( SELECT y FROM T WHERE p ) 
 úgy van definiálva , hogy szemantikailag egyenértékü az alábbi-
 val  
  EXISTS (SELECT* FROM T WHERE (p) AND x $ T.y ) 
 Ehhez hasonlóan , az alábbi minden vagy valami predikátum  
  x $ALL ( SELECT y FROM T WHERE p ) 
 a definició szerint szemantikailag egyenértékü a következövel 
  NOT EXISTS ( SELECT* FROM T WHERE (p) AND NOT ( x $ T.y ))  
 Létezés tesztek 
 A létezés teszt a következö alakú predikátum 
  EXISTS subquery 
 A predikátum kiértékelése hamis értéket ad , ha az al-lekérdezés
 kiértékelése üres halmazt eredményez , az érték egyébként igaz.
 Megjegyzés : Ebben a speciális kontextusban (csak) az al-lekérde-
 zés számára meg van engedve , hogy "SELECT*"-ot használjon
 "SELECT value-expression " (SELECT érték-kifejezés) helyett , még
 akkor is , ha az eredménynek egynél több oszlopa van. Valóban a 
 "SELECT*" a normál eset. 
 1.Példa : keressük meg azon szállitóknak a szállitó neveit , akik
 legalább egy alkatrészt szállitanak. 
  SELECT S.SNAME
  FROM S
  WHERE EXISTS
  ( SELECT*
  FROM SP
  WHERE SP.SNO = S.SNO ) 
 2.Példa. Keressük meg azoknak a szállitóknak a szállitó neveit ,
 akik egy alkatrészt sem szállitanak. 
  SELECT S.SNAME
  FROM S
  WHERE NOT EXISTS
  ( SELECT*
  FROM SP
  sql.doc Page: 95 
  WHERE SP.SNO = S.SNO ) 
 3.Példa: Keressük meg azoknak a szállitóknak a szállitó neveit ,
 akik minden alkatrészt szállitanak. 
  SELECT S.SNAME
  FROM S
  WHERE NOT EXISTS
  ( SELECT*
  FROM P
  WHERE NOT EXISTS
  ( SELECT*
  FROM SP
  WHERE S.SNO = SP.SNO
  AND SP.PNO = P.PNO ) ) 
 4.Példa: Keressük meg azoknak a szállitóknak a szállitó szá-
 mait , akik legalább egy alkatrészt nagyobb mennyiségben szál-
 litanak , mint minden olyan mennyiség , melyben az S1 szálli-
 tó alkatrészt szállit. 
  SELECT DISTINCT SPX.SNO
  FROM SFX
  WHERE NOT EXISTS
  ( SELECT*
  FROM SP SPY
  WHERE SPY.SNO = 'S1'
  AND SPY.QTY >= SPX.QTY ) 
 Hasonlitsa össze ezt a feladatnak a korábban látható
 ">ANY" megoldásával.                         
  sql.doc Page: 96  
  10
 -------- ----- ------ ----- ----- ----------------  
 Beágyazott SQL 
 10.1 BEVEZETÉS  
 Mint ahogy a 3.2 alfejezetben elmagyaráztuk , az X3H2 dokumen-
 táció "mellékletek" vagy függelékek egész sorát tartalmazza ,
 melyek az SQL-nek egy "beágyazott" verzióját definiálják , -va-
 gyis az SQL-nek egy olyan verzióját , melyet arra terveztek ,
 hogy közvetlenül beépithetö legyen host programokba (vagyis
 azokba a host programokba , amelyek COBOL , FORTRAN , Pascal és
 PL/I nyelven vannak irva). Jóllehet , természetesen nem része
 a hivatalos szabványnak , a beágyazott SQL mégis sokféle módon
 a teljes javaslat legközvetlenebbül látható aspektusát repre-
 zentálja. Ebben a fejezetben részletesen megvizsgáljuk a beá-
 gyazott SQL-t. A világos megfogalmazás érdekében , a leirásun-
 kat PL/I-re alapozzuk , de természetesen az elgondolásoknak a
 nagy része más host nyelvekre is leforditható (le van fordit-
 va), úgy , hogy csak kismértékü változtatások szükségesek. A
 10.2 alfejezet egy komplett beágyazott SQL - PL/I programot ad
 meg; a 10.3 alfejezet ezen példa által bemutatott részletes
 nyelvi szempontokat tárgyalja. 
 10.2 EGY TELJES PÉLDA  
 Beágyazott SQL utasitásokkal rendelkezö host nyelvü program -
 "beágyazott SQL host program" egy egyébként standard host
 programból , plusz egy "beágyazott SQL deklaráció részböl",
 beágyazott cursor definició készletéböl , beágyazott kivételes
 állapot deklarációk készletéböl és egy beágyazott SQL utasi-
 tás készletböl áll. A 10.1. ábrában bemutatjuk a 6. fejezet-
 böl (6.1. ábra) vett példának egy beágyazott SQL verzióját.
 A következö fejezet részletes magyrázatait (nagyrészt) ennek
 a példának a segitségével adjuk meg. 
 10.1. ábra. Beágyazott SQL-re példa
 (A program megjegyzések csak magyar nyelven láthatók , a for-
 ditó megjegyzése)   
 SQLEX: PROC OPTIONS (MAIN) ;
  EXEC SQL BEGIN DECLARE SECTION ;
  /* program input */
  DCL GIVENPNO CHAR(6) ;
  DCL GIVENCIT CHAR(15) ;
  DCL GIVENINC DECIMAL(3) ;
  DCL GIVENLVL DECIMAL(3) ;  
  /* célok a "FETCH SUPPLIER"-hez */ 
  DCL SNO CHAR(5) ;
  DCL SNAME  CHAR(20) ;
  sql.doc Page: 97 
  DCL STATUS DECIMAL(3) ;
  DCL CITY CHAR(15) ; 
  /* SQL visszatérési kód változó */
  DCL SQLCODE FIXED BINARY(15) ;
   EXEC SQL END DECLARE SECTION ;
  /* housekeeping változók */
  DCL DISP CHAR(7) ;
  DCL MORE_SUPPLIERS BIT(1) ;
  /* kivételes állapot deklarációk */
  EXEC SQL WHENEVER NOT FOUND CONTIUNE ;
  EXEC SQL WHENEVER SQLERROR CONTIUNE ;
  /* adatbázis kivételes állapot kezelö */
  ON CONDITION ( DBEXCEPTION )
  BEGIN ;
  PUT SKIP LIST ( SQLCODE ) ;
  EXEC SQL ROLLBACK WORK ;
  PUT SKIP LIST ( SQLCODE ) ;
  GO TO QUIT ;
  END ;
  /* cursor definició */
  EXEC SQL DECLARE Z CURSOR FOR
  SELECT S.SNO, S.SNAME, S.STATUS, S.CITY
  FROM S
  WHERE S.SNO IN
  ( SELECT SP.SNO
  FROM SP
  WHERE SP.PNO = :GIVENPNO ) ;
  /* fö program logika */
  GET LIST ( GIVENPNO, GIVENCIT, GIVENINC, GIVENLVL ) ;
  EXEC SQL OPEN Z ;
  IF NOT ( SQLCODE = 0 )
  THEN SIGNAL CONDITION (DBEXCEPTION ) ;
  MORE_SUPPLIERS = '1'B ;
  DO WHILE ( MORE_SUPPLIERS ) ;
  EXEC SQL FETCH Z INTO :SNO, :SNAME, :STATUS, :CITY ;
  SELECT ; /* a PL/I SELECT, nem egy SQL SELECT */
  WHEN ( SQLCODE = 100 )
  MORE_SUPPLIERS = '0'B ;
  WHEN NOT (SQLCODE =100 | SQLCODE = 0 )
  SIGNAL CONDITION ( DBEXCEPTION ) ;
  WHEN ( SQLCODE = 0 )
  DO ;
  DISP = 'bbbbbbb' ;
  IF CITY = GIVENCIT
  THEN
  DO ;
  EXEC SQL UPDATE S
  SET STATUS = S.STATUS + :GIVENINC
  WHERE S.SNO ;
  IF NOT ( SQLCODE = 0 )
  THEN SIGNAL CONDITION ( DBEXCEPTION ) ;
  DISP = 'UPDATED' ;
  END ;
  ELSE
  sql.doc Page: 98 
  IF STATUS< GIVENLVL
  THEN
  DO ;
  EXEC SQL DELETE
   FROM SP
  WHERE SP.SNO = :SNO ;
  IF NOT ( SQLCODE = 0 | SQLCODE = 100 )
  THEN SIGNAL CONDITION ( DBEXCEPTION ) ;
  EXEC SQL DELETE
  FROM S
  WHERE S.SNO = :SNO ; 
  IF NOT ( SQLCODE = 0 )
  THEN SIGNAL CONDITION ( DBEXCEPTION ) ;
  DISP = 'DELETED' ;
  END ;
  PUT SKIP LIST ;
  ( SNO, SNAME, STATUS, CITY, DISP ) ;
  END ; /* WHEN ( SQLCODE = 0 ) ... */
  END ; /* PL/I SELECT */
  END ; /* DO WHILE */
   EXEC SQL CLOSE Z ;
  EXEC SQL COMMIT WORK ;
  QUIT: RETURN ;
  END ; /* SQLEX */ 
 10.3 FELMERüLö SZEMPONTOK 
 1. A beágyazott SQL utasitásokat EXEC SQL elötag elözi meg
 (úgy, hogy ezek könnyen megkülönböztethetök legyenek a host 
 nyelv utasitásaitól) és a következöképpen fejezödnek be (zá-
 ródnak le): 
  COBOL -END-EXEC
  FORTRAN -folytatás karakter hiánya (vagyis nincs expli-
  cit terminátor)
  PASCAL -pontosvesszö
  PL/I -pontosvesszö 
 2. Végrehajtható SQL utasitás mindenhol megjelenhet, ahol
 végrehajtható host utasitás megjelenhet. Megjegyezzük, hogy
 az "Executable" (végrehajtható) minösitö, itt: DECLARE CURSOR,
 nem végrehajtható utasitás, ugyanez érvényes a WHENEVER-re
 (lásd késöbb), valamint a BEGIN-re és END DECLARE SECTION-ra
 is. 
 3. Az SQL utasitások tartalmazhatnak hivatkozásokat host válto-
 zókra. Az ilyen hivatkozások elé kettöspontot kell elhelyezni
 azért, hogy megkülönböztethetök legyenek az SQL oszlop nevek-
 töl. Nem szabad minösitetteknek vagy index-szel ellátva lenniük
 és skalárokat, nem pedig tömböket vagy struktúrákat kell azo-
 nositaniuk. Megjelenhetnek SQL adatmanipuláló utasitásokban
 ugyanazokon a helyeken, mint ahol paraméterek jelenhetnek meg a
 manipulativ utasitásokban a modul nyelvben (lásd az 5.2 alfeje-
 zetet). 
  sql.doc Page: 99  
 4. Minden host változónak, melyre SQL utasitásokban hivatko-
 zás fog történni, definiáltnak kell lennie a "beágyazott SQL
 deklarálási részen" belül, melyet a BEGIN és END DECLARE SEC-
 TION utasitások határolnak (lásd a 10.1 ábrát). Az ilyen host
 változó definiciók szándékosan bizonyos egyszerü formátumokra
 vannak korlátozva (például tömbök és struktúrák nincsenek meg-
 engedve), az olvasónak a szabvány dokumentációjában kell meg-
 néznie a részleteket. Host változónak nem szabad megjelennie 
 beágyazott SQL utasitásban, mielött ennek a definiálása meg-
 történt volna. 
 5. Minden beágyazott SQL programnak tartalmaznia kell SQLCODE
 (FORTRAN-ban SQLCODE) nevü host változót. Miután valamilyen SQL
 utasitás végrehajtása megtörtént, a programnak egy numerikus
 állapot jelzö adódik vissza az SQLCODE-ban. Lásd az 5.2 alfe-
 jezetben az SQLCODE értékek részleteit. 
 6. A host változóknak olyan adattipussal kell rendelkezniük,
 mely kompatibilis azoknak az oszlopoknak az SQL adattipusával,
 amelyekkel a változókat össze kell hasonlitani, vagy amelyek-
 hez vagy amelyekböl a host változókat meg kell adni. Az adatti-
 pus kompatibilitás az 5.2 alfejezetben van definiálva. 
 7.  A host változóknak és SQL oszlopoknak azonos nevük is lehet. 
 8. Minden SQL utasitást elvben a visszaadott SQLCODE érték
 tesztjének kell követnie. A WHENEVER utasitás azért van megad-
 va, hogy egyszerüsitse ezt a folyamatot. A WHENEVER utasitás-
 nak a szintaxisa az alábbi: 
  EXEC SQL WHENEVER condition action terminator 
 ahol "terminator" (terminátor) a fenti 1. szakaszban elmagya-
 rázott terminátor, "condition" (feltétel) vagy SQLERROR vagy
 NOT FOUND és "action" (tevékenység) vagy CONTINUE vagy egy GO
 TO utasitás. A WHENEVER nem végrehajtható utasitás; hanem egy
 direktiva az SQL nyelv processzorhoz. "WHENEVER" feltétel GO
 TO Cimke" (WHENEVER condition GO TO label) eredményeként ez
 a processzor beszúr egy "IF feltétel GO TO cimke" (IF con-
 dition GO TO label" utasitást minden végrehajtható SQL utasi-
 tás után, amelyet megtalál. "WHENEVER feltétel CONTINUE" (WHE-
 NEVER condition CONTINUE) eredményeként nem szúr be semmilyen
 ilyen utasitást, ennek hallgatólagosan az a jelentése, hogy a
 programozó fog beszúrni kézzel ilyen utasitásokat. A két "fel-
 tétel" a következöképpen van definiálva: 
  NOT FOUND means SQLCODE = 100
  SQLERROR means SQLCODE < 0  
 Minden WHENEVER utasitás, amelyet az SQL processzor megtalál,
 (egy adott feltétel esetén) a programszöveg szekvenciális le-
 tapogatás során, érvényteleniti az elözöt, amelyet megtalál
 (mely ugyanilyen feltételt tartalmaz).
  A minta programban (10.1 ábra) minden kivételes állapot
  sql.doc  Page: 100 
 tesztelés explicit módon van végrehajtva oktatási okok miatt. 
 9. Indikátor változók olyan módon használhatók (és igy is
 kell használni ezeket), mely pontosan analóg azzal a móddal,
 ahogyan a modul nyelvben az indikátor paramétereket használ-
 ják (lásd az 5.3 alfejezetet). Például: 
  EXEC SQL SELECT P.WEIGHT
  INTO :WEIGHT INDICATOR :WEIGHT_INDIC
  FROM P
  WHERE P.PNO = :PNO ;                                            
  sql.doc Page: 101  
  11
 -------- ----- ------ ----- ----- --------- ----- ------ 
 DEFINICIOS KITERJESZTESEK 
 11.1 BEVEZETÉS 
 Az X3H2 bizottság jelenleg az alap SQL szabványhoz javasolt ki-
 terjesztések sorozatán dolgozik. Ebben a fejezetben és a követ-
 kezöben rövid pillantást vetünk ezekre a javaslatokra. Figyel-
 meztetjük az olvasót arra, hogy ebben a szakaszban ezek még csak
 javaslatok; kétségtelenül számos különbözö módon meg fognak
 változni, mielött elérik a hivatalos szabvány állapotot (ha
 valaha is elérik). Ennek ellenére, érdemesnek látszik, hogy
 eltöltsünk velük egy kis idöt ebben a könyvben, már csak azért
 is, mivel valamennyire jelzik, hogy az X3H2 jelenleg hogyan 
 gondolkodik és ebböl következöen azt jelzik, hogy a nyelv va-
 lószinüleg hogyan fejlödik a közeljövöben. 
  A javaslatok általános területre sorolhatók, adat defini-
 ció kiterjesztések (vagyis kiterjesztések a séma nyelvhez) és
 adatmanipuláló kiterjesztések (vagyis kiterjesztések a modul
 nyelvhez). A jelen fejezet a definiciós kiterjesztésekkel fog-
 lalkozik; a manipulativ kiterjesztéseket a 12. fejezetben tár-
 gyaljuk.  
  Megjegyzés: Az X3H2 kiterjesztéseket javasol az SQL-nek
 két új host nyelvbe, nevezetesen a C-be és az Ada-ba beágya-
 zásához is. A részleteket itt nem tárgyaljuk; természetesen
 nagy általánosságban ezek ugyanazok, mint amit a 10. fejezetben
 tárgyaltunk. 
 11.2 ALAPÉRTÉKEK 
 Egy új (opcionális) "default clause" (alapértelmezés szerinti
 klauzula) adódik egy oszlop definicióhoz a CREATE TABLE-en be-
 lül a következö szintaxissal:  
  DEFAULT ( literal : NULL : USER ) 
  Például : 
  CREATE TABLE S
  ( SNO CHAR(5) NOT NULL ,
  SNAME CHAR(20) DEFAULT '???',
  STATUS DECIMAL(3) NOT NULL DEFAULT 0,
  CITY CHAR(15) DEFAULT ' ',
  UNIQUE ( SNO )) 
  Az alapértelmezés szerinti klauzula célja annak az érték-
 nek a megadása , amelyet a jelzett helyre kell bevinni , ha a
 felhasználó nem ad meg értéket az INSERT-ben. "DEFAULT NULL"
 azt jelenti , hogy null az alapérték.(NOT NULL-t nem szabad
 alkalmazni , ha DEFAULT NULL van megadva); "DEFAULT literal"
  sql.doc Page: 102 
 azt jelenti , hogy a megadott literál az alapérték ; "DEFAULT
 USER" azt jelenti , hogy az USER értéke (lásd a 4.3. alfejezetet)
 az alapérték. 
  Ha nincs explicit alapérték klauzula megadva , akkor :
 (a) Ha NOT NULL érvényes a kérdéses oszlopra , akkor az oszlop-
  nak nincs alapértéke (vagyis , egy értékre szükség van eh-
  hez az oszlophoz az INSERT-ben);
 (b) Ha NOT NULL nem érvényes a kérdéses oszlopra , akkor DEFAULT
  NULL a feltételezés (ennek a felvétele történik).  
  Megjegyzés : A felhasználó definiálta alapértékek ("DEFAULT
  literal") lehetövé teszik , hogy a felhasználó elkerüljön
  néhány olyan nehézséget , amely az SQL tipusu null-okkal 
  van kapcsolatban. 
 11.3 CHECK KÖVETELMÉNYEK  
 A CREATE TABLE utasitás kibövül azért , hogy bármennyi "CHECK
 klauzulát" tartalmazzon. A CHECK klauzula szintaxisa : 
  CHECK (search-condition)  
  A CHECK klauzula célja egy olyan feltétel - vagyis integ-
 ritás követelmény - megadása , amelyet a táblában minden sornak
 ki kell elégitenie (állandóan). Megadunk erre egy példát : 
  CREATE TABLE S 
  ( SNO .... etc.)
  CHECK (S.STATUS BETWEEN 10 AND 100 )
  CHECK (S.CITY IN ( 'Athens','London','Madrid','Oslo',
  'Paris','Rome'))
   CHECK (S.CITY <> 'London' OR S.STATUS = 20 ) 
  Ezek közül a CHECK klauzulák közül az elsö kijelenti , hogy
 az S.STATUS értékeinek elöirt tartományon belül kell lenniük;
 a második kijelenti , hogy az S.CITY értékeit egy elöirt listá-
 ból kell kivenni ; a harmadik azt állitja , hogy ha az S.CITY 
 értéke London , akkor az S.STATUS értékének 20-nak kell lennie.
 Ezen megszigoritások bármelyikének megszegésére irányuló ki-
 sérlet (INSERT vagy UPDATE müveleten keresztül) visszautasitás-
 ra fog kerülni. 
  CHECK klauzulában a keresési feltételnek bizonyos korlá-
 tozott alakunak kell lennie , mely technikailag megszigoritás
 predikátumként ismert. Egy megszigoritás predikátum olyan fel-
 tétel , mely adott sorhoz csak ezen sor elszigetelt vizsgálatá-
 val értékelhetö ki - nincs szükség arra , hogy bármilyen más
 sor, ebböl a táblázatból vagy bármi másból , vizsgálatra
 kerüljön annak meghatározására , hogy a feltétel igaz-e a vizs-
 gált sorhoz. SQL meghatározásokkal ez a követelmény azt jelen-
 ti , hogy a feltételnek nem szabad tartalmaznia semmilyen al-le-
 kérdezést vagy függvényt és az egyetlen tábla , amelyre a felté-
 telben hivatkozás lehet (explicit vagy implicit módon) a kér-
 déses tábla (vagyis az a tábla , amelyik magának a CREATE TABLE 
   sql.doc Page: 103 
 utasitásnak a tárgya). 
  Ha egy CHECK klauzula a táblának csak egyetlen oszlopára
 hivatkozik (mint a fenti elsö két példában), akkor ez opcioná-
 lisan ezen oszlop definiciója részeként adható meg , a tábla
 szinten megadás helyett. Például : 
  CREATE TABLE S
  ( SNO ... ,
  SNAME ... ,
  STATUS ... CHECK (S.STATUS BETWEEN 10 AND 100 ),
  CITY ... CHECK (S.CITY IN ( 'Athens','London',
   'Madrid','Oslo',
  'Paris','Rome') ) )
  CHECK ( S.CITY <> 'London' OR S.STATUS = 20 ) 
 Azonban , jegyezzük meg , hogy a harmadik CHECK klauzulának is
 megadottnak kell lennie tábla szinten , mivel két különbözö 
 oszlopra hivatkozik. 
 11.4 REFERENCIALIS INTEGRITAS  
 Megjegyzés : Ez egy fontos témakör. A referenciális integritás
 fontos része a relációs modellnek , ugyanakkor sajnálatos dolog,
 hogy a legtöbb meglévö relációs termék - nevezetesen a legtöbb
 SQL-en alapuló termék - jelenleg nem támogatja ezt.  
 Elsödleges kulcsok 
 Egy opcionális PRIMARY KEY (elsödleges kulcs) klauzula van
 hozzáadva a CREATE TABLE -hez. Például : 
  CREATE TABLE S
  ( SNO CHAR(5) NOT NULL,
   SNAME CHAR(20) DEFAULT '???',
  STATUS DECIMAL(3) NOT NULL DEFAULT 0,
  CITY CHAR(15) DEFAULT ' ',
  PRIMARY KEY ( SNO ) ) 
 Az alábbi megadás 
  PRIMARY KEY ( column-commalist ) 
 szemantikailag azonos a következö megadással  
  UNIQUE (column-commalist) 
 (lásd a 3.3. alfejezetet) , azzal a kivétellel , hogy :
 (a) Egy adott CREATE TABLE utasitás legfeljebb egy PRIMARY
  KEY klauzulát tartalmazhat (ezen kivül egy vagy több
  UNIQUE klauzulát tartalmazhat , ha a kérdéses táblának egy
  vagy több további egyedi azonositója is van ); és
 (b) Az elsödleges kulcs (vagyis azoknak az oszlopoknak a kom-
  binációja , amelyeket a PRIMARY KEY klauzula azonosit) spe-
  ciális kezelésben részesül minden megfelelö idegen kulcs
  sql.doc Page: 104 
  specifikációban (lásd késöbb a jelen alfejezetben). 
 Emlékezzünk vissza , hogy egy UNIQUE klauzulában (és ebböl kö-
 vetkezik , hogy PRIMARY KEY klauzulában) megemlitett bármilyen
 oszlopnak NOT NULL-ként megadottnak kell lennie. 
  Magyarázat: a PRIMARY KEY klauzulának opcionálisnak kell
  lennie a multtal kompatibilitáshoz , de nagyon javasoljuk ,
  hogy minden CREATE TABLE a gyakorlatban tartalmazzon i-
  lyen klauzulát. A relációs modell szükségessé teszi az
  elsödleges kulcsokat. 
  Megjegyzés : Ha egy elsödleges kulcs egyetlen oszlop , mint
  a fenti példában , akkor ez az oszlop definició részeként
  adható meg külön PRIMARY KEY klauzulán keresztüli megadás
  helyett. Például : 
  CREATE TABLE S
  ( SNO CHAR(5) NOT NULL PRIMARY KEY ,
  SNAME CHAR(20) DEFAULT '???',
  STATUS DECIMAL(3) NOT NULL DEFAULT 0,
  CITY CHAR(15) DEFAULT ' ') 
 Azonban , az ilyen megadás ugy van definiálva , hogy egyszerüen
 a korábban látható verzió röviditése. 
 Idegen kulcsok 
 1. A relációs modellben egy idegen kulcs egy oszlop (vagy
 oszlopok kombinációja) egyetlen T2 táblában , amelynek az
 értékei meg kell , hogy egyezzenek valamilyen T1 táblában
 lévö elsödleges kulcs értékeivel (kissé pontatlanul megfo-
 galmazva).Például, a szállitók és alkatrészek adatbázisban
 az SP tábla SP.SNO oszlopa egy idegen kulcs , mely megegyezik
 az S tábla S.SNO elsödleges kulcsával; minden szállitó szám-
 érték , amely az SP.SNO oszlopban megjelenik , az S.SNO oszlop-
 ban is meg kell , hogy jelenjen (egyébként az adatbázis nem
 lenne konzisztens). Ehhez hasonlóan az SP tábla SP.PNO osz-
 lopa olyan idegen kulcs , ami megegyezik a P tábla P.PNO el-
 södleges kulcsával ; az SP.PNO oszlopban megjelenö minden al-
 katrész szám értéknek meg kell jelennie a P.PNO oszlopban is. /*/ 
 ----- ----- ---------------
 * Megjegyezzük , hogy ezzel ellentétben , létezhet elsödleges kulcs
 érték megegyezö idegen kulcs érték nélkül. Például , ha adva van
 a szokásos szállitók és alkatrészek minta adatok - lásd a 2.1
 ábrát - az 55-ös szállitó jelenleg nem szállit semmilyen alkat-
 részt és ebböl következik , hogy az 55 érték megjelenik az S.SNO
 oszlopban , de nem jelenik meg az SP.SNO oszlopban.  
 2. Egyébként , az "idegen kulcs" (foreign key) fenti nem pon-
 tos definiálásunkban a T1 és T2 jelü két táblának nem kell
 szükségképpen különbözönek lennie. Vagyis egy tábla tartal-
 mazhat olyan idegen kulcsot , melynek értékeire szükség van
  sql.doc Page: 105 
 ugyanazon tábla elsödleges kulcsa értékeivel illesztéshez.
 Erre egy példa az alábbi tábla lehet 
  CHILDOF ( CHILD , MOTHER ) 
 ahol minden egyes MOTHER (ANYA) , ugyanakkor valamilyen más
 MOTHER (ANYA) CHILD (GYERMEKE) is (stb) . Itt CHILD az elsöd-
 leges kulcs és MOTHER egy idegen kulcs , amelyik a CHILD-et
 illeszti , (vagyis adott sorban lévö MOTHER értéknek egyen-
 lönek kell lennie valamilyen más sorban lévö CHILD érték-
 kel. 
  A mostani példa csak egy speciális esete egy általánosabb
 helyzetnek , nevezetesen annak a helyzetnek , amelyben T1 , T2
 T3,...,Tn táblák ciklikusak , ugy , hogy T1 tartalmaz egy i-
 degen kulcsot , mely a T2-re hivatkozik , T2 tartalmaz egy ide-
 gen kulcsot , mely T3-ra hivatkozik ,..., és Tn tartalmaz egy
 idegen kulcsot , mely a T1-re hivatkozik. 
 3. A CHILDOF példa is arra szolgál , hogy további szempontot
 mutasson be - nevezetesen azt , hogy az idegen kulcsok számára
 (az elsödleges kulcsoktól eltéröen) esetenként meg kell enged-
 ni , hogy null-okat elfogadhassanak. A most vizsgált esetben
 feltételezhetöen lesz legalább egy sor a CHILDOF táblában ,
 melyhez a MOTHER ismeretlen. 
 4. Adott idegen kulcs érték az ezt tartalmazó sorból (sorok-
 ból) arra a sorra hivatkozást reprezentál , amelyik az illesz-
 kedö elsödleges kulcs értéket tartalmazza. Ezért annak bizto-
 sitásának problémáját , hogy valójában minden idegen kulcs ér-
 ték illeszkedjen (megegyezzen) a megfelelö elsödleges kulcs
 értékéhez (értékével) a referenciális integritás problémájaként
 ismerjük. A jelenlegi SQL szabványban (és a legtöbb meglévö
 relációs termékben ) a referenciális integritást a felhasználó-
 nak kell fenntartania (vagyis specifikus alkalmazási kóddal).
 Nyilvánvaló , hogy kivánatosabb volna , ha képesek lennénk arra ,
 hogy deklarativ módon referenciális követelményeket adjunk meg
 az adatdefinició részeként és ezeket a rendszerrel tartatnánk
 fenn (öriztetnénk) a felhasználó helyett. Mindig is ez volt
 a relációs modell szándéka és ez a szándéka az alábbiakban
 leirt , javasolt idegen kulcs kiterjesztésnek. 
 5. Egy adott CREATE TABLE utasitás tetszöleges számu FOREIGN
 KEY klauzulát tartalmazhat. Például : 
  CREATE TABLE SP
  ( SNO CHAR(5) NOT NULL,
  PNO CHAR(6) NOT NULL,
  QTY DECIMAL(5) NOT NULL DEFAULT 0 )
  PRIMARY KEY ( SNO , PNO ) )
  FOREIGN KEY ( SNO ) REFERENCES S
  FOREIGN KEY ( PNO ) REFERENCES P 
 A két FOREIGN KEY klauzula közül az elsö kifejezi , hogy
 az SP.SNO oszlop az S tábla elsödleges kulcsával illeszkedö
  sql.doc Page: 106 
 idegen kulcs (jegyezze meg , hogy az S táblának tartalmaznia
 kell egy elsödleges kulcsot ehhez a FOREIGN KEY megadáshoz
 ahhoz , hogy megengedett legyen ). A második FOREIGN KEY klau-
 zula ezzel analóg. 
  1. Megjegyzés : Itt az történik , hogy a két idegen kulcs kö-
  zül mindkettö a "tartalmazó" tábla elsödleges kulcsának
  komponense. Azonban általában bármelyik oszlop vagy osz-
  lopok bármilyen kombinációja idegen kulcs lehet. Például
  az S tábla CITY oszlopa idegen kulcs lehet , ha az adatbá-
  zis tartalmazott városokat reprezentáló másik táblát. 
  2. Megjegyzés : Ha egy idegen kulcs egyetlen oszlop , mint
  a fenti mindkét példában a REFERENCES megadás bevihetö az
  oszlopdefinicióba , ahelyett , hogy külön FOREIGN KEY klau-
  zula részévé kelljen tenni. Például : 
  CREATE TABLE SP
  ( SNO CHAR(5) NOT NULL REFERENCES S,
  PNO CHAR(6) NOT NULL REFERENCES P,
  QTY DECIMAL(5) NOT NULL DEFAULT 0 )
  PRIMARY KEY (SNO, PNO ) ) 
 Azonban , az ilyen megadások egyszerüen csak a korábban látha-
 tó megadások röviditéseként vannak definiálva. 
 7. Legyen T2.FK idegen kulcs és legyen T1.PK az illeszkedö
 (megegyezö) elsödleges kulcs .Az egyszerüség kedvéért felté-
 telezzük , hogy T1.PK egyetlen oszlop , és ebböl következik , hogy
 T2.FK is egyetlen oszlop. /*/ 
 ----- ----- -------------
 * Ezt a feltételezést csupán azért tesszük meg , hogy egyszerüsit-
 sük a bemutatást. Több oszlopos idegen kulcsokra általánositás
 unalmas , fárasztó feladat , de eléggé nyilvánvaló (jóllehet az
 X3H2 ugy tünik , hogy néhány szükségtelen bonyolitást vezet be).
 A részleteket itt kihagyjuk.  
 A T2.FK és T1.PK közötti referenciális követelmény ki van e-
 légitve , akkor és csakis akkor , ha a T2 tábla minden t2 sora
 olyan , hogy vagy t2.FK null (ha nullok meg vannak engedve
 T2.FK-hoz), vagy létezik olyan t1 sor T1-ben , hogy t1.PK
 egyenlö t2.FK-val. 
 8. A T2.FK és T1.PK között referenciális követelmény megör-
 zése érdekében a rendszernek vagy (a) vissza kell utasitania
 minden müveletet , amely ezt megtenné vagy (b) végre kell haj-
 tania valamilyen megfelelö kompenzáló tevékenységet. Azok a 
 müveletek , amelyek potenciálisan megsérthetik a követelményt ,
 az alábbiak : 
 - Egy INSERT a T2 táblában vagy UPDATE a T2.FK oszlopban
  olyan (nem null) értéket vihet be a T2.FK-hoz , amely nem
  létezik T1.PK értékeként.
  sql.doc Page: 107  
 - Egy DELETE a T1 táblán vagy update a T1.PK oszlopon
  "lógó hivatkozásokat" hagyhatna a T2 táblában (vagyis ,
  olyan sorokat a T2 táblában , amelyek nem hivatkoznak sem-
  milyen sorra a T1-ben. 
  Az elsö esetben a müvelet egyszerüen visszautasitódik. A
 második esetben a végrehajtott tevékenység attól a törlési sza-
 bálytól vagy aktualizálasi szabálytól (amelyik alkalmazható)
 függ , amelyet akkor adtak meg , amikor az idegen kulcs definiá-
 lásra került. Altalában minden FOREIGN KEY klauzula tartalmaz
 mind törlési szabályt , mind aktualizálási szabályt : 
  FOREIGN KEY (column ) REFERENCES table 
  [ON DELETE ( RESTRICT : CASCADE : SET NULL : SET DEFAULT )]
  [ON UPDATE ( RESTRICT : CASCADE : SET NULL : SET DEFAULT )] 
  Vizsgáljuk meg elöször a törlési szabályt. RESTRICT (amely
 az alpértelmezés) , azt jelenti , hogy a T1 egyik sorának tör-
 lési kisérlete sikertelen lesz , ha bármilyen megegyezö (illesz-
 kedö ) sor létezik T2-ben . A többi három megadás azt jelenti ,
 hogy a T1 sor törlését megelözi egy kompenzálási tevékenység
 a következöképpen. 
 - CASCADE azt jelenti , hogy a T2-ben lévö megegyezö sorok is
  törlésre kerülnek
 - SET NULL azt jelenti , hogy a T2.FK értékek , a T2-ben a
  megegyezö sorokban , nullára állitódnak (ebben az esetben
  T2.FK-hoz nem szabad NOT NULL-nak megadottnak lennie).
 - SET DEFAULT azt jelenti , hogy T2.FK értékei , T2-ben a
  megegyezö sorokban ,az alkalmazható alapértékre állitód-
  nak (a T2.FK-nak rendelkeznie kell alapértékkel ebben az 
  esetben ; ezen kivül már léteznie kell T1 olyan sorának ,
  amelyik ezt az alapértéket a T1.PK értékeként tartalmazza). 
  Egyébként megjegyezzük , hogy annak a felhasználónak , aki
 az eredeti törlési kérést kiadja , nem kell rendelkeznie expli-
 cit DELETE privilégiummal (vagy UPDATE privilégiummal , az adott
 helyzettöl függöen) a hivatkozási táblázatban azért , hogy a
 fenti kompenzálási tevékenységek végrehajtásra kerüljenek. 
  Az aktualizálási szabály értelmezése analóg : RESTRICT (a-
 mely az alapértelmezés) azt jelenti , hogy az a kisérlet , amely-
 nek során a T1 valamelyik sorában lévö T1.PK értéket aktuali-
 zálni próbálják , sikertelen lesz , ha bármilyen illeszkedö
 (megegyezö) sor létezik T2-ben ; a többi három megadás azt je-
 lenti , hogy T1.PK-ban az aktualizálást megelözi kompenzáló te-
 vékenység a következöképpen : 
 - CASCADE azt jelenti , hogy T2.FK értéke , T2-ben az illesz-
  kedö (megegyezö) sorokban , megfelelö módon aktualizálódik.
 - SET NULL azt jelenti , hogy T2.FK értékei , T2-ben a megfe-
  lelö (illeszkedö) sorokban , null-ra állnak (ebben az eset-
  ben T2.FK-hoz nem szabad NOT NULL-t megadni).
 - SET DEFAULT azt jelenti , hogy T2.FK értékei T2-ben a meg-
  sql.doc Page: 108 
  felelö (illeszkedö) sorokban , az alkalmazható alapértékek-
  re állnak (ebben az esetben T2.FK-nak tartalmaznia kell
  egy alapértéket ; ezen kivül már léteznie kell T1 olyan so-
  rának , amelyik tartalmazza ezt az alapértéket a T1.PK ér-
  tékeként). 
  Ismét elmondjuk , hogy annak a felhasználónak , aki az ere-
 deti aktualizálási kérést kiadja , nem kell explicit UPDATE
 privilégiummal rendelkeznie a hivatkozó táblában azért , hogy
 a fenti kompenzálási tevékenységeket végréhajthassa. 
  Megjegyzések :
  1. Kivánatos lehet "other" (egyéb) opció támogatása az
  ON DELETE és ON UPDATE klauzulákban. A RESTRICT-CASCADES-
  SET NULL - SET DEFAULT opciók nem szükségképpen terjednek
  ki minden lehetöségre.
  2. Az X3H2 javaslat jelenlegi verziója valójában lehetö-
  vé teszi , hogy a hivatkozott táblázatban bármilyen UNIQUE
  oszlopra vagy oszlop kombinációra idegen kulcs hivatkoz-
  hasson , nem szükségképpen csak elsödleges kulcs. A
  FOREIGN KEY klauzula név szerint adhatja meg a hivatkozott
  oszlopot (oszlopokat). Ha nem ez történik , alapértelmezés
  szerint a hivatkozott tábla elsödleges kulcsának használa-
  ta történik (ez a normál eset ; lásd a fenti példákat).
  A jelen könyv irójának véleménye szerint az a képesség ,
  hogy olyan egyedi azonositóra hivatkozás történjen , ame-
  lyik nem az elsödleges kulcs , jó példa a "hamis általá-
  nosságra": A többlet szabadságfok ténylegesen nem biztosit
  semmilyen többlet funkcionalitást , egyszerüen csak nagyobb
  bonyolultsághoz vezet. 
 A REFERENCES privilégium 
 Annak elöirására , hogy a T2 tábla T2.FK oszlopa egy idegen
 kulcs , mely a T1 tábla T1.PK oszlopára hivatkozik a T2 tábla
 létrehozójának rendelkeznie kell a REFERENCES privilégiummal
 a T1.PK oszlopban. A T1 tábla létrehozója automatikusan bir-
 tokolja a REFERENCES privilégiumot a T1 tábla minden oszlopá-
 ban és megadhatja ezt a privilégiumot (oszlopról oszlopra a-
 lapon , ha ugy kivánja) , más felhasználóknak. 
  Magyarázat : A fentiekböl következöen ugy tünik , hogy T1
  és T2 két tábla , melyeknek különbözö U1 és U2 tulajdono-
  saik vannak , ezek közül egyszerre mindkettö nem tartalmazhat 
  a másikra hivatkozó idegen kulcsot (mivel T1 nem hozható
  létre mindaddig , amig U1 birtokolja a REFERENCES privilégi-
  umot a T2-ben és U1-nek nem adhatja meg ezt a privilégiumot
  az U2 , mindaddig , amig az U2 létre nem hozta T2-t és U2
  nem hozhatje létre T2-t , mindaddig , amig T2 birtokolja a
  references privilégiumot T1-en , stb .., stb.) Ez nem lát-
  szik nagyon kivánatos korlátozásnak.    
  sql.doc Page: 109  
   12
 -------- ----- ------ ----- ----- --------- ----- ------ 
 Manipulativ kiterjesztések 
 12.1 ORTOGONALITAS TOVABBFEJLESZTÉSEK  
 A szabványos SQL nem nagyon ortogonális nyelv. A jelen könyv
 korábbi részében leirt részletes kritikák közül sok lényegé-
 ben ezen általános (és nagyon széleskörü) panasz specifikus
 esetei. Az ortogonalitás függetlenséget jelent : egy nyelv or-
 togonális , ha független fogalmak függetlenek maradnak és nem
 keverednek egymással zürzavaros módokon. Az ortogonalitás hiá-
 nyára egy példát (sok közül egyet ) az SQL-ben az a szabály ad,
 amelyiknek az az értelme , hogy beépitett függvényhez tartozó
 argumentum nem lehet másik függvény hivatkozás (a további tár-
 gyalást lásd az A. függelékben). 
  Az ortogonalitás kivánatos , mivel minél keésbé ortogoná-
 lis egy nyelv , annál bonyolultabb és (paradox módon , de ezzel
 egyidejüleg) annál kevésbé hatékony."Az ortogonális konstruk-
 ció maximalizálja a kifejezöképességet , miközben elkerüli a 
 veszedelmes felesleges dolgokat" (A.van Wijngaarden és munka-
 társai , eds., Revised Report on the Algorithmic Language Algol
 68, (Módositott jelentés algol 68-as algoritmikus nyelvröl )
 Springer-Verlag, 1976-os kiadványból). Az SQL , a jelenleg de-
 finiált állapotban , rendkivül fogyatékos ebböl a szempontból.
 Ezt a tényt felismerve az X3H2 bizottság jelenleg kisérletet
 tesz a korlátozások közül néhány eltávolitására a hivatalos
 szabványból. A jelen alfejezetben fölvázoljuk az ebben az i-
 rányban tett fö javaslatokat. 
 1. A lekérdezés kifejezések - vagyis a "query specifications" 
 (lekérdezés specifikációk) UNION-jai (lásd a 9.1. alfejezetet)
 - már nincsenek arra korlátozva , hogy csak cursor definició
 kontextusában jelenhetnek meg. Ehelyett , most már a következö
 kontextusokban is meg vannak engedve (amely lényegében azt
 jelenti , hogy az UNION most meg van engedve ezekben a kontextu-
 sokban): 
 (a) CREATE VIEW-en belül (a nézet érvényességi körének defi-
  niálásához);
 (b) Al-lekérdezésben (vagyis egy al-lekérdezés nemcsak egy-
  szerüen lekérdezési kifejezés zárójelek közé zárva - ki-
  véve , hogy az al-lekérdezés kiértékelésének eredménye még
  mindig egy oszlopos tábla kell, hogy legyen , kivéve , ha
  ez egy EXISTS argumentum;
 (c) INSERT-en belül (több soros formátum) a beszurandó sorok
  definiálására;
 (d) FROM klauzulán belül. 
  Ezek közül az utolsó bizonyos további magyarázatot igé-
 nyel. A FROM klauzula altalános szintaxisa még mindig : 
  sql.doc Page: 110 
  FROM table-reference-commalist 
 de a "table reference" (tábla hivatkozás) most ki van terjeszt-
 ve a következöképpen : 
  table-reference
  ::= table [[AS] range-variable]
  :( query-expression )[AS] range-variable 
  Az "AS" csak zavart okoz mindkét esetben . Az elsö alak lé-
 nyegében ugyanaz , mint a mai szabványos SQL-ben ; a második be-
 vezeti azt az elgondolást , hogy, ahelyett , hogy a FROM operan-
 dusait megnevezett táblákra korlátoznánk , tábla értékü kife-
 jezések lehetnek. Például : 
  SELECT MAX ( X.CITY )
  FROM ( SELECT S.CITY FROM S
  UNION
  SELECT P.CITY FROM P )  
  Azonban , jegyezzük meg , hogy UNION még mindig nincs meg-
 engedve SELECT utasitásban (vagyis szingli SELECT-ben).  
   Magyarázat: Ez a kiterjesztés, jóllehet kivánatos olyan
  mértékben, ahogyan ismertettük, még mindig nem ismeri el
  azt az alapvetö szempontot, hogy egy tábla nevet csak egy
  általános tábla (vagy lekérdezés) kifejezés speciális
  esetének szabad tekinteni. Magyarázat vége. 
  A "query specification" (lekérdezés megadás) szintaktikai
 kategóriának most csak lekérdezés kifejezés komponenseként van
 jelentése (lényegében egy lekérdezés megadás egyszerüen olyan
 lekérdezés kifejezés, mely nem tartalmaz semmilyen UNION-t.) 
 2. DISTINCT-et tartalmazó függvényhez az argumentum már nincs
 arra korlátozva, hogy oszlop referencia legyen, hanem ehelyett
 bármilyen skalár kifejezés lehet. 
 3. Elvetették a csoportositott nézetekre vonatkozó korlátozá-
 sokat (például egy FROM klauzula, amely hivatkozást tartalmaz
 csoportositott nézetekre, nem tartalmazhat semmilyen más tábla
 hivatkozásokat). Tulajdonképpen a "grouped view" (csoportosi-
 tott nézet) kifejezést teljes mértékben elvetették. 
 4. Most lehetöség van nevek bevitelére SELECT klauzulában lé-
 vö származtatott oszlopokhoz, mint például a következökben: 
  SELECT P.PNO, ( P.WEIGHT 454 ) AS GMWT
  FROM P
  ORDER BY GMWT 
 Itt az "AS" nem zavaró - erre szükség van. A bevitt névre hi -
 vatkozni lehet az ORDER BY-ban (minta példában), de nem le-
 het hivatkozni semmilyen más klauzulában (WHERE, stb.). 
  sql.doc Page: 111  
 12.2. CSúSZTATó CURSOROK 
 Emlékezzünk vissza a 6. fejezetböl, hogy a szabványos SQL-ben
 az egyetlen cursor elmozditási müvelet a FETCH (jelentése
 "fetch next" (következö fetch-je)). A csúsztató cursor a
 standard cursornak egy kiterjesztett verziója, olyan verzió,
 melyben támogatva vannak más cursor elmozditási müveletek.
 Egy cursort csúsztató cursorként a cursor definicióban a
 CURSOR kulcsszót közvetlenül megelözö SCROLL kulcsszó megje-
 lenése definiálja. Például: 
  DECLARE X SCROLL CURSOR
  FOR SELECT ... etc 
 A FETCH utasitás ki van bövitve úgy, hogy tartalmazzon
 egy "fetch orientation" (fetch orientáció) megadást a követke-
 zöképpen: 
  FETCH [fetch-orientation] cursor INTO target-commalist 
 ahol "fetch orientation" a következök valamelyike: 
  NEXT
  PRIOR
  FIRST
  LAST
  ABSOLUTE scalar-expression
  RELATIVE scalar-expression 
 (NEXT az alapértelmezés és az egyetlen megengedett opció, ha
 a cursor nem csúsztató cursor). NEXT (KÖVETKEZÖ), PRIOR (ELÖZÖ),
 FIRST (ELSÖ) és LAST (UTOLSó) önmagát magyarázzák. Az utolsó
 két esetben, legyen n a skalár kifejezés (amelynek exakt nume-
 rikus tipusúnak kell lennie kiértékelésének (kiszámitásának)
 eredménye; ennek nem szabad nullának lennie. ABSOLUTE n elmoz-
 ditja a cursort az n. sorhoz (a végétöl visszafelé számolva,
 ha n negativ). RELATIVE n elmozditja a cursort az n-edik sor-
 ra az aktuális helytöl kezdve (ismét visszafelé számitva, ha
 n negativ).               
  sql.doc Page: 112  
 A. Függelék
  Minta feladatok gyüjteménye 
 A.1 BEVEZETÉS 
 Ebben a fejezetben minta feladatok "testbed"-jét adjuk meg azok-
 nak az olvasóknak, akik ki óhajtják próbálni képességeiket néhány
 szabványos SQL kód megirásában. A feladatok (nagyrészt) a szerzö-
 nek a Guide to DB2 (A DB2 bevezetése) (Addison-Wesley, 1984) cimü
 könyvéböl vett feladatokon alapulnak. Ezek nagy része a "szállitók-
 alkatrészek-projectek" adatbázist tartalmazza (lásd az A.1 ábrát).
 Az adatbázis információkat tartalmaz a szállitókról (suppliers, S),
 alkatrészekröl (parts, P) és projectekröl (projects, J). A szálli-
 tókat, alkatrészeket és projecteket egyedi módon azonositja a szál-
 litó szám (SNO), alkatrész szám (PNO), illetve project szám (JNO).
 Egy SPJ (szállitmány) sornak az a jelentése, hogy a megadott szál-
 litó leszállitja a megadott alkatrészt a megadott projecthez a mega-
 dott mennyiségben (és az (SNO-PNO-JNO kombináció egyedi módon azono-
 sit egy ilyen sort). 
 A.2 ADAT DEFINICIó 
 A.2.1 Irjunk egy alkalmas sémát (vagyis CREATE TABLE utasitások hal-
  mazát) a szállitók-alkatrészek projectek adatbázishoz. 
 A.2.2 Hozzunk létre egy nézetet, mely a (csak) Londonban megvalósuló
  projectekhez tartalmaz project információkat. 
 A.2.3 Definiáljuk a szállitók - és - alkatrészek adatbázisának SP
  tábláját a szállitók-alkatrészek-projectek adatbázis SPJ táblá-
  ja nézeteként.                       
  sql.doc Page: 113  
 A.1 ábra A szállitók - alkatrészek - projectek adatbázis 
 S --- ----- ------ ------ SPJ --- --- --- ---
  SNO SNAME STATUS CITY SNO PNO JNO QTY
  --- ----- ------ ------ --- --- --- ---
  S1 Smith 20 London S1 P1 J1 200
  S2 Jones 10 Paris S1 P1 J4 700
  S3 Blake 30 Paris S2 P3 J1 400
  S4 Clark 20 London S2 P3 J2 200
  S5 Adams 30 Athens S2 P3 J3 200
  S2 P3 J4 500
 P --- ----- ----- ------ ------ S2 P3 J5 600
  PNO PNAME COLOR WEIGHT CITY S2 P3 J6 400
  --- ----- ----- ------ ------ S2 P3 J7 800
  P1 Nut Red 12 London S2 P5 J2 100
  P2 Bolt Green 17 Paris S3 P3 J1 200
  P3 Screw Blue 17 Rome S3 P4 J2 500
  P4 Screw Red 14 London S4 P6 J3 300
  P5 Cam Blue 12 Paris S4 P6 J7 300
  P6 Cog Red 19 London S5 P2 J2 200
  S5 P2 J4 100
 J --- -------- ------  S5 P5 J5 500
  JNO JNAME CITY S5 P5 J7 100
  --- -------- ------ S5 P6 J2 200
  J1 Sorter Paris S5 P1 J4 100
  J2 Punch Rome S5 P3 J4 200
   J3 Reader Athens S5 P4 J4 800
  J4 Console Athens S5 P5 J4 400
  J5 Collator London S5 P6 J4 500
  J6 Terminal Oslo
  J7 Tape London 
 Ahol:
  SNO = Szállitó száma
   SNAME = szállitó neve
  STATUS = állapot
  CITY = város
  PNO = alkatrész szám
  PNAME = alkatrész neve
  COLOR = szin
  WEIGHT = súly
  Nut = anya
  Bolt = fejescsavar
  Screw = csavar
  Cam = bütyök
  Cog = fogaskerék
  Red = vörös
  Green = zöld
  Blue = kék
  JNO = project száma
  JNAME = project megnevezés
  Sorter = rendezö
  Punch = lyukasztó
  Reader = olvasó
  sql.doc Page: 114 
  Console = konzol
  Collator = válogatógép
  terminal = terminál
  Tape = szalag 
 A.2.4 Hozzunk létre egy nézetet a szállitók-alkatrészek-projec-
  tek adatbázisból, mely tartalmazza az összes olyan projec-
  tet (csak project szám és város oszlopok), melyeknek az S1
  szállitó szállit, vagy amelyek P1 alkatrészt használnak. 
 A.2.5 Hozzunk létre egy nézetet, amely a nem ugyanabban a vá-
  rosban lévö szállitókhoz és alkatrészekhez tartozó szállitó
  számokból és alkatrész számokból áll. 
 A.2.6 Adva van az alábbi nézet definició: 
  CREATE VIEW SUMMARY ( SNO, PNO, MAXQ , MINQ, AVGQ )
  AS SELECT SPJ.SNO, SPJ.PNO,
   MAX ( SPJ.QTY ), MIN ( SPJ.QTY ), AVG ( SPJ.QTY )
  FROM SPJ
  GROUP BY SPJ.SNO, SPJ.PNO
  HAVING SUM ( SPJ.QTY ) > 50 
  Határozza meg, hogy a következö lekérdezés kifejezések és
  aktualizálási müveletek közül melyek azok, amelyek megenge-
  dettek és, azokhoz, amelyek megengedettek, adja meg a lefor-
  ditott ekvivalenseket. 
  (a) SELECT *
  FROM SUMMARY 
  (b) SELECT *
  FROM SUMMARY
  WHERE SUMMARY.SNO <> 'S1' 
   (c) SELECT *
  FROM SUMMARY
  WHERE SUMMARY.MAXQ > 250 
  (d) SELECT SUMMARY.MAXQ - SUMMARY.MINQ, SUMMARY.SNO, SUMMARY.PNO
  FROM SUMMARY
  WHERE SUMMARY.SNO = 'S1'
  AND SUMMARY.PNO = 'P1' 
  (e) SELECT SUMMARY.SNO
  FROM SUMMARY
  GROUP BY SUMMARY.SNO 
  (f) SELECT SUMMARY.SNO, SUMMARY.MAXQ
  FROM SUMMARY
  GROUP BY SUMMARY.SNO, SUMMARY.MAXQ 
  (g) SELECT S.SNO, SUMMARY.AVGQ
  FROM S, SUMMARY
  WHERE S.SNO = SUMMARY.SNO
  sql.doc Page: 115  
  (h) UPDATE SUMMARY
  SET SNO = 'S2'
  WHERE SUMMARY.SNO = 'S1' 
  (i) UPDATE SUMMARY
  SET SUMMARY.MAXQ = 1000
  WHERE SUMMARY.SNO = 'S1' 
  (j) DELETE
  FROM SUMMARY
  WHERE SUMMARY.SNO = 'S1' 
 A.3 ADAT MANIPULáLáS: VISSZANYERéSI MÜVELETEK
  -------- ----- ------ -------- 
 Irjon lekérdezés kifejezéseket a következökhöz. 
 Egyszerü lekérdezések 
 A.3.1 Keressük meg minden project minden részletét.
 A.3.2 Keressük meg minden londoni project minden részletét.
 A.3.3 Keressük meg azon szállitók szállitó számait, akik J1
  projectnek szállitanak.
 A.3.4 Keressük meg az összes olyan szállitmányt, ahol a meny-
  nyiség 300 és 750 (ezt is beleértve) közötti tartományban van.
 A.3.5 Keressük meg az osszes alkatrész-szin/alkatrész-város kom-
  bináció listáját, ismétlödö sor szin/város párok kihagyásával.
 A.3.6 Keressük meg az összes olyan szállitmányt, ahol a mennyiség
  nem nulla.
 A.3.7 Keressük meg azokat a project számokat és városokat, ahol a
  város nevében a második betüként "o" szerepel. 
 Összekapcsolások 
 A.3.8 Keressük meg az összes szállitó-szám/alkatrész szám/project
  szám hármasokat, amelyeknél a jelzett szállitó, alkatrész
  és project ugyanabban a városban van.
 A.3.9 Keressük meg az összes olyan szállitó szám/alkatrész szám/
  project szám hármast, amelyeknél a jelzett szállitó/alkatrész
   és project közül nem mindegyik ugyanabban a városban van.
 A.3.10 Keressük meg az összes olyan szállitószám/alkatrészszám/project
  szám hármast, amelyeknél a jelzett szállitó, alkatrész és pro-
  ject közül kettö ugyanabban a városban van.
 A.3.11 Keressük meg azoknak az alkatrészeknek az alkatrészszámait,
  amelyeket londoni szállitó szállitott.
 A.3.12 Keressük meg azoknak az alkatrészeknek az alkatrészszámait,
  amelyeket londoni szállitó szállit londoni projectekhez.
 A.3.13 Keressük meg az összes olyan város név párt, amelyeknél az
  elsö városban lévö szállitó szállit a második városban lévö
  projecthez.
 A.3.14 Keressük meg az összes olyan alkatrésznek az alkatrész számát,
  amelyeket bármilyen projecthez ugyanabban a városban lévö
  szállitó szállit, mint amelyikben a project van.
 A.3.15 Keressük meg az összes olyan projecthez tartozó project szá-
  sql.doc Page: 116 
  mot, amelyben legalább egy, nem ugyanabban a városban lévö
  szállitó szállit.
 A.3.16 Keressük meg az összes olyan alkatrész szám párt, amelyeknél
  a jelzett mindkét alkatrészt valamilyen (ugyanaz) a szállitó
  szállitja. 
 Al-lekérdezések 
 A.3.17 Keressük meg azoknak a projecteknek a neveit, melyekhez az S1
  szállitó szállit.
 A.3.18 Keressük meg azoknak az alkatrészeknek a szineit, melyeket az
  S1 szállitó szállit.
 A.3.19 Keressük meg azoknak az alkatrészeknek az alkatrész számait,
  amelyeket valamilyen londoni projecthez szállitanak.
 A.3.20 Keressük meg azoknak a projecteknek a project számait, amelyek
  legalább egy olyan alkatrészt használnak, mely az S1 szállitó-
  tól áll rendelkezésre.
 A.3.21 Keressük meg azoknak a szállitóknak a szállitó számait, akik
  legalább egy olyan alkatrészt szállitanak, melyet viszont lega-
  lább egy olyan szállitó szállit, aki legalább egy vörös alkat-
  részt szállit.
 A.3.22 Keressük meg azoknak a szállitóknak a szállitó számait, akiknek
  az állapota kisebb, mint az S1 szállitó állapota.
 A.3.23 Keressük meg azoknak a szállitóknak a szállitó számait, akik
  olyan mennyiségben szállitanak valamilyen projecthez P1 alkat-
  részt, amely nagyobb, mint az ehhez a projecthez a P1 alkatrész
   átlagos szállitmány mennyisége. 
 EXISTS 
 A.3.24 Ismételjük meg az A.3.19 sz. feladatot úgy, hogy a megoldásban
  használjunk EXISTS-et.
 A.3.25 Ismételjük meg az A.3.20 sz. feladatot úgy, hogy a megoldásban
  használjunk EXISTS-et.
 A.3.26 Keressük meg azoknak a projecteknek a project számait, melyek-
  hez nincs olyan londoni szállitó, aki vörös alkatrészt szállit.
 A.3.27 Keressük meg azoknak a projecteknek a project számait, melyek-
  hez kizárólag (teljesen) az S1 szállitó szállit.
 A.3.28 Keressük meg azoknak az alkatrészeknek az alkatrész számait,
  melyeket az összes londoni projecthez szállitanak.
 A.3.29 Keressük meg azoknak a szállitóknak a szállitó számait, akik
  ugyanazt az alkatrészt szállitják minden projecthez.
 A.3.30 Keressük meg azoknak a projecteknek a project számait, melyek-
  hez az S1 szállitótól rendelkezésre álló összes alkatrészt
  szállitják. 
 A következö négy (A.3.31-A.3.34) feladatban alakitsa vissza a bemuta-
 tott SQL kifejezést ekvivalens, angol nyelvü megfogalmazásra.       
  sql.doc Page: 117 
 A.3.31 SELECT DISTINCT SPJX.JNO
  FROM SPJ SPJX
  WHERE NOT EXISTS
  ( SELECT *
  FROM SPJ SPJY
   WHERE SPJY.JNO = SPJX.JNO
  AND NOT EXISTS
  ( SELECT *
  FROM SPJ SPJZ
  WHERE SPJZ.PNO = SPJY.PNO
  AND SPJZ.SNO = 'S1' )) 
 A.3.32 SELECT DISTINCT SPJX.JNO
  FROM SPJ SPJX
  WHERE NOT EXISTS
  ( SELECT *
  FROM SPJ SPJY
  WHERE EXISTS
  ( SELECT *
  FROM SPJ SPJA
  WHERE SPJA.SNO = 'S1'
  AND SPJA.PNO = SPJY.PNO )
  AND NOT EXISTS
  ( SELECT *
  FROM SPJ SPJB
  WHERE SPJB.SNO = 'S1'
  AND SPJB.PNO = SPJY.PNO
  AND SPJB.JNO = SPJX.JNO )) 
 A.3.33 SELECT DISTINCT SPJX.JNO
  FROM SPJ SPJX
  WHERE NOT EXISTS
  ( SELECT *
  FROM SPJ SPJY
  WHERE EXISTS
   ( SELECT *
  FROM SPJ SPJA
  WHERE SPJA.PNO = SPJY.PNO
  AND SPJA.JNO = SPJX.JNO )
  AND NOT EXISTS
  ( SELECT *
  FROM SPJ SPJB
  WHERE SPJB.SNO = 'S1'
  AND SPJB.PNO = SPJY.PNO
  AND SPJB.JNO = SPJX.JNO ))          
  sql.doc Page: 118  
 A.3.34 SELECT DISTINCT SPJX.JNO
  FROM SPJ SPJX
  WHERE NOT EXISTS
  ( SELECT *
  FROM SPJ SPJY
  WHERE EXISTS
  ( SELECT *
  FROM SPJ SPJA
  WHERE  SPJA.SNO = SPJY.SNO
  AND SPJA.PNO.IN
  ( SELECT P.PNO
  FROM P
  WHERE P.COLOR = 'RED' )
  AND NOT EXISTS
  ( SELECT *
   FROM SPJ SPJB
  WHERE SPJB.SNO = SPJY.SNO
  AND SPJB.JNO = SPJX.JNO ))) 
 Beépitett függvények 
 A.3.35 Keressük meg azoknak a projecteknek az össz számát, amelyeket
  az S1 szállitó szállit.
 A.3.36 Keressük meg annak a P1 alkatrésznek a teljes mennyiségét, a-
  melyet az S1 szállitó szállit.
 A.3.37 Egy projecthez leszállitandó minden alkatrészhez keressük meg
  az alkatrész számát, a project számát és a megfelelö teljes
  mennyiséget.
 A.3.38 Keressük meg azoknak a projecteknek a project számait, amelyek
  városa az elsö az ilyen városok abc-szerinti listájában.
 A.3.39 Keressük meg azokhoz a projectekhez tartozó project számokat,
  melyekhez P1 alkatrészt olyan átlagos mennyiségben szállitanak,
  amely nagyobb, mint az a legnagyobb mennyiség, melyben valamilyen
  alkatrészt a J1 projecthez szállitanak.
 A.3.40 Keressük meg azoknak a szállitóknak a szállitó számait, akik
  valamilyen projecthez olyan mennyiségben szállitanak P1 alkat-
  részt, amelyik nagyobb, mint az átlagos mennyiség, amelyben
  ehhez a projecthez P1 alkatrész szállitása történik. 
 Egyesités 
 A.3.41 Allitsuk össze az összes olyan város listáját, melyben legalább
  egy szállitó, alkatrész vagy project van.
 A.3.42 Mutassuk meg a következö eredményét: 
  SELECT P.COLOR
  FROM P
  UNION
  SELECT P.COLOR
  FROM P    
  sql.doc Page: 119  
 A.4 ADAT MANIPULáCIó: AKTUALIZALASI MÜVELETEK 
 Irjunk INSERT, DELETE vagy UPDATE utasitásokat (az adott helyzet-
 nek megfelelöen) a következö feladatok mindegyikéhez: 
 A.4.1 Változtassuk meg az összes vörös alkatrész szinét narancs-
  sárgára.
 A.4.2 Töröljük az összes olyan projectet, melyhez nincs szállitmány.
 A.4.3 Növeljük meg 10 %-kal a szállitmány szállitási mennyiségét
  minden olyan szállitmány esetén, mely vörös alkatrészt szálli-
  tó szállitótól érkezik.
 A.4.4 Törölje az összes római projectet és minden ehhez tartozó szál-
  litmányt.
 A.4.5 Helyezzen be egy új szállitót (S10) az S táblába. A név és város
  "White" (fehér), illetve "New York"; az állapot még nem ismert.
 A.4.6 Allitsunk össze egy táblát, mely azon alkatrészek alkatrész szá-
  mainak listáját tartalmazza, amelyeket vagy londoni szállitó
  szállit, vagy amelyeket egy londoni projecthez szállitanak.  
 A.4.7 Allitsunk össze egy táblát, mely azon projectek project
 számainak listáját tartalmazza, amelyek vagy londoni projec-
 tek, vagy amelyekhez londoni szállitó szállit.
 A.4.8 Adjunk hozzá 10-et az összes olyan szállitó állapotához,
 amelynek az állapota jelenleg kisebb, mint az S4 szállitó ál-
 lapota. 
 A.5 BEAGYAZOTT SQL 
 A.5.1 Irjunk beágyazott SQL programot minden szállitó felsoro-
 lására, szállitó szám sorrendben. A felsorolásban minden szál-
 litót közvetlenül követnie kell az összes olyan projectnek,
 amelyhez ez a szállitó szállit, project szám sorrendben. 
 A.5.2 Módositsuk az A.5.1 számú feladatunkhoz elkészitett
 megoldásunkat úgy, hogy ezen kivül tegyük a következöket: (a)
 növeljük meg az állapotot 50 %-kal minden olyan szállitó ese-
 tén, akik kettönél több projecthez szállitanak; (b) töröljünk
 minden olyan szállitót, aki egyáltalán semmilyen projecthez sem
 szállit. 
 A.5.3(Nehezebb). Adva vannak az alábbi táblák: 
  CREATE TABLE PARTS
  ( PNO ... NOT NULL,
  DESCRIPTION ... ) 
  CREATE TABLE PART_STRUCTURE
  ( MAJOR_PNO ... NOT NULL,
  MINOR_PNO ... NOT NULL,
  QTY ... ) ; 
 ahol PART_STRUCTURE mutatja, hogy mely alkatrészek (MAJOR_PNO)
 mely más alkatrészeket (MINOR_PNO) tartalmaznak elsö szintü
 komponensként, irjunk beágyazott SQL programot adott alkatrész
  sql.doc  Page: 120 
 minden komponens alkatrészének felsorolására, minden szinthez
 (az "alkatrészek robbantási" problémája). 
 A.6 VALASZOK 
 Ebben az alfejezetben megadjuk a lehetseges válaszok halmazát
 az A.2-A.5 alfejezetek feladataira. A bemutatott megoldások
 nem szükségképpen az egyetlen lehetséges megoldást jelen-
 tik. 
 A.2.1 CREATE TABLE S
  ( SNO CHAR(5) NOT NULL UNIQUE,
  SNAME CHAR(20),
  STATUS DECIMAL(3),
  CITY CHAR(15) ) 
  CREATE TABLE P
  ( PNO CHAR(6) NOT NULL UNIQUE,
  PNAME CHAR(20),
  COLOR CHAR(6),
  WEIGHT DECIMAL(3),
  CITY CHAR(15) ) 
  CREATE TABLE J
  ( JNO CHAR(4) NOT NULL UNIQUE,
  JNAME CHAR(10),
  CITY CHAR(15) ) 
  CREATE TABLE SPJ
  ( SNO CHAR(5) NOT NULL,
  PNO CHAR(6) NOT NULL,
  JNO CHAR(4) NOT NULL,
  QTY DECIMAL(5)
  UNIQUE ( SNO, PNO, JNO ) ) 
 A.2.2 CREATE VIEW LONDON PROJECTS ( JNO, JNAME, CITY )
  AS SELECT J.JNO, J.JNAME, J.CITY
  FROM J
  WHERE J.CITY = 'London' 
 A.2.3  CREATE VIEW SP ( SNO, PNO, QTY )
  AS SELECT SPJ.SNO, SPJ.PNO, SUM ( SPJ.QTY )
  FROM SPJ
  GROUP BY SPJ.SNO, SPJ.PNO 
 A.2.4 CREATE VIEW JC ( JNO, CITY )
  AS SELECT DISTINCT J.JNO. J.CITY
   FROM J, SPJ
  WHERE J.JNO = SPJ.JNO
  AND ( SPJ.SNO = 'S1' OR
  SPJ.PNO = 'P1' ) 
 A.2.5 CREATE VIEW NON_COLOCATED ( SNO, PNO)
  AS SELECT S.SNO, P.PNO
  FROM S, P
   sql.doc Page: 121 
  WHERE S.CITY <> P.CITY 
 A.2.6 Csak (a), (b) és (d) van megengedve. A (d) lefordi-
 tott verziója: 
  SELECT MAX(SPJ.QTY)-MIN(SPJ.QTY), SPJ.SNO, SPJ.PNO
  FROM SPJ
  WHERE SPJ.SNO= 'S1'
  AND SPJ.PNO= 'P1'
  GROUP BY SPJ.SNO, SPJ.PNO
  HAAVING SUM(SPJ.QTY)> 50 
 A.3.1 SELECT J.JNO, J.JNAME, J.CITY
  FROM J 
 A.3.2 SELECT J.JNO, J.JNAME, J.CITY
  FROM J
  WHERE J.CITY='London' 
 A.3.3 SELECT DISTINCT SPJ.SNO
  FROM SPJ
  WHERE SPJ.JNO='J1'
  ORDER BY SPJ.SNO 
 A.3.4 SELECT SPJ.SNO, SPJ.PNO, SPJ.JNO, SPJ.QTY
  FROM SPJ
  WHERE SPJ.QTY BETWEEN 300 AND 750 
 A.3.5 SELECT DISTINCT P.COLOR, P.CITY
  FROM P 
 A.3.6 SELECT SPJ.SNO, SPJ.PNO, SPJ.JNO, SPJ.QTY
  FROM SPJ
  WHERE SPJ.QTY IS NOT NULL 
 A.3.7 SELECT J.JNO, J.CITY
  FROM J
  WHERE J.CITY LIKE '_0%' 
 A.3.8 SELECT S.SNO, P.PNO, J.JNO
  FROM S, P, J
  WHERE S.CITY = P.CITY
  AND P.CITY = J.CITY 
 A.3.9 SELECT S.SNO, P.PNO, J.JNO
  FROM S, P, J
  WHERE NOT
  ( S.CITY = P.CITY AND P.CITY = J.CITY ) 
 A.3.10 SELECT S.SNO, P.PNO, J.JNO
  FROM S, P, J
  WHERE S.CITY <> P.CITY
  AND P.CITY <> J.CITY
  AND J.CITY <> S.CITY 
  sql.doc Page: 122  
 A.3.11 SELECT DISTINCT SPJ.PNO
  FROM SPJ, S
  WHERE SPJ.SNO = S.SNO
  AND S.CITY = 'London' 
 A.3.12 SELECT DICTINCT SPJ.PNO
  FROM SPJ, S, J
  WHERE SPJ.SNO = S.SNO
  AND SPJ.JNO = J.JNO
  AND S.CITY = 'London'
  AND J.CITY = 'London' 
 A.3.13 SELECT DISTINCT S.CITY, J.CITY
  FROM S, SPJ, J
  WHERE S.SNO = SPJ.SNO
  AND SPJ.JNO = J.JNO 
 A.3.14 SELECT DISTINCT SPJ.PNO
  FROM SPJ, S, J
  WHERE SPJ.SNO = S.SNO
  AND SPJ.JNO = J.JNO
  AND S.CITY = J.CITY 
 A.3.15 SELECT DISTINCT J.JNO
  FROM SPJ, S, J
  WHERE SPJ.SNO = S.SNO
  AND SPJ.JNO = J.JNO
  AND S.CITY <> J.CITY 
 A.3.16 SELECT SPJX.PNO, SPJY.PNO
  FROM SPJ.SPJX, SPJ.SPJY
  WHERE SPJX.SNO = SPJY.SNO
  AND SPJX.PNO > SPJY.PNO 
 A.3.17 SELECT J.JNAME
  FROM J
  WHERE J.JNO IN
  ( SELECT SPJ.JNO
  FROM SPJ
  WHERE  SPJ.SNO = 'S1' ) 
 A.3.18 SELECT DISTINCT P.COLOR
  FROM P
  WHERE P.PNO IN
  ( SELECT SPJ.PNO
  FROM SPJ
  WHERE SPJ.SNO = 'S1' ) 
 A.3.19 SELECT DISTINCT SPJ.PNO
  FROM SPJ
  WHERE SPJ.JNO IN
  ( SELECT J.JNO
  FROM J
  WHERE J.CITY = 'London' )
  sql.doc Page: 123  
 A.3.20 SELECT DISTINCT SPJ.JNO
  FROM SPJ
  WHERE SPJ.PNO IN
  ( SELECT SPJ.PNO
  FROM SPJ
  WHERE SPJ.SNO = 'S1' ) 
 A.3.21 SELECT DISTINCT SPJ.SNO
  FROM SPJ
  WHERE SPJ.PNO IN
  ( SELECT SPJ.PNO
  FROM SPJ
   WHERE SPJ.SNO IN
  ( SELECT SPJ.SNO
  FROM SPJ
  WHERE SPJ.PNO IN
  ( SELECT P.PNO
  FROM P
  WHERE P.COLOR = 'Red' ) ) ) 
 A.3.22 SELECT S.SNO
  FROM S
  WHERE S.STATUS <
  ( SELECT S.STATUS
  FROM S
  WHERE S.SNO = 'S1' ) 
 A.3.23 SELECT DISTINCT SPJX.SNO
  FROM SPJ SPJX
  WHERE SPJX.PNO = 'P1'
  AND SPJX.QTY >
  ( SELECT AVG (SPJY.QTY)
  FROM SPJ SPJY
  WHERE SPJY.PNO = 'P1'
  AND SPJY.JNO = SPJX.JNO ) 
 A.3.24 SELECT DISTINCT SPJ.PNO
  FROM SPJ
  WHERE EXISTS
  ( SELECT *
  FROM J
  WHERE J.JNO = SPJ.JNO
  AND J.CITY = 'London' ) 
 A.3.25 SELECT DISTINCT SPJX.JNO
  FROM SPJ SPJX
  WHERE EXISTS
  ( SELECT *
  FROM SPJ SPJY
  WHERE SPJY.PNO = SPJX.PNO
  AND SPJY.SNO = 'S1' )  
 A.3.26 SELECT J.JNO
  FROM J