Il server eXtraWay non è un DataBase Relazionale e quindi non prevede di implementare pienamente la sintassi SQL bensì limitarsi allo sviluppo delle funzionalità più probabilmente utili a sviluppatori e fruitori di Db XML.
Nella fattispecie, quindi, il server accetta condizioni di Join di varia natura (espresse nella clausola from o nella clausola where) purché la condizione espressa sia di uguaglianza. Non sono accettate altre forme di Join (disuguaglianze o altre condizioni di selezione).
Fatta salva questa principale condizione l'attuale implementazione dell'interprete SQL entro il server eXtraWay accetta tutti gli operatori più direttamente riconducibili a quelli leciti nel linguaggio di ricerca nativo eXtraWay. Vediamo, caso per caso, di cosa stiamo parlando.
La clausola SELECT prevede l'elencazione delle colonne (separate da virgole) che si intendono selezionare. Esse possono essere rappresentate da:
E' consentito l'uso della forma 'name as shotname' per successive semplificazioni nel resto dello statement SQL.
Parimenti, l'uso dei nomi di colonna può corrispondere, di fatto, ad altri 'shortnames' dichiarati, ad esempio, nella clausola FROM.
Nella clausola SELECT non sono accettate, nell'attuale implementazione, le forme:
Alcune di queste funzionalità, per contro, sono ammesse in fase di Update delle tabelle.
La clausola FROM prevede l'elencazione delle tabelle (separate da virgole) sulle quali si estende la selezione e sulle quali vengono svolti i Join. La clausola può inoltre comprendere condizioni di Join a patto che comportino uguaglianza tra valori di colonne. Sono quindi consentite le forme:
AS
seguito da una shorthand per il nome tabella diviene obbligatoria.La sintassi SQL prevede, inoltre, che si possano sfruttare in uno statement SELECT anche forme composite quali la configurazione di viste, di table expressions e di common table expressions. Il presente documento non intende entrare nel dettaglio di queste specifiche, ci sarà sufficiente darne una rapida panoramica e descrivere come sia stata applicata ad eXtraWay una di queste forme.
Le view è il risultato di una query che viene valutata dinamicamente ogni volta che ad essa si fa riferimento. La query viene stabilita una tantum ed utilizzata per definire la view. Una volta definita la view essa può essere referenziata un numero indefinito di volte negli statement SELECT. La sintassi prevista per definire ed utilizzare le view è la seguente...
create view view_name(col1_name, col2_name, ...) as select ... from ... where ...
...per poi farne uso ad esempio come...
select tabella.colonna, view_name.col1_name from tabella, view_name where ...
La table expression è rappresentata da una sub query che definisce dinamicamente, ed in modo del tutto volatile, una sorta di tabella derivata che può essere utilizzata nello statemente SELECT (entro la clausola FROM) al pari di una view. Mentre la view, una volta definita, può essere utilizzata indefinitamente, una table expression è una semplice ricerca che ha valenza solo ed esclusivamente nell'ambito dello statement SELECT in corso di elaborazione. La sintassi prevista per la dichiarazione e l'utilizzo di una table expression in ricerca è la seguente...
select tabella.colonna, t_exp.col1 from tabella, (select ... from ... where...) as t_exp(col1, ...) where ...
Come estensione della table expression, la common table expression prevede la definizione di una sorta di view temporanea che precede la dichiarazione dello statement SELECT che può poi far uso di tale view. La sintassi per la dichiarazione e l'utilizzo di una common table expression in ricerca è la seguene...
whit c_t_exp(col1, col2, ...) as (select ... from ... where...) select tabella.col, c_t_exp.col2 from tabella, c_t_exp where ...
Nell'implementazione dell'interprete SQL per eXtraWay nessuna delle 3 forme precedentemente descritte è stata effettivamente implementata. La prima prevede la definizione di una sorta di ricerca frequente, funzionalità pienamente supportata da eXtraWay ma che non si è ritenuto di dover ancora implementare. Per quanto concerne il secondo ed il terzo caso essi si avvicinano maggiormente al concetto di raffinamento esistente per il motore eXtraWay quindi s'è deciso di implementare una variante delle sintassi indicate per perseguire esattamente quest'obiettivo.
Compiere quanto detto consiste nell'implementare una via di mezzo tra una table expression ed una common table expression. Compiere un raffinamento, infatti, consiste nel compiere una ricerca e, conseguentemente, effettuare una restrizione della ricerca compiendo sul subset da essa identificato un ulteriore ricerca. La formula somiglia quanto più alla common table expression ma per motivi tecnici essa è stata realizzata seguendo ed adeguando alle esigenze eXtraWay la sintassi della table expression.
Com'è stato evidenziato precedentemente, la definzione della table expression prevede che essa venga identificata da uno statement SELECT direttamente entro la clausola FROM dello statement SELECT che potremmo definire il più esterno. Avendo scelto di non consentire direttamente la nidificazione delle SELECT (operazione per altro realizzabile in futuro senza particolari impatti) la soluzione più naturale è stata quella di sostituire la SELECT più interna con l'identificativo della selezione che da essa deriva. Tale identificativo è rappresentato da una sequenza di caratteri che inizia, per definizione, col carattere 3. Questa caratteristica fa si che il nome di tale identificativo non risulti un nome di tabella valido. Esso va quindi racchiuso tra doppi apici per essere sintatticamente accettabile. Per semplificare l'utilizzo di questo identificativo, ad esso può essere affinacato uno 'shortname' per messo dell'operatore AS.
Il seguente esempio chiarirà l'uso che si è previsto di fare di questa forma di raffinamento. Come detto si deve prima compiere una selezione. Essa può essere effettuata sia nel linguaggio nativo eXtraWay che con uno statement SQL. In questo secondo caso il comando inviato al server deve specificare che si richiede un elenco di unità informative, compatibile con il formato di eXtraWay, e non la produzione della tabella temporanea altrimenti calcolata. La nostra ricerca, quindi, da luogo all'identificativo. Diciamo ad esempio che la ricerca sia...
select * from comuni where comuni.provincia='Bologna'
Come detto più volte, il risultato che possiamo gestire è un identificativo di selezione e non una tabella temporanea. Ne consegue che quello che si deve ottenere risulterà di fatto indipendente da quali colonne vengono selezionate.
L'operazione precedentemente descritta ci da un file di selezione eXtraWay identificato, ad esempio, come 3sefe096013a02
.
un possibile uso di questo identificatore di selezione, sotto forma di table expression in uno statement SELECT potrebbe quindi essere il seguente...
select rubrica.nome, view.regione
from rubrica, "3sefe096013a02" as view
where rubrica.cap=view.cap and view.cap>40120
La clausola WHERE esprime la condizione secondo la quale vengono selezionati i record. Le condizioni riguardano i valori assunti dalle colonne o espressioni booleane tra colonne. In particolare sono accettati:
Nella clausola WHERE non sono accettate, nell'attuale implementazione, le forme:
La clausola ORDER BY esprime la condizione secondo la quale vengono ordinati i record selezionati. Le condizioni riguardano colonne delle tabelle selezionate e consentono ordinamenti ascendenti e discendenti. Viene quindi accettata una o più forme "'nome colonna' [asc|desc]" separate tra loro da una virgola.
Per venire incontro a diverse tipologie di esigenze esistono due diversi stili di input della richiesta di selezione e, conseguentemente, due diversi stili di output.
Di fatto due sono le possibili esigenze:
Corrispondentemente ci sono due tipi di possibili richieste:
Questo tipo d'operazione è certamente la più semplice ma, al contempo, quella che offre meno possibilità. Sarà sufficiente esprimere nella frase di ricerca eXtraWay di una comune operazione di ricerca uno statement SQL completo di ogni sua parte e che figuri - in testa, in coda o in qualsiasi altra posizione - il modificatore "[?SQL]".
Il server provvederà a rimuovere tale modificatore ed eseguire lo statement espresso producendo un file di selezione in tutto e per tutto equivalente a quelli ottenibili con le comuni ricerche in linguaggio nativo eXtraWay. Ovviamente, non potendo rappresentare in questo modo dati composti provenienti da tabelle diverse, questa modalità ha delle restrizioni.
La sola vera restrizione si ha per il fatto che le colonne selezionate DEVONO
appartenere tutte alla stessa tabella. Se così non fosse, la richiesta produrrebbe un errore sintattico.
Lo statement può quindi coinvolgere colonne di tabelle differenti e può compiere join ed ordinamenti facendo uso di tali colonne a patto che selezioni colonne di una sola tabella.
assolutamente
ininfluente
in quanto vengono selezionate intere Unità Informative e non delle singole righe estratte da esse. A tal fine si suggerisce di selezionare una colonna sola per ridurre il carico di lavoro del server che, vista la tipologia dell'esito della selezione, sarebbe in grossa parte inutile qualora si selezionino numerose colonne. In presenza di più tabelle coinvolte la richiesta di colonne selezionate non deve essere effettuata su '*' ne su colonne appartenenti a diverse tabelle.Questo tipo di operazione è la più completa e versatile. Consente di ottenere risultati in tutto e per tutto equivalenti a quelli ottenibili con la Simulazione di una ricerca eXtraWay, seguendo le stesse identiche restrizioni, ma consente anche di rappresentare la tabella temporanea esito della Select in forma XML. In essa saranno riconoscibili le righe e le colonne selezionate e se ne potrà dare una corretta rappresentazione esteriore.
Il comando va inviato al server per mezzo di uno dei comandi XML resi disponibili. In particolare il comando in esame è il comando '0x0d'. La possibilità di ottenere un file di selezione standard anche in questo caso si ottiene esplicitando il bit '1'.
La forma del comando è:
<?xml version="1.0" encoding="windows1252"?> <cmd c="xd" bits="0"> <bst> ...Statement SQL... </bst> </cmd>
La forma della risposta sarà:
<?xml version="1.0" encoding="utf-8" ?> <rsp ack="1" e="0"> <sqltab name="tabella"> <!-- SQL Statement: ... --> <sqlcolumns cols="4" rows="299"> <sqlcomumn name="colonna_1" /> <sqlcomumn name="colonna_2" /> <sqlcomumn name="colonna_3" /> <sqlcomumn name="colonna_4" /> </sqlcolumns> <sqlrow> <cell>Valore riga 1 colonna 1</cell> <cell>Valore riga 1 colonna 2</cell> <cell>Valore riga 1 colonna 3</cell> <cell>Valore riga 1 colonna 4</cell> </sqlrow> <sqlrow> <cell>Valore riga 2 colonna 1</cell> <cell>Valore riga 2 colonna 2</cell> <cell>Valore riga 2 colonna 3</cell> <cell>Valore riga 2 colonna 4</cell> </sqlrow> ... <sqlrow> <cell>Valore riga n colonna 1</cell> <cell>Valore riga n colonna 2</cell> <cell>Valore riga n colonna 3</cell> <cell>Valore riga n colonna 4</cell> </sqlrow> </sqltab> </rsp>
Ecco di seguito alcuni esempi si statement SQL di ricerca accettate dal server.
select xcrwl_Document.titolo, xcrwl_Target.t_nome_target, xcrwl_Target.percorso_http, xcrwl_Target.percorso from xcrwl_Target, xcrwl_Document where xcrwl_Target.timeout between 100 and 200 and xcrwl_Target.t_nome_target=xcrwl_Document.d_nome_target
La Select non può dar luogo ad un file di selezione in quanto seleziona colonne da tabelle diverse.
select struttura_esterna.struest_nome,
persona_esterna.persest_cognome,
persona_esterna.persest_nome,
persona_esterna.persest_matricola
from persona_esterna,
struttura_esterna,
comune
where struttura_esterna.struest_coduff = persona_esterna.persest_appartenenzacoduff and
struttura_esterna.struest_indirizzocomune = comune.comuni_nome and
comune.comuni_regione = 'lazio'
Anche quest'espressione non può dar luogo ad un file di selezione in quanto seleziona colonne di tabelle diverse. Si compiono Join tra 3 tabelle differenti selezionando in fine colonne solo da 2 di esse. Tutta la condizione di Join è espressa nella clausola WHERE
.
select struttura_esterna.struest_nome,
persona_esterna.persest_cognome,
persona_esterna.persest_nome,
persona_esterna.persest_matricola
from persona_esterna join struttura_esterna join comune
on struttura_esterna.struest_coduff = persona_esterna.persest_appartenenzacoduff
on struttura_esterna.struest_indirizzocomune = comune.comuni_nome
where comune.comuni_regione = 'lazio'
Fondamentalmente identico all'esempio precedente ma con l'espressione delle clausole di join espresse sotto forma di uguaglianza dei valori di colonne di tabelle diverse direttamente nella clausola FROM
. Nella clausola WHERE
viene espressa l'unica condizione non altresì esprimibile.
select struttura_esterna.struest_nome,
persona_esterna.persest_cognome,
persona_esterna.persest_nome,
persona_esterna.persest_matricola
from comune, persona_esterna join struttura_esterna
on struttura_esterna.struest_coduff = persona_esterna.persest_appartenenzacoduff
where struttura_esterna.struest_indirizzocomune = comune.comuni_nome and
comune.comuni_regione = 'lazio'
Rifacendoci ancora una volta agli esempi precedenti abbiamo la stessa identica ricerca nella quale viene espresso uno dei due Join tra colonne nella clausola FROM
e l'altro nella clausola WHERE
unitamente alla condizione su un particolare valore della colonna comuni_regione
.
select struttura_esterna.struest_nome,
persona_esterna.persest_cognome,
persona_esterna.persest_nome,
persona_esterna.persest_matricola
from comune, struttura_esterna left join persona_esterna
on struttura_esterna.struest_coduff = persona_esterna.persest_appartenenzacoduff
where struttura_esterna.struest_indirizzocomune = comune.comuni_nome and
comune.comuni_regione = 'lazio'
order by struttura_esterna.struest_nome,
persona_esterna.persest_cognome
Condizione di ricerca derivata dalle precedenti ma composta con un Left
Join
. L'esito della selezione viene poi ordinato in base alle colonne espresse.
select se.struest_nome,
pe.persest_cognome,
pe.persest_nome,
pe.persest_matricola
from comune, persona_esterna as pe right join struttura_esterna as se
on pe.persest_appartenenzacoduff = se.struest_coduff
where se.struest_indirizzocomune = comune.comuni_nome and
comune.comuni_regione = 'lazio'
Condizione di ricerca derivata dalle precedenti ma composta con un Right
Join
. Alla ricerca viene applicata la clausola AS
per semplificarne la sintassi
Tutti gli esempi, da 2 a 6, possono condurre alla produzione di un semplice file di selezione - che quindi fa riferimento alle Unità Informative, a patto che le colonne selezionate appartengano ad una sola tabella. Privando ognuno di quegli esempi della selezione, ad esempio, della colonna struttura_esterna.struest_nome
il gioco è fatto!
Si fa notare, però, che il numero di documenti selezionati nei suddetti esempi potrebbe non corrispondere al numero delle righe selezionate nella tabella temporanea esito della select in quanto lo statement SQL può prevedere condizioni di right join o left join che conducono a selezionare, ad esempio, solo colonne di una data tabella. Se le colonne richieste, al termine della select, non appartengono a quella tabella, il numero di documenti che il server introduce nella selezione prodotta può risultare inferiore al numero di righe che si selezionerebbero richiedendo il rendering della tabella XML dei risultati.
Quanto detto vale anche in presenza di ordinamento che dovesse coinvolgere colonne di tabelle non selezionate.