Al pari delle funzionalità di ricerca, non tutta la panoramica della sintassi SQL è accettata dal Server eXtraWay. Se in parte ciò è dovuto al fatto che eXtraWay Server non è un DB Relazionale, in buona parte la limitazione all'utilizzo viene fatta perché solo un insieme significativo di funzionalità è effettivamente sensato per i fruitori di un Native XML DBMS.
La prima è più significativa limitazione, che dal punto di vista di eXtraWay Server è altresì un pregio, è il fatto che esiste un legame particolare ma non stringente tra le Tabelle così come vengono intese nel linguaggio SQL e le Unità Informative di eXtraWay.
Se è vero che si fa corrispondere una tabella
ad un'unità
informativa
, non c'è alcun rapporto, alcun legame stringente tra i canali di ricerca dichiarati nel file nomearchivio.conf.xml e le colonne
appartenenti alla tabella
.
In altri termini, in un DB Relazionale gestito via SQL, si deve innanzitutto creare la tabella
desiderata dichiarando la natura di tutte le colonne che la compongono e le singole caratteristiche di ogni colonna
. Nel nostro caso ciò non ha molto senso in quanto eXtraWay Server non impone significative limitazioni alla composizione di un'unità
informativa
se non in presenza di una precisa DTD che la identifichi. In generale, comunque, non si può dire che solo i canali
di
ricerca
dichiarati nel file nomearchivio.conf.xml siano valide colonne
per la rappresentazione relazionale che il linguaggio SQL consente di dare agli archivi eXtraWay.
In aggiunta a quanto detto vanno presi in considerazione gli alias dei canali di ricerca. Il supporto al linguaggio SQL è stato implementato in modo da usufruire di tali alias se disponibili ma di poterne fare a meno quanto più possibile per semplificare al massimo la configurazione di un archivio che si voglia gestire direttamente via SQL.
In sintesi, quindi, ogni tabella
SQL viene fatta corrispondere ad un'unità
informativa
e viene riconosciuta ed identificata per mezzo del nome del suo primary
node
element
.
Ogni colonna
viene fatta corrispondere ad un canale di ricerca, esplicito o implicito, sulla base del nome dell'alias, se definito, ovvero del nome dell'elemento o dell'attributo, diretti figli del primary
node
element
.
Qualora siano indicati nell'apposita area di configurazione degli alias di canali di ricerca l'assunto che viene fatto è il nome dell'alias corrisponda a...
<nome tabella>.<nome colonna>
... ovvero a...
<nome colonna>
...nel caso in cui tale alias non possa essere frainteso con altri di altre tabelle
.
Come detto, se tali alias non esistono, il nome della tabella
ed al suo interno della colonna
vengono fatti corrispondere ai canali...
XML,/<nome tabella>/<nome colonna>
...ovvero a...
XML,/<nome tabella>/@<nome colonna>
Gli esempi successivi chiariranno meglio gli aspetti di questo rapporto tabelle
+ colonne
-> primry
node
element
+ nome
canale
In merito alle operazioni di inserimento il formato accettato da eXtraWay Server non consente di sottintendere le colonne
che compongono una tabella
, sulla scorta di quanto detto nell'introduzione. Ne deriva che una sintassi come la seguente...
insert into <nometabella> values(<val1>, <val2>,..., <valN>)
...non sia una sintassi ammissibile. La richiesta è che ogni colonna
della tabella
nella quale si intende effettuare l'inserimento venga dichiarata preventivamente con la sintassi...
insert into <nometabella>(<col1>,<col2>,...,<colN>) values(<val1>, <val2>,..., <valN>)
L'inserimento di nuove
righe
in una tabella
non è consentito sulla base dell'esito di una Select. In altri termini la sintassi...
insert into <nometabella> select <clausola articolata di ricerca>
...non è una sintassi valida.
L'espressione dei valori dev'essere racchiusa tra singoli apici in caso di stringhe che possono contenere caratteri illegali per la sintassi SQL. Per ogni altro valore numerico i singoli apici non sono richiesti (ma possono essere usati). In sostanza, eXtraWay Server non fa attualmente alcun distinguo sulla tipologie di canale che deve ospitare un valore. Simili verifiche verranno effettuate con le successive versioni.
Vedremo in generale che le sintassi composite non sono attualmente gestite da eXtraWay Server.
Al pari delle operazioni di inserimento, anche le operazioni di modifica non ammettono l'uso di sintassi di ricerca composite. Non è quindi possibile identificare le righe
di una tabella
dalle quali isolare le colonne
da modificare sulla base di una Select che coinvolga tabelle
diverse da quella in fase di modifica. Le condizioni di Join non sono previste nella sintassi della clausola Update ma tale comportamento potrebbe essere ottenuto con una clausola Exists nella fase di ricerca che potrebbe nidificare una Select. Tale sintassi non viene attualmente riconosciuta.
Le restrizioni originariamente esistenti sulle modalità di intervento sui valori delle colonne ove si intende operare una modifica sono state almeno in parte abbattute. Ora è possibile esprimere costanti, come in passato, ma anche valori derivanti da operazioni matematiche e funzioni generiche. In alcuni casi è possibile anche ammettere il concetto di default
.
Vediamo nel dettaglio come è possibile operare.
La modifica può avvenire sulla base di una sintassi...
update <nome tabella> set <col1>=<val1>, <col2>=<val2>, ..., <colN>=<valN> [where <clausola di rierca>]
...dove i valori val1
, val2
ecc. ecc. corrispondono ad una costante, a null
, ad un'operazione matematica o funzione o, dove previsto, dal valore di default.n
Le modalità previste sono:
colonne
o valori
. La somma è ammessa per stringhe, date e numeri. La sottrazione solo per date e numeri mentre moltiplicazione e divisione esclusivamente per numeri. Le operazioni compiute sulle date, somme e sottrazioni, si intendono basate sull'unità di misura rappresentata dai giorni.default
. Questa modalità è consentita solo ed esclusivamente per colonne che rappresentino degli attributi nella struttura XML dell'archivio ed ai quali sia associato una DTD che dichiara un valore di default
per tale attributo.La cancellazione dev'essere considerata al pari di un sottinsieme delle funzionalità della modifica e quindi rispetta le stesse regole e subisce le stesse restrizioni. Ne deriva che anche in questo caso la clausola di ricerca, se espressa, non può nidificare una Select articolata in grado di compiere Join tra tabelle diverse.
La sintassi ammessa è quindi...
delete <nome tabella> [where <clausola di ricerca>]
I seguenti esempi chiariranno meglio quanto indicato nelle precedenti sezioni e daranno idea di cosa sia possibile (ed in particolare di cosa NON sia possibile) fare.
Gli esempi saranno più chiari se letti nell'ordine (Inserimento, Modifica e Cancellazione).
Come detto, gli inserimenti non consentono di sottintendere i nomi delle colonne
. Ne consegue che esse devono sempre essere esplicitate.
Immaginando di partire da un archivio vuoto, completamente privo di unità
informative
, effettuando un'operazione come la seguente...
insert into rubrica(nome, cognome, indirizzo, cap, reparto, mansione, prefisso, n_tel) values('Roberto', 'Tirabassi', 'Via Speranza 35', 40068, 'Sviluppo Motore', 'Programmatore', 051, '450844')
...si ottiene l'inserimento in questa base dati neutra, di un unità
informativa
composta come segue...
<rubrica> <nome>Roberto</nome <cognome>Tirabassi</cognome> <indirizzo>Via Speranza 35</indirizzo> <cap>40068</cap> <reparto>Sviluppo Motore</reparto> <mansione>Programmatore</mansione> <prefisso>051</prefisso> <n_tel>450844</n_tel> </rubrica>
... impostando un elemento per ogni colonna
dichiarata. Per chiarire quanto detto più volte, la stessa operazione espressa sottointendendo le colonne
...
insert into rubrica values('Roberto', 'Tirabassi', 'Via Speranza 35', 40068, 'Sviluppo Motore', 'Programmatore', 051, '450844')
...non viene considerata valida e provoca errore.
L'inserimento precedentemente eseguito prevede la dichiarazione (sottintesa se assente nel file nomearchivio.conf.xml) di un primary
node
denominato 'rubrica' e dei canali di ricerca corrispondenti.
Un risultato più accurato si può ottenere impostando gli alias più opportuni.
Di seguito vediamo un pezzo di file nomearchivio.conf.xml che si potrebbe prestare a spiegare quali potenzialità sono disponibili...
<primary_node ud_name="rubrica" ud_container="listof_rubrica"> <key name="XML,/rubrica" attr_collate="#cogn_nome:$@cognome@ $$@nome@$"/> <key name="XML,/rubrica/@nome" /> <key name="XML,/rubrica/@cognome" /> </primary_node> <hw_fields> <search_alias search_name="rubrica.nome" search_key="xml,/rubrica/@nome/"/> <search_alias search_name="cognome" search_key="xml,/rubrica/@cognome/"/> <search_alias search_name="rubrica.cognome_e_nome" search_key="xml,/rubrica/#cogn_nome/"/> </hw_fields>
Facendo uso di un simile file di configurazione l'inserimento effettuato prima porterebbe all'inserimento di un documento conformato come segue...
<rubrica nome="Roberto" cognome="Tirabassi"> <indirizzo>Via Speranza 35</indirizzo> <cap>40068</cap> <reparto>Sviluppo Motore</reparto> <mansione>Programmatore</mansione> <prefisso>051</prefisso> <n_tel>450844</n_tel> </rubrica>
...consentendo di comporre anche una chiave composita cogn_nome
che può essere usata esclusivamente in ricerca e mai in inserimento o modifica.
Poiché gli inserimenti possono essere fatti anche per un insieme incompleto di colonne
il documento che scaturisce dall'inserimento...
insert into rubrica(cognome, nome, mansione, reparto) values('Ritelli', 'Walter', 'Programmatore', 'Sviluppo Java')
...produce un documento composto come segue...
<rubrica cognome="Ritelli" nome="Walter"> <mansione>Programmatore</mansione> <reparto>Sviluppo Java</reparto> </rubrica>
Come si può notare l'ordine degli elementi e degli attributi non viene forzato non essendoci una DTD a regolare l'unità
informativa
. Ciò non influenza l'alimentazione dei canali di ricerca ne la possibilità di rappresentare in righe
e colonne
il contenuto di una tabella
.
Al momento di compiere le ricerche l'indicazione della colonna
cognome nella tabella
rubrica, condurrà all'alias di ricerca più opportuno in quanto compito del server è stabilire quali combinazioni dei nomi di tabella
e colonna
vadano usati. Se la ricerca viene effettuata per rubrica.cognome sarà l'alias cognome, se pure privo del prefisso rubrica, ad essere prescelto.@ E' comunque buona norma, per le applicazioni votate all'SQL, di indicare gli alias nella forma 'tabella.colonna'.
Va da se che, qualora alcuni canali siano sottintesi nel file di configurazione d'archivio, il trattamento degli attributi non potrebbe avere luogo in modo corretto. Per chiarire meglio questo importante concetto si prenda in esame l'esempio basato sulla struttura dell'archivio ACL utilizzato, nell'applicazione DocWay, disponibile nel suggessivo pargrafo dedicato alle modifiche. Quanto indicato si presta anche alla fase di inserimento ma risulta più chiaro nella forma di modifica.
La modifica impone limiti sulla tipologia dei valori impostati e sulla nidificazione di clausole Select nella clausola di ricerca.
Per meglio intenderci, immaginando di avere a disposizione anche una tabella dei comuni con vari dati al suo interno (Regione, provincia, comunque, cap ed altri), la modifica effettuata con la seguente sintassi...
update rubrica set prefisso=051 where exists (select cap from rubrica, comuni where rubrica.cap=comuni.cap and comuni.provincia='Bologna')
...non verrebbe accettata in quanto nidifica una clausola Select nella clausola Where, condizione attualmente non accettata.
Per esprimere una modifica lecita, si possono dare comandi come i seguenti...
update rubrica set reparto='Laboratiorio ed Amministrazione', prefisso=051 where cap like '40%'
...ovvero...
update rubrica set mansione='Sviluppo Motore', cap=null where cognome_e_nome = 'Tirabassi Roberto' OR cognome_e_nome = 'Ritelli Walter' OR cognome_e_nome = 'Morara Massimo'
...o ancora...
update rubrica set cap=40139, indirizzo='Via Indipendenza 10', mansione='Amministratori Delegati'
... su tutte le righe
della tabella
. In tempi più recenti sono state introdotte altre modalità di update che comprendono operatori matematici e funzioni. Vediamo alcuni esempi...
update scadenze set data_scadenza=data_scadenza+7 where cliente = '...'
Con questa operazione abbiamo posticipato di 7 giorni (i giorni sono le unità di misura negli interventi sulle date) la scadenza dei pagamenti di un dato cliente.
update stipendi set importo=importo * 100 / 193627, valuta='Euro' where pagamento='attivo' and valuta='Lire'
Con quest'operazione abbiamo convertito in Euro gli stipendi pagati.
Si deve però far notare che la mappatura tra i canali di ricerca dell'archivio ed i corrispondenti alias è fondamentale per compiere un corretto inserimento o modifica.
Qualora ci siano, ad esempio, attributi sottintesi essi non verrebbero correttamente trattati. Si veda il successivo esempio basato sulla struttura dell'archivio ACL usato, tra le altre, nell'applicazione DocWay.
L'archivio ACL prevede, al suo interno, un tipo di unità informativa che riguarda i comuni. Per tale unità informativa sono stati previsti diversi canali di ricerca. Tra essi appare anche il cap del comune in esame per il quale non è stato costituito un alias di ricerca (di fatto il cap è annoverto tra i canali che appartengono alla ricerca globale, campo chioccola) ma quel che è più importante è che non è stata dichiarata la chiave nell'apposita sezione dedicata all'unità informativa. A tale canale, quindi, sono state assegnate le caratteristiche di default evidentemente ritenute sufficienti.
Immaginiamo di selezionare un comune con la ricerca che segue:
select * from comune where comune.COMUNI_NOME=' PONTE NUOVO'
Il risultato sarà il comune di Ponte Nuovo in provincia di Ravenna. Tale comune ha cap 48100, prefisso 0544, provincia RA ed altre caratteristiche. Volendo procedere alla modifica dei dati di questo record possiamo, ad esempio, impostare un nuovo cap ed una nuova provincia con la sintassi...
update comune set cap='49200', COMUNI_PROV='NA' where comune.COMUNI_NAME=' PONTE NUOVO'
...ma come si può notare, non avendo un alias di ricerca per il canale cap, abbiamo tentato di dichiararlo col suo semplice nome. La mappatura che si avvale del file di configurazione dell'archivio non trova una corrispondenza perchè la chiave non è configurata e quindi assume che cap sia il nome di un elemento (condizione di default). In tal modo, il valore dell'attributo cap rimane invariato mentre viene introdotto un elemento cap indesiderato.
Se ripartiamo dal documento originario e proviamo nuovamente indicando il nome del canale preceduto dalla @ che gli compete per essere identificato come attributo, la chiocciola viene ignorata ed otteniamo lo stesso risultato. Per contro, il canale inerente la provincia viene modificato con successo.
Stesso comportamento corretto si ha nel caso si voglia modificare il prefisso telefonico con la sintassi...
update comune set COMUNI_PROV='BA', COMUNI_PREFISSO=0555 where comune.COMUNI_NOME=' PONTE NUOVO'
Quanto mostrato da particolare evidenza al fatto che volendo compiere operazioni di inserimento o modifica su una struttura libera, ovvero non legata ad una struttura applicativa che la dichiari nel dettaglio, siamo liberi di fare quello che riteniamo più opportuno in quanto la forma data al frammento XML prodotto sarà tanto semplice quanto efficacie. Se, per contro, come nel caso esposto, abbiamo a che fare con una struttura ben precisa, è indispensabile non estraniarsi da essa per non influenzare negativamente l'applicazione che ne fa uso e quindi ogni intervento (inserimento e modifica in particolare) devono essere effettuati solo ed esclusivamente sulla base di canali correttamente dichiarati nel file di configurazione dell'archivio e possibilmente associati ad un preciso alias di ricerca.
A completamento di quanto detto si agiunge che la natura delle diverse colonne (alfanumerica, numerica, data) viene determinata sulla base della tipologia di indicizzazione espressa nel file di configurazione d'archivio. Anche questo, quindi, invita a compiere sempre la dichiarazione delle chiavi XML cui si intende far corrispondere una colonna
evitando quanto più possibile le colonne sottintese.
Anche in questo caso la cancellazione rappresenta una sorta di sottinsieme delle funzionalità della modifica e quindi non ammette sintassi come la seguente...
delete from rubrica where exists (select cap from rubrica, comuni where rubrica.cap=comuni.cap and comuni.provincia='Bologna')
...mentre sono accettate sintassi quali...
delete from rubrica where nome='Roberto'
...o ancora...
delete from ore_settimanali
...per rimuovere tutte le righe
di una tabella
.