Metaspråket for å beskrive grammatikk

Størrelse: px
Begynne med side:

Download "Metaspråket for å beskrive grammatikk"

Transkript

1 1 SQL-syntaks Korrekt språkbruk bygger på et sett av regler. Eksempler: En SQL utvalgsspørring inneholder alltid ordene SELECT og FROM, mens WHERE og tilhørende betingelse er valgfri. Etter SELECT kan det komme en liste med kolonnenavn, men det er også lov å bruke funksjoner som COUNT og AVG. GROUP BY er en forutsetning for å bruke HAVING. Slike språkregler kalles for syntaks, og lar seg beskrive presist med en grammatikk. Dette notatet inneholder grammatikken for viktige deler av SQL. Metaspråket for å beskrive grammatikk For å beskrive en grammatikk trenger vi et metaspråk, det vil si et språk for å beskrive et annet. Metaspråket vi skal bruke kalles for BNF (Backus-Naur Form), oppkalt etter John Backus og Peter Naur. BNF ble første gang brukt for å beskrive programmeringsspråket Algol 60 [Naur 1960]. En BNF-grammatikk består av et antall regler. Her er et eksempel med tre regler: <lite-tall> ::= [<fortegn>] <lite-siffer> <lite-siffer> <fortegn> ::= + - <lite-siffer> ::= Symbolene ::=,, [ og ], samt < og >, har en spesiell betydning i metaspråket. Bortsett fra disse symbolene består reglene av metasymboler og grunnsymboler. Metasymbolene er rammet inn av spissparentesene < og >. Grunnsymbolene er alle de øvrige symbolene, som i dette eksemplet er +, -, 1, 2 og 3. Grunnsymbolene utgjør alfabetet i språket vi beskriver. En lovlig setning består av bare grunnsymboler. Metasymbolene er kun hjelpesymboler for å definere strukturen til lovlige setninger. Hver regel består av en venstreside og en høyreside med symbolet ::= mellom. Venstresiden er et enkelt metasymbol, mens høyresiden består av en sekvens av symboler, der brukes for å skille alternative høyresider fra hverandre. Den andre regelen leses som <fortegn> «er på formen» + eller -. Firkantparentesene [ og ] rammer inn konstruksjoner som er valgfrie. Den første regelen sier dermed at <lite-tall> er på formen <fortegn> <lite-siffer> <lite-siffer>, eller <lite-siffer> <lite-siffer>. Merk at reglene refererer til hverandre. Høyresiden for <lite-tall> inneholder både <fortegn> og <lite-siffer>. Ved å sammenholde alle reglene kan

2 2 man slutte at <lite-tall> beskriver tall med to sifre (valgt fra 1, 2 eller 3) og eventuelt et fortegn. Metasymboler er navn på konstruksjoner som skal «ekspanderes». Ved å erstatte venstresider med høyresider kan vi «produsere» setninger. Dette kalles for en avledning. Her er to avledninger fra metasymbolet <lite-tall>: <lite-tall> <lite-siffer> <lite-siffer> 1 <lite-siffer> 13 <lite-tall> <fortegn> <lite-siffer> <lite-siffer> - <lite-siffer> <lite-siffer> - <lite-siffer> 2-32 Enhver grammatikk har et startsymbol. Hvis ikke annet er oppgitt så er startsymbolet det metasymbolet som forekommer på venstresiden av den første regelen. Et språk består av en samling setninger. Språket definert ved en grammatikk er samlingen av alle setninger (som kun består av grunnsymboler), og som kan avledes fra startsymbolet. I avledningene over så er 13 og -32 setninger. Disse kan ikke ekspanderes videre. Vår eksempelgrammatikk beskriver følgende språk: { -11, -12, -13, -21, -22, -23, -31, -32, -33, +11, +12, +13, +21, +22, +23, +31, +32, +33, 11, 12, 13, 21, 22, 23, 31, 32, 33 } De fleste interessante språk er uendelige, det vil si at de inneholder et uendelig antall lovlige setninger. Her er en meget enkel grammatikk som beskriver et uendelig språk: <enere> ::= [<enere>] 1 Det er ofte behov for å beskrive kommaseparerte lister. Hvis <x> er et metasymbol, så angir <x-liste> en ikke-tom liste med x er skilt med komma. Eksempel: <parentes> ::= ( <bin-siffer-liste> ) <bin-siffer> ::= 0 1

3 3 Denne siste grammatikken beskriver språket som inneholder alle mulige sekvenser av 0 og 1, skilt med komma og omsluttet av parenteser: { (0), (1), (0,0), (0,1), (1,0), (1,1), (0,0,0), (0,0,1), (0,1,0), (1,1,0,1,1,0), }. Av og til innfører vi ekstra metasymboler for å gjøre det lettere å lese reglene. For eksempel så er reglene for å navngi tabeller og utsnitt de samme, og kunne vært beskrevet med et felles metasymbol <navn>. Vi bruker likevel både <tabell-navn> og <utsnitt-navn>. Grammatikken i dette vedlegget er sterkt forenklet i forhold til den offisielle SQL-standarden, og det kan nok hende at vår grammatikk godtar visse konstruksjoner som strengt tatt ikke er lovlige. Vi har også navngitt konstruksjoner (metasymboler) på en annen måte enn i standarden, fordi hensikten er å forklare strukturen i språket SQL og hva en grammatikk er, mer enn å gi en komplett og presis definisjon av alle konstruksjoner i SQL. Etter at man har forstått hvordan en grammatikk er bygd opp, vil man være i stand til å lese selve standarden, og også grammatikken for andre programmeringsspråk. SQL-setninger Vi beskriver (en del av) språket SQL topp-ned. Det betyr at vi starter med å definere SQL-setninger 1, og jobber oss ned mot detaljene, med lovlig oppbygging av uttrykk og navn. <SQL-setning> ::= <tabell-def> <tabell-slett> <tabell-endre> <indeks-def> <indeks-slett> <utsnitt-def> <utsnitt-slett> <utvalg-spørring> <innsetting-rad> <innsetting-utvalg> <oppdatering> <sletting> <transaksjon-fullfør> <transaksjon-avbryt> <rettighet-gi> <rettighet-frata> Navn på metasymbolene er valgt med tanke på å være mest mulig selvforklarende, men likevel forholdsvis korte. 1 Vi bruker SQL-setning som det generelle begrepet som fanger inn alle typer av SQL-«kommandoer», og bruker begrepet spørring kun i forbindelse med utvalgsspørringer.

4 4 Tabellstruktur Her har vi samlet tre SQL-setninger for henholdsvis definisjon av tabeller, sletting av tabeller og endring av tabellstruktur. <tabell-def> ::= CREATE TABLE <tabell-navn> ( <tabell-def-elem-liste> ) <tabell-slett> ::= DROP TABLE <tabell-navn> <tabell-endre> ::= ALTER TABLE <tabell-navn> <tabell-endre-elem> En tabelldefinisjon inneholder et antall elementer, for definisjon av kolonner, primærnøkler, fremmednøkler og valideringsregler. <tabell-def-elem> ::= <kolonne-def> <primær-def> <fremmed-def> <regel-def> <kolonne-def> ::= <kolonne-navn> <datatype> [DEFAULT <literal>] [UNIQUE] [NOT NULL] <primær-def> ::= CONSTRAINT <regel-navn> PRIMARY KEY ( <kolonne-navn-liste> ) <fremmed-def> ::= CONSTRAINT <regel-navn> FOREIGN KEY ( <kolonne-navn-liste> ) REFERENCES <tabell-navn> [( <kolonne-navn-liste> )] [ON <hendelse> <aksjon>] <hendelse> ::= UPDATE DELETE <aksjon> ::= RESTRICT SET NULL CASCADE SET DEFAULT <regel-def> ::= CONSTRAINT <regel-navn> CHECK ( <betingelse> ) Elementer i en tabelldefinisjon kan legges til og slettes igjen, etter at tabellen er definert. <tabell-endre-elem> ::= ADD COLUMN <kolonne-def> ADD <primær-def> ADD <fremmed-def> ADD <regel-def>

5 5 DROP COLUMN <kolonne-navn> DROP CONSTRAINT <regel-navn> Hvilke datatyper som er tilgjengelige varierer fra system til system, men vil typisk inkludere følgende: <datatype> ::= CHAR( <heltall-literal> ) VARCHAR( <heltall-literal> ) CLOB( <heltall-literal> ) BLOB( <heltall-literal> ) SMALLINT INTEGER NUMERIC ( <heltall-literal>, <heltall-literal> ) DECIMAL ( <heltall-literal>, <heltall-literal> ) FLOAT( <heltall-literal> ) REAL DOUBLE DATE TIME TIMESTAMP( <heltall-literal> ) INTERVAL BOOLEAN Indekser En indeks er knyttet til en eller flere kolonner i en bestemt tabell. Indekser kan defineres og slettes. <indeks-def> ::= <indeks-slett> ::= CREATE [UNIQUE] INDEX <indeks-navn> ON <tabell-navn> ( <kolonne-navn-liste> ) DROP INDEX <indeks-navn>

6 6 Utsnitt Et utsnitt blir definert ved en utvalgsspørring. Utsnitt kan også slettes. <utsnitt-def> ::= <utsnitt-slett> ::= CREATE VIEW <utsnitt-navn> ( <kolonne-navn-liste> ) AS <utvalg-spørring> DROP VIEW <utsnitt-navn> Merk at utvalgsspørringen som definerer utsnittet ikke kan inneholde ORDER BY. Vi kunne introdusert et eget metasymbol <utvalg-spørringuten-sortering> og fanget inn regelen i selve grammatikken, men har altså i stedet valgt å kommentere denne restriksjonen i fritekst her. Utvalgsspørringer Den vanligste formen for utvalgsspørringer er SELECT-FROM-WHERE, eventuelt utvidet med gruppering og sortering. Slike «enkle» spørringer kan kombineres ved hjelp av mengdeoperatorene UNION, INTERSECT og MINUS. Merk at en utvalgsspørring kan inneholde andre utvalgsspørringer både i SELECT-delen, FROM-delen og WHERE-delen. Syntaksreglene for uttrykk blir beskrevet i et eget avsnitt. <utvalg-spørring> ::= <enkel-spørring> <utvalg-spørring> <mengde-oper> [ALL] <utvalg-spørring> <enkel-spørring> ::= SELECT <utvalg-modus> <utvalg-uttrykk-liste> FROM <tabell-uttrykk-liste> [WHERE <betingelse>] [GROUP BY <kolonne-ref-liste> [HAVING <betingelse>]] [ORDER BY <sortering-elem-liste>] <utvalg-modus> ::= ALL DISTINCT <utvalg-uttrykk> ::= <uttrykk> [AS <kolonne-alias>] <sortering-elem> ::= <uttrykk> [ASC] <uttrykk> [DESC] <mengde-oper> ::= UNION INTERSECT MINUS En utvalgsspørring gir et spørreresultat som er på «tabellform». Spørreresultater og utsnitt kan dermed kobles på lik linje med (lagrede) tabeller. Alle

7 7 tabell-uttrykk, fra enkle navn på tabeller og utsnitt, til kompliserte koblingsuttrykk, kan brukes i FROM-delen. <tabell-uttrykk> ::= <tabell-ref> <utvalg-spørring> <tabell-uttrykk> <koblingstype> <tabell-uttrykk> ON <betingelse> <tabell-uttrykk> AS <tabell-alias> ( <tabell-uttrykk> ) <tabell-ref> ::= <tabell-navn> <utsnitt-navn> <tabell-alias> <koblingstype> ::= [INNER] JOIN NATURAL JOIN LEFT [OUTER] JOIN RIGHT [OUTER] JOIN FULL [OUTER] JOIN Ajourhold av tabellinnhold Ajourhold av tabeller gjøres med kommandoene INSERT, UPDATE og DELETE for henholdsvis innsetting, oppdatering og sletting av rader. INSERT kommer i to varianter, avhengig av om man skal sette inn en enkelt rad, eller overføre mange rader ved hjelp av en utvalgsspørring. <innsetting-rad> ::= INSERT INTO <tabell-navn> [( <kolonne-navn-liste> )] VALUES ( <uttrykk-liste> ) <innsetting-utvalg> ::= INSERT INTO <tabell-navn> [( <kolonne-navn-liste> )] <utvalg-spørring> <oppdatering> ::= UPDATE <tabell-navn> SET <kolonne-tilordning-liste> [WHERE <betingelse>] <kolonne-tilordning> ::= <kolonne-ref> = <uttrykk> <sletting> ::= DELETE FROM <tabell-navn> [WHERE <betingelse>]

8 8 Transaksjoner SQL-setninger for transaksjonshåndtering er syntaktisk svært enkle: <transaksjon-fullfør> ::= COMMIT <transaksjon-avbryt> ::= ROLLBACK Noen DBHS innfører en egen kommando for å starte en transaksjon. Hvis en slik kommando ikke finnes, starter en transaksjon der den forrige ble avsluttet med enten COMMIT eller ROLLBACK. Brukeradministrasjon I sin enkleste form innebærer brukeradministrasjon å tildele eller frata bestemte brukere bestemte rettigheter på bestemte objekter. Et objekt er en samlebetegnelse på det vi kan lagre i en database, som for eksempel tabeller, utsnitt og programmer. De fleste DBHS gir mulighet for å definere brukergrupper eller roller for å forenkle brukeradministrasjon. I så fall må <brukernavn> erstattes av <bruker-eller-gruppe-navn> i syntaksreglene. <rettighet-gi> ::= GRANT <rettighet-liste> ON <objekt-navn> TO <bruker-navn> [WITH GRANT OPTION] <rettighet-frata> ::= REVOKE <rettighet-liste> ON <objekt-navn> FROM <bruker-navn> I et konkret system vil det finnes en omfattende liste av rettigheter, og man skiller gjerne mellom objektrettigheter og systemrettigheter. Objektrettigheter er rettigheter på et bestemt objekt, for eksempel en tabell, mens systemrettigheter er mer generelle rettigheter, for eksempel retten til å lage nye tabeller. <rettighet> ::= SELECT DELETE INSERT UPDATE ALL

9 9 Uttrykk Uttrykk kan forekomme i flere sammenhenger, for eksempel som WHEREdelen av en utvalgsspørring, eller på høyresiden av en kolonnetilordning i en oppdatering. Resultatet av å evaluere et uttrykk er en verdi. En betingelse er et uttrykk som gir en boolsk verdi, det vil si true eller false. <uttrykk> ::= NULL <literal> <kolonne-ref> <funksjons-app> <uttrykk> <binær-oper> <uttrykk> <unær-oper> <uttrykk> <kolonne-ref> BETWEEN <uttrykk> AND <uttrykk> <kolonne-ref> IS [NOT] NULL <uttrykk> <binær-oper-rel> <kvantor> ( <utvalg-spørring> ) EXISTS ( <utvalg-spørring> ) ( <uttrykk> ) <betingelse> ::= <uttrykk> <kvantor> ::= ALL ANY SOME En funksjonsapplikasjon er en anvendelse av en bestemt funksjon. Enten man bruker en «vanlig» funksjon, eller en mengdefunksjon, så er syntaksen den samme. Vi velger likevel å beskrive mengdefunksjonene som en del av grammatikken fordi de ikke kan brukes overalt. <funksjons-app> ::= <funksjons-navn> ( <uttrykk-liste> ) <mengdefunk-navn> ( <kolonne-ref> ) <mengdefunk-navn> ::= AVG MAX MIN SUM COUNT Et operatoruttrykk er bygd opp fra operatorer og operander, der operandene er uttrykk (og tilsvarer argumentlisten til en funksjonsapplikasjon). Vi skiller mellom unære operatorer som skal ha en enkelt operand og binære operatorer som skal ha to operander.

10 10 <unær-oper> ::= <unær-oper-arit> <unær-oper-logisk> <unær-oper-arit> ::= + - <unær-oper-logisk> ::= NOT <binær-oper> ::= <binær-oper-arit> <binær-oper-rel> <binær-oper-logisk> <binær-oper-arit> ::= + - * / <binær-oper-rel> ::= < > <= >= <> = LIKE <binær-oper-logisk> ::= AND OR En kolonnereferanse er et uttrykk som peker på en enkelt kolonne, eller en liste av kolonner. <kolonne-ref> ::= [<tabell-ref>.] <kolonne-navn> [<tabell-ref>.] * <kolonne-alias> Leksikalske elementer SQL er som andre formelle dataspråk satt sammen av enkle byggeklosser som tall, reserverte ord, brukerdefinerte navn, spesielle symboler som punktum, parenteser og semikolon. Disse kalles for leksikalske elementer. Det er fullt mulig å definere syntaksen til de leksikalske elementene med BNF. Vi velger imidlertid å beskrive denne delen av språket mer uformelt, og gir i tillegg noen eksempler. <navn> er en sekvens av bokstaver, sifre og noen spesialtegn som _. Navn må starte med en bokstav, og kan ikke være et reservert ord. Eksempler: etnavn, et_navn, navn_2. I grammatikken blir følgende metasymboler benyttet som synonymer for <navn>: <tabell-navn>, <kolonne-navn>, <regel-navn>, <utsnitt-navn>, <indeks-navn>, <bruker-navn>, <objekt-navn>, <tabell-alias>, <kolonnealias>, <funksjons-navn>. Alle ord skrevet med store bokstaver i reglene er reserverte ord, men det finnes også flere (fordi vi kun gir regler for en del av SQL). Eksempel: SELECT, FROM, WHERE. En literal er en bestemt måte å skrive konkrete verdier på, og varierer med hva slags datatype det er snakk om.

11 11 <literal> ::= <heltall-literal> <kommatall-literal> <tekststreng-literal> <tidspunkt-literal> <heltall-literal> er en sekvens av sifre, eventuelt med fortegn foran. Eksempler: 30, +12, <kommatall-literal> starter med en heltallsliteral, eventuelt etterfulgt av et punktum og en ikke-tom sekvens av sifre, eventuelt igjen etterfulgt av symbolet E (eller e), et valgfritt fortegn, og en ikke-tom sekvens av sifre. Eksempler: 30, +12, -123, , , 1.23E2, E-02, e-09. <tekststreng-literal> er en sekvens av tegn rammet inn av enkle apostrofer. Teksten kan ikke inneholde enkle apostrofer, men en enkel apostrof kan kodes ved å skrive to etterfølgende apostrofer. Eksempler: 'God dag!', 'Tallet 3', 'Bob''s Cafe'. <tidspunkt-literal> består av en dato og/eller et klokkeslett rammet inn av enkle apostrofer. Dato-eksempler: ' ', '2003/12/24', '24-DEC-2004'. Klokkeslett-eksempler: '14:56:07', '2.56 PM', '07.56 AM'. Tidspunkt-eksempel: ' :56:07'. Reglene for å skrive literaler varierer noe fra system til system. For eksempel så godtar Access doble apostrofer rundt tekstliteraler og # rundt datoer, og i Oracle blir datoer og klokkeslett skrevet som tekstliteraler, men man kan styre oppsettet med et brukerdefinert format og en egen funksjon TO_DATE.