Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
La guida completa
Dal catalogo McGraw-Hill:
J. Price, Oracle Database 10g SQL
M. Abbey et al., Guida a Oracle Database 10g
K. Loney, G. Koch, Guida completa Oracle 9i
R.G. Freeman, Oracle 9i Le nuove proprietà
B.D. Brown, Oracle 9i Sviluppo Web
K. Loney, M. Theriault, Il manuale Oracle 9i DBA
M. Abbey et al., Guida a Oracle 9i
K. Loney, M. Theriault Il manuale Oracle 8i DBA
M. Abbey et al., Guida a Oracle 8i
A. Adkoli, R. Velpuri, Oracle8 Backup e Recovery
A. Adkoli, R. Velpuri, Oracle8 per NT
G. Koch, K. Loney, Guida completa Oracle8
K. Loney, Il manuale Oracle8 DBA
○ ○ ○ ○ ○
KEVIN LONEY
LA GUIDA COMPLETA
ORACLE
DATABASE 10G
McGraw-Hill
Milano New York San Francisco Washington, D.C. Auckland Bogotá Lisbon London
Madrid Mexico City Montreal New Delhi San Juan Singapore Sydney Tokyo Toronto
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
EDITOR: Maria Grazia Viscito
PRODUZIONE: Donatella Giuliani
REALIZZAZIONE: Studio GSG – Traduttori associati, Lesa (NO)
TRADUZIONE: Stefano Gubian, Valeria Cardano
STAMPA: Cromografica Europea, Rho (MI)
Ogni cura è stata posta nella creazione, realizzazione, verifica e documentazione dei programmi
contenuti in questo libro, tuttavia né l’Autore né The McGraw-Hill Companies, S.r.l. Publishing
Group Italia possono assumersi alcuna responsabilità derivante dall’implementazione dei pro-
grammi stessi, né possono fornire alcuna garanzia sulle prestazioni o sui risultati ottenibili dal-
l’utilizzo dei programmi. Inoltre, date le caratteristiche intrinseche di Internet, non sono respon-
sabili per eventuali variazioni negli indirizzi o nei contenuti dei siti riportati. Lo stesso dicasi per
ogni persona o società coinvolta nella creazione, nella produzione e nella distribuzione di questo
libro.
Nomi e marchi citati nel testo sono generalmente depositati o registrati dalle rispettive case pro-
duttrici.
Printed in Italy
1234567890CROLIL098765
ISBN 88 386 4408-X
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Indice
Introduzione XV
PARTE QUAR
PARTE TA ● PL/SQL
QUART 485
PARTE QUINT
PARTE A ● DA
QUINTA TABASE RELAZIONALI A OGGETTI
DAT 553
PARTE SEST
PARTE A ● JA
SESTA VA IN ORACLE
JAV 625
PARTE OTT
PARTE AVA ● GUIDE
OTTA 683
L
a documentazione di Oracle è completa e assai voluminosa,
tanto da comprendere diversi CD-ROM. Oracle Database 10g: La guida completa è il primo
libro che raccoglie tutte le principali definizioni, i comandi, le funzioni, le funzionalità e i pro-
dotti legati a Oracle in un unico volume, una grande guida di riferimento che tutti gli utenti e gli
sviluppatori dovrebbero tenere a portata di mano.
Le persone cui si rivolge questo libro possono essere distinte in tre categorie, descritte di
seguito.
■ Utenti finali di Oracle È possibile utilizzare Oracle per operazioni estremamente semplici
come inserire dati ed eseguire report standard, ma in questo modo non se ne sfruttano le
potenzialità; è come acquistare una potente macchina sportiva e poi trainarla con un cavallo. Con
il materiale introduttivo fornito nelle prime due parti di questo libro, anche un utente finale quasi
del tutto privo di esperienza nell’elaborazione dei dati può divenire un piccolo esperto di Oracle,
in grado di generare report con indicazioni in italiano, guidare gli sviluppatori nella creazione di
nuove funzionalità e migliorare la velocità e la precisione in un’azienda. Il linguaggio di questo
libro è semplice e chiaro, privo di termini gergali; le conoscenze di computer o database richieste
come presupposto sono assai ridotte. Il libro guida i principianti a diventare degli esperti con una
struttura semplice da seguire e numerosi esempi concreti.
■ Sviluppatori che si avvicinano a Oracle per la prima volta Con tutti i volumi di cui è
dotata la documentazione di ORACLE, trovare un comando o un concetto importante può rive-
larsi un’operazione molto lunga. Questo libro cerca di fornire un metodo meglio organizzato e
più efficiente di apprendere i fondamenti del prodotto. Lo sviluppatore che non conosce Oracle
viene condotto in una rapida panoramica sui concetti di base, accompagnato nelle aree più com-
plesse, informato di possibili incomprensioni circa il prodotto e lo sviluppo di database relazionali,
guidato con principi chiari per lo sviluppo di applicazioni.
■ Sviluppatori esperti in ORACLE Come per tutti i prodotti di ampio respiro e molto sofi-
sticati, esistono importanti aspetti riguardo ai quali vi è poca o nessuna documentazione. La
conoscenza giunge con l’esperienza, ma spesso non viene trasferita agli altri. Questo libro ap-
profondisce molti di questi argomenti, comprese le nuove caratteristiche, come le opzioni
flashback, Data Pump e molti altri. Nel testo sono inoltre chiariti molti aspetti che spesso sono
oggetto di confusione e suggeriti rigorosi principi guida per affrontare lo sviluppo delle applica-
zioni e i problemi di progettazione e prestazioni.
XVI INTRODUZIONE
CONCETTI
DEI DATABASE
FONDAMENTALI
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 1
Opzioni dell’architettura
di Oracle Database 10g
O
racle Database 10g è un aggiornamento significativo rispetto
alle versioni precedenti di Oracle. Presenta infatti nuove caratteristiche che danno a sviluppatori,
amministratori di database e utenti finali un maggior controllo sulla memorizzazione, l’elabora-
zione e il recupero dei dati. In questo capitolo verranno messe in luce le caratteristiche fonda-
mentali dell’architettura di Oracle Database 10g, mentre i prossimi presenteranno analisi detta-
gliate delle nuove funzionalità, come il supporto per le espressioni regolari, le query di versione
flashback e Data Pump. Obiettivo di questo capitolo è presentare una panoramica di alto livello
delle capacità che è possibile sfruttare nelle applicazioni Oracle e fornire un’introduzione ai
capitoli che le descrivono.
Questo libro è suddiviso in otto parti.
La Parte prima è un’introduzione ai concetti fondamentali dei database e offre una descri-
zione generale delle opzioni di Oracle Database 10g, nonché le istruzioni necessarie per installa-
re il software Oracle, per creare o aggiornare un database e dei consigli utili per pianificare
l’implementazione delle applicazioni. In questi capitoli viene descritta la terminologia di base
che utenti e sviluppatori possono utilizzare per condividere concetti in modo coerente e intelli-
gente, al fine di garantire il successo di qualsiasi lavoro di sviluppo. Questo capitolo introduttivo,
insieme al Capitolo 4, si rivolge a sviluppatori e utenti finali di Oracle, mentre i Capitoli 2 e 3
sono destinati agli amministratori di database.
La Parte seconda, spiega la teoria e le tecniche dei sistemi di database relazionali con le
relative applicazioni, tra cui SQL (Structured Query Language) e SQL*Plus. Questa parte inizia
con un numero relativamente limitato di presupposti circa la conoscenza delle tecniche di elabo-
razione dei dati da parte del lettore e prosegue passo per passo fino a raggiungere argomenti
molto avanzati e tecniche complesse. Il testo è scritto ponendo molta attenzione all’uso di un
linguaggio chiaro e scorrevole, con esempi unici e interessanti ed evitando l’uso di termini gergali
o indefiniti. Questa parte è dedicata principalmente a sviluppatori e utenti finali che si accostano
a Oracle per la prima volta, o che necessitano di un rapido ripasso di alcune caratteristiche di
base. Vengono esaminate passo per passo le funzionalità di base di SQL e dello strumento per
query interattive di Oracle, SQL*Plus. Una volta completata questa parte, il lettore avrà una
conoscenza completa di tutte le parole chiave, le funzioni e gli operatori di SQL e sarà in grado
di produrre query complesse, creare tabelle, inserire, aggiornare ed eliminare dati in un database
Oracle.
La Parte terza si occupa di alcune opzioni avanzate, come i virtual private database, Data
Pump, la replica, l’indicizzazione del testo, le tabelle esterne e l’uso delle opzioni flashback, e si
rivolge a sviluppatori e amministratori di database. La maggior parte delle caratteristiche de-
4 CAPITOLO 1
scritte in questa parte non verranno impiegate direttamente dagli utenti finali, tuttavia le applica-
zioni a essi destinate possono essere basate su queste funzionalità.
La Parte quarta offre una trattazione di PL/SQL; tra gli argomenti presi in esame troviamo
un’analisi delle strutture PL/SQL, nonché dei trigger, delle stored procedure e dei package. Il
linguaggio viene trattato sia nella versione standard sia in quella dinamica nativa.
La Parte quinta è dedicata a un’ampia trattazione delle funzionalità orientate agli oggetti,
come i tipi di dati astratti, i metodi, le viste oggetto, le tabelle oggetto, le tabelle annidate, gli
array variabili e i LOB (Large OBject).
La Parte sesta si occupa invece delle funzionalità Java presenti nel database Oracle; questa
parte include un’introduzione generale alla sintassi di Java, oltre a capitoli su JDBC e sulle
stored procedure Java.
La Parte settima offre una descrizione generale di Real Application Cluster e dell’architettu-
ra per il grid computing disponibile in Oracle Database 10g.
La Parte ottava contiene diverse guide: al dizionario dati, all’ottimizzatore del database, a
Oracle Application Server, all’amministrazione dei database e all’implementazione di XML di
Oracle. Queste guide contengono un’introduzione generale alle aree che gli sviluppatori potreb-
bero aver bisogno di utilizzare nello sviluppo e nell’amministrazione delle loro applicazioni.
L’ultimo capitolo della Parte ottava è una guida di riferimento completa per il server Oracle,
che potrebbe costituire di per sé un intero libro. Le pagine introduttive sono molto utili per
comprendere meglio il testo. Questa parte contiene i riferimenti relativi alla maggior parte dei
comandi di Oracle, alle parole chiave, ai prodotti, alle funzionalità e alle funzioni, con ampi
riferimenti incrociati tra gli argomenti. Questa guida di riferimento è stata studiata per essere
consultata sia dagli utenti sia dagli sviluppatori di Oracle, ma richiede una certa familiarità con
i prodotti. Per sfruttare al meglio la guida è consigliabile leggere le pagine introduttive, che
spiegano in dettaglio gli argomenti trattati e mostrano come leggere il testo.
Il CD allegato al libro contiene il testo in versione elettronica, in modo che il lettore possa
portarlo con sé sul proprio computer, mentre la versione cartacea rimane nel proprio ufficio
oppure a casa. Il CD contiene inoltre le istruzioni per la creazione delle tabelle utilizzate nel
libro, insieme con quelle per l’inserimento dei dati. Per chiunque stia imparando Oracle, la
disponibilità di queste tabelle nel proprio ID, o in uno di esercizio, facilita notevolmente la
comprensione degli esempi.
Per consentire l’accesso alle tabelle, è possibile utilizzare viste che effettuano unioni e
aggregazioni, limitano il numero di righe restituite o modificano le colonne visualizzate. Le
viste possono essere di sola lettura o aggiornabili e possono fare riferimento a tabelle locali o
remote. L’accesso alle tabella può avvenire tramite i database link ed è possibile utilizzare i
sinonimi per mascherare la posizione fisica delle tabelle. Per maggiori informazioni sui database
link si rimanda al Capitolo 23; per ulteriori dettagli su viste e sinonimi, consultare il Capitolo 17.
Per mettere a punto gli accessi a queste tabelle, Oracle supporta molti tipi di indici, tra cui i
seguenti:
■ Indici B*-tree Un indice B*-tree è il tipo di indice standard disponibile in Oracle ed è
molto utile per la selezione delle righe che soddisfano un criterio di equivalenza o di intervallo.
La creazione degli indici avviene con il comando create index.
■ Indici bitmap Per le colonne che contengono alcuni valori unici, un indice bitmap può
migliorare le prestazioni delle query. Gli indici bitmap devono essere utilizzati solo quando il
caricamento dei dati avviene in modalità batch (come in molte applicazioni di data warehousing
o reporting).
■ Indici a chiave inversa Se ci sono problemi di conflitti di I/O durante gli inserimenti di
valori sequenziali, Oracle può invertire dinamicamente i valori indicizzati prima di memorizzarli.
■ Indici basati su funzioni Invece di indicizzare una colonna, come Nome, è possibile
indicizzare una colonna basata su funzione, come UPPER(Nome). L’indice basato su funzione
fornice all’ottimizzatore di Oracle delle opzioni aggiuntive per la selezione di un percorso di
esecuzione.
■ Indici partizionati È possibile partizionare gli indici per supportare le tabelle partizionate
o per agevolare la gestione degli indici. Le partizioni degli indici possono essere locali per le
partizioni delle tabelle o possono applicarsi globalmente a tutte le righe della tabella.
■ Indici di testo È possibile indicizzare valori di testo a supporto delle capacità di ricerca
potenziate, come l’espansione delle radici delle parole o la ricerca di frasi. Gli indici di testo
sono insiemi di tabelle e indici mantenuti da Oracle per supportare le esigenze delle ricerche
testuali complesse. Oracle Database 10g presenta diversi miglioramenti negli indici di testo che
ne semplificano l’amministrazione e la manutenzione.
Per ulteriori dettagli sui tipi di indice elencati qui (esclusi gli indici di testo) si rimanda ai
Capitoli 17 e 43; per gli indici di testo, fare riferimento al Capitolo 25.
Tablespace
Una tablespace è costituita da uno o più file di dati; un file di dati può far parte di una e una sola
tablespace. Oracle Database 10g crea almeno due tablespace per ciascun database, SYSTEM e
SYSAUX, a sostegno delle proprie esigenze di gestione interne. È possibile utilizzare i file
gestiti da Oracle (OMF, Oracle Managed Files) per semplificare la creazione e la manutenzione
dei file di dati.
OPZIONI DELL'ARCHITETTURA DI ORACLE DATABASE 10G 7
A partire da Oracle Database 10g è possibile creare un tipo speciale di tablespace, chiamata
tablespace grande, che può avere una dimensione di diverse migliaia di terabyte. Insieme agli
OMF, la gestione dei file di grandi dimensione fa in modo che la gestione delle tablespace risulti
completamente trasparente al DBA, il quale può gestire la tablespace come un’unita senza pre-
occuparsi della dimensione e della struttura dei file di dati sottostanti.
Se una tablespace viene designata come temporanea, la tablespace in sé è permanente; solo
i segmenti salvati in essa sono temporanei. Oracle utilizza le tablespace temporanee a supporto
delle operazioni di ordinamento, quali la creazione di indici e il processo di join. I segmenti
temporanei non devono essere memorizzati nelle medesime tablespace che ospitano gli oggetti
permanenti.
Le tablespace possono essere gestite a livello di dizionario o gestite localmente. In una
tablespace gestita a livello di dizionario, la distribuzione dello spazio viene registrata nel dizio-
nario dati, mentre in una tablespace gestita localmente (opzione predefinita in Oracle Database
10g), Oracle mantiene una bitmap in ciascun file di dati della tablespace per tenere traccia della
disponibilità di spazio. Solo le quote vengono gestite nel dizionario dati, riducendo così in modo
notevole i conflitti per le tabelle del dizionario dati.
Dati eliminati
Il concetto di cestino introdotto con Oracle Database 10g influisce sui requisiti di spazio neces-
sario per le tablespace e i file dei dati. In Oracle Database 10g quando una tabella viene elimina-
ta, lo spazio allocato per essa viene mantenuto per default; questo uso dello spazio è visibile
tramite la vista RECYCLEBIN del dizionario dati. Se si crea e si elimina una tabella due volte,
il cestino conterrà due copie della tabella. Benché questa architettura agevoli notevolmente il
recupero di tabelle cancellate erroneamente, può accrescere notevolmente lo spazio usato nel
database. Per rimuovere le voci obsolete dal cestino si utilizza il comando purge. Si consulti il
Capitolo 48 per la sintassi di questo comando.
8 CAPITOLO 1
Strutture programmatiche
Oracle consente di adottare una vasta gamma di metodi accesso programmatico. Il linguaggio
SQL, descritto in modo dettagliato in tutto il libro, è fondamentale per lo sviluppo di qualunque
applicazione. Tra gli altri metodi di accesso troviamo i seguenti:
■ PL/SQL Come descritto nella Parte quarta del libro, PL/SQL è un componente fondamen-
tale della maggior parte delle implementazioni di applicazioni. È possibile ricorrere a PL/SQL
per creare stored procedure e funzioni, che possono poi essere chiamate all’interno delle query.
Procedure e funzioni possono essere raccolte in package. È anche possibile dar vita a trigger,
indicando al database che misure adottare quando si verificano diversi eventi all’interno del
database. I trigger possono verificarsi durante eventi del database (come l’avvio di un database),
modifiche alle strutture (come i tentativi di eliminare delle tabelle) o modifiche a righe. In ogni
caso si utilizzerà PL/SQL per controllare il comportamento del database o dell’applicazione
quando si verifica l’evento che attiva il trigger.
■ SQL dinamico È possibile generare istruzioni SQL in fase di esecuzione e passarle a pro-
cedure che le eseguono tramite SQL dinamico. Fare riferimento al Capitolo 32.
■ SQL*Plus Come si vedrà in tutto il libro, SQL*Plus fornisce una semplice interfaccia per
il database Oracle. SQL*Plus può soddisfare delle necessità di reporting rudimentali, tuttavia è
più famoso per il suo supporto allo scripting. Esso fornisce un’interfaccia coerente per il recupero
dei dati dal dizionario dati e per la creazione di oggetti del database.
■ Java e JDBC Come si vedrà nella Parte sesta del libro, il supporto per Java e JDBC offerto
da Oracle consente di utilizzare Java al posto di PL/SQL per molte operazioni. È persino possi-
bile scrivere stored procedure basate su Java. Le capacità Java offerte da Oracle vengono amplia-
te e potenziate al rilascio di ogni nuova versione.
■ XML Come descritto nel Capitolo 47, è possibile utilizzare le interfacce XML di Oracle e
i tipi XML per consentire l’inserimento e il recupero dei dati tramite XML.
■ SQL e PL/SQL a oggetti È possibile utilizzare Oracle per creare e accedere a strutture
orientate agli oggetti, come tipi di dati definiti dagli utenti, metodi, oggetti LOB (Large OBject),
object table e tabelle nidificate. Fare riferimento alla Parte quinta.
OPZIONI DELL'ARCHITETTURA DI ORACLE DATABASE 10G 9
■ Data Pump Data Pump Import e Data Pump Export, entrambe introdotte in Oracle Database
10g, accrescono notevolmente la gestibilità e le prestazioni delle utility Import ed Export prece-
denti. Data Pump può essere impiegata per estrarre rapidamente dei dati e spostarli in diversi
database alterando lo schema e modificando le righe. Per dettagli sull’uso di Data Pump, si
rimanda al Capitolo 22.
■ SQL*Loader È possibile utilizzare SQL*Loader per caricare rapidamente dei file piatti
nelle tabelle Oracle. Un singolo file piatto può essere caricato in più tabelle con lo stesso
caricamento e le operazioni possono avvenire in parallelo. Fare riferimento al Capitolo 21.
■ Programmi e procedure esterni È possibile incorporare istruzioni SQL nei programmi
esterni, oppure è possibile creare librerie di procedure che in seguito vengono collegate a Oracle.
Fare riferimento al Capitolo 31.
■ UTL_MAIL UTL_MAIL è un package introdotto in Oracle Database 10g che consente a
uno sviluppatore di applicazioni PL/SQL di inviare e-mail senza dover sapere come usare lo
stack di protocollo SMTP sottostante.
Installazione
di Oracle Database 10g
e creazione di un database
I
l software per l’installazione di Oracle diventa sempre più faci-
le da usare a ogni versione, al punto che diviene difficile resistere alla tentazione di aprire la
scatola dei CD e iniziare immediatamente l’installazione. Questa soluzione può andare bene per
chi ha intenzione di sperimentare alcune delle nuove caratteristiche del database; se invece si
intende effettuare un’installazione corretta senza essere costretti a rimettere le mani sul proprio
lavoro dopo un mese, o persino a reinstallare, è necessaria una pianificazione accurata. Anche se
una descrizione dettagliata dell’installazione di Oracle Database 10g non rientra nelle finalità di
questo libro, verranno illustrate le basi di un’installazione di Oracle con Oracle Universal Installer
(OUI); verrà inoltre fornito un modello di base per l’esecuzione di un’installazione manuale del
database con il comando create database. In ogni caso, un’analisi completa della guida all’in-
stallazione per la propria piattaforma è un altro degli elementi chiave per una distribuzione del
database Oracle di successo.
NOTA Benché questo capitolo sia rivolto a chi si accosta all’amministrazione del
database, il processo di pianificazione dovrebbe coinvolgere utenti finali, sviluppatori di appli-
cazioni e amministratori di sistema in modo che la valutazione del carico di lavoro e dei requi-
siti di spazio sia più precisa possibile.
■ Selezionare il set di caratteri del database e un set di caratteri alternativo. Benché sia facile
lasciare le opzioni predefinite per il set di caratteri in fase di installazione, potrebbe essere neces-
sario considerare dove sono dislocati gli utenti del database e i loro requisiti linguistici. È possi-
bile cambiare i set di caratteri dopo l’installazione solo se il nuovo set è un sovrainsieme di
quello esistente.
■ Decidere la dimensione predefinita migliore per i blocchi del database. La dimensione di
blocco predefinita da DB_BLOCK_SIZE non può essere modificata in un secondo tempo senza
procedere alla reinstallazione del database. Si osservi che Oracle accetta più dimensioni di bloc-
co in un singolo database.
■ Pianificare la memorizzazione degli oggetti utente non SYSTEM in tablespace diverse da
SYSTEM. Accertarsi che tutti gli utenti senza qualifiche amministrative siano assegnati per
default a una tablespace diversa da SYSTEM.
■ Pianificare l’implementazione di Automatic Undo Management per rendere più agevole l’am-
ministrazione delle informazioni per l’annullamento delle transazioni.
■ Pianificare una strategia di backup e ripristino, decidendo le modalità e la frequenza di
backup necessarie per il database. Considerare l’impiego di più di un metodo per il backup del
database.
È fondamentale avere familiarità con un paio di siti Web fondamentali. Oracle Technology
Network (OTN), http://otn.oracle.com, offre una grande quantità di informazioni, come white
paper, strumenti gratuiti, codice di esempio e la versione online della rivista Oracle Magazine.
L’uso di OTN non comporta alcun costo, ma è richiesta la registrazione al sito.
L’acquisto di una licenza per il software di database Oracle è un buon punto di partenza, ma
un contratto di assistenza Oracle con supporto Web può rivelarsi un elemento chiave per un’in-
stallazione e una distribuzione di successo. Grazie a Oracle Metalink (http://metalink.oracle.com)
può accadere di non essere mai costretti a uscire dagli amichevoli e rassicuranti confini del
browser Web per mantenere in efficienza il proprio database. Attraverso Metalink è possibile
inviare una richiesta di assistenza, effettuare ricerche tra le altre richieste di supporto, scaricare
patch, scaricare white paper e fare ricerche nel database dei bug.
A partire da Oracle Database 10g, le licenze per il database Oracle possono essere concesse
solo per singolo utente o per CPU e non esiste più l’opzione di licenza per utenti concorrenti. Il
DBA deve pertanto utilizzare il parametro di inizializzazione LICENSE_MAX_USERS per spe-
cificare il numero massimo di utenti che è possibile creare nel database. Ne risulta che i parame-
tri LICENSE_MAX_SESSIONS e LICENSE_SESSIONS_WARNING non sono più accettati
in Oracle Database 10g.
Oltre a ciò, Oracle Management Server (il backend per un client Oracle Enterprise Manager,
o OEM) può essere installato durante un’installazione sul lato server o sul lato client. Si consi-
glia tuttavia di effettuare questa installazione una volta completata con successo un’installazione
di base del database.
NOTA Per gli ambienti UNIX sarà necessario impostare un valore adeguato per
la variabile di ambiente DISPLAY e abilitare xhost prima di avviare OUI attraverso lo script
runInstaller.
Le figure con il contenuto delle schermate per i principali passaggi correlati alla creazione
di un database verranno mostrate nel prossimo paragrafo del capitolo.
ni di prodotto, gli strumenti di gestione, i servizi di rete e un software client di base per il server
di database Oracle. Se si seleziona l’opzione “client”, OUI installerà gli strumenti di gestione
enterprise, i servizi di rete, le utility, gli strumenti di sviluppo, i precompilatori e il software
client di base. Per la prima installazione si consiglia di usare l’opzione “database” per creare il
database di base.
4. Scelta del tipo di installazione: Enterprise Edition, Personal Edition o Custom.
5. Se si è scelta l’opzione “database” al punto 3, il programma chiederà di confermare la crea-
zione del database di partenza.
6. Il programma chiederà di scegliere una delle configurazioni standard del database (uso ge-
nerico, elaborazione delle transazioni o data warehouse).
7. Scelta delle opzioni di configurazione per il database di base. Tra queste troviamo il nome
globale del database, il nome di istanza, il set di caratteri e la scelta se includere o meno gli
schemi di esempio.
8. Specifica di una singola password da usare per tutti gli schemi precaricati nel database di
partenza o specifica di password separate per tutti gli account.
9. Specifica delle opzioni di memorizzazione del database da utilizzare. Se si utilizzano dei file
del file system, occorre specificare la directory da usare. Tra le altre opzioni possibili ci sono la
gestione automatica dello spazio di memorizzazione e l’eventuale impiego di dispositivi raw.
10. Il programma chiederà di finalizzare la selezione delle opzioni di gestione e dei servizi
prima di accettare la configurazione e dare inizio all’installazione.
Durante l’installazione del software, il Database Configuration Assistant (DBCA) assume il
controllo e richiede i parametri necessari a dimensionare e configurare il database (a partire dal
punto 6 di questo elenco). I passaggi di installazione del prossimo paragrafo presuppongono che
sia già stata completata l’installazione del software e che si sia creato un database di partenza;
verrà quindi creato e configurato un secondo database sullo stesso server con DBCA.
Opzioni di DBCA
Dopo una schermata di benvenuto, vengono presentate quattro opzioni:
■ Create a Database Questa opzione è molto semplice; si dà vita a un nuovo database da zero,
utilizzando un modello come punto di partenza.
■ Configure Database Options in a Database Alcuni parametri di sistema per un’installazio-
ne di database esistente possono essere modificati, come il cambiamento dalla modalità con
server dedicato a quella a server condiviso.
INSTALLAZIONE DI ORACLE DATABASE 10G 15
■ Delete a Database Anche questa opzione è molto semplice, e altrettanto pericolosa. Essa
infatti arresterà il database e cancellerà tutti i file di dati e il file di controllo associati a esso. È
necessaria la password di SYS o SYSTEM per poter procedere con questa opzione.
■ Manage Templates Questa opzione consente di aggiungere, modificare o eliminare modelli.
Nel corso di una sessione di DBCA, una volta raccolti tutti i parametri del database, è possibile
salvare le proprie impostazioni sotto forma di modello. In molti casi i modelli predefiniti forniti
da Oracle non sono proprio perfetti per il proprio ambiente, quindi l’opportunità di salvare le
proprie opzioni come modello in modo da poterle scegliere in una sessione di DBCA futura può
rivelarsi una scelta importante per risparmiare tempo.
■ Data Warehouse Questo modello è concepito per gli ambienti database in cui gli utenti
effettuano molte query complesse che uniscono grandi tabelle per la produzione di report, la
generazione di previsioni e l’esecuzione di analisi.
■ General Purpose Se non si conosce ancora con certezza lo scopo preciso del database che si
sta per creare, o se si desidera soddisfare gli utenti con esigenze di tipo analitico nonché quelli
con necessità di elaborazione delle transazioni, è consigliabile scegliere questo modello.
■ Transaction Processing Questo modello è adatto per gli ambienti 24×7 in cui il numero di
utenti è elevato, le transazioni sono impegnative ma brevi e la gran parte dell’attività è caratteriz-
zata da operazioni di creazione e aggiornamento.
Per questa installazione verrà scelto il modello General Purpose, che combina in un solo
database le caratteristiche di un data warehouse e di un ambiente OLTP; è consigliabile utilizza-
re questa opzione se si deve usare il database per entrambi gli ambienti. L’ideale comunque è che
qualunque database venga creato sia configurato e messo a punto per i tipi di utenti e di transa-
zioni che lo caratterizzeranno.
Opzioni di memorizzazione
Il database può utilizzare molti metodi diversi per la memorizzazione dei file di dati, dei file di
controllo e dei file redo log. Se si dispone di risorse sufficienti per dedicare un’altra istanza del
database alla gestione dello spazio su disco, si consiglia di scegliere l’opzione ASM. Se ci si
trova in un ambiente Real Application Clusters e non si ha a disposizione un file system per
cluster (come OCFS), l’opzione consigliata è Raw Devices. La Figura 2.3 mostra queste opzioni
sulla schermata Storage Options.
Una novità di Oracle Database 10g è il concetto di Flash Recovery Area, una posizione sul
disco dedicata, separata dalla posizione dei file operativi del database, che contiene il file di
backup creati da RMAN (Recovery Manager). Si consiglia vivamente di utilizzare una Flash
Recovery Area in modo che RMAN possa gestire più agevolmente le operazioni di backup e
ripristino. Occorre accertarsi che la Flash Recovery Area sia abbastanza grande da contenere
almeno due copie di tutti i file dei dati, dei backup incrementali, del file di controllo, degli
SPFILE e dei file redo log archiviati ancora presenti sul disco.
È anche possibile abilitare la modalità ARCHIVELOG, nonché specificare la posizione o le
posizioni dei file redo log archiviati. Si consiglia di lasciare disattivata l’archiviazione fino a
installazione avvenuta del database, in quanto la sua attivazione farà aumentare il tempo neces-
sario per la creazione del database. I parametri per la modalità ARCHIVELOG possono facil-
mente essere modificati nel file init.ora o in SPFILE immediatamente dopo la messa in funzione
del database.
studio presuppongono la presenza di questi schemi nel database. Questi ultimi inoltre sono utili
in quanto dimostrano quasi tutti i tipi di dati e i costrutti disponibili nel database, dagli indici
bitmap alle tabelle riunite in cluster e ai tipi di oggetti.
Parametri di inizializzazione
La schermata della Figura 2.5 consente al DBA di regolare i parametri di inizializzazione fonda-
mentali del database. Nella figura è visibile la scheda Memory della schermata Initialization
Parameters. Se si seleziona l’opzione Typical, o se si seleziona Custom con Shared Memory
Management in modalità Automatic, Oracle farà delle previsioni sulla memoria che può utilizza-
re per la SGA e i processi in background. Anche se si accettano molti dei parametri predefiniti
della configurazione Typical, è pur sempre possibile specificare quanta memoria fisica del server
dev’essere utilizzata per Oracle, in relazione alla quantità di memoria usata dal sistema operati-
vo e al fatto che sul server siano in esecuzione altre applicazioni insieme a Oracle. Il valore per
Java Pool deve avere la dimensione di almeno un’unità minima del database, 4MB o 16MB,
tuttavia si consiglia di specificare almeno 20MB.
Le ultime sezioni di questa schermata del DBCA consentono di specificare la dimensione di
blocco predefinita del database, il numero totale di processi che si collegheranno simultanea-
mente, la modalità di connessione da utilizzare e il set di caratteri per il database.
INSTALLAZIONE DI ORACLE DATABASE 10G 19
Opzioni di creazione
Nella Figura 2.6 si è pronti per creare il database. Oltre a ciò, è possibile utilizzare le informazio-
ni fornite nelle schermate precedenti e salvarle in un modello. In caso di dubbi, il consiglio è di
salvare comunque come modello; lo spazio necessario al salvataggio di un modello è minimo ed
è facile eliminarlo in un secondo tempo eseguendo nuovamente DBCA.
Prima della creazione del database, viene presentato un riepilogo del modello in formato
HTML; tale report può essere salvato come file HTML se si desidera conservarlo nella docu-
mentazione.
Completamento dell’installazione
Dopo aver fatto clic su OK nella schermata Summary, DBCA effettua le operazioni necessarie a
creare il database e avviare l’istanza. Al primo avvio del database viene eseguito un gruppo
20 CAPITOLO 2
standard di script; tra questi ci sono gli script che creano gli schemi di esempio, oltre agli even-
tuali script personalizzati specificati in precedenza. Questo insieme standard di script varierà in
relazione alle opzioni selezionate tramite DBCA.
Una volta completata l’inizializzazione e gli script di creazione, compare una schermata di
riepilogo che fornisce la posizione del file log di questa installazione. Si consiglia di analizzare
questo file per accertarsi che non si siano verificati errori imprevisti nel corso dell’installazione.
Si consiglia inoltre di salvare questo file log assieme all’altra documentazione relativa al database,
in quanto può rivelarsi utile come base per future installazioni.
Il database Oracle appena creato ora è in funzione; a questo punto è possibile sbloccare gli
altri account creati durante l’installazione e assegnare a essi delle password.
Ecco i passaggi di base necessari per la creazione manuale di un database. Alcuni di questi
sono correlati al sistema operativo o alla piattaforma e le differenze verranno segnalate. Occorre
aver letto la guida all’installazione per la propria piattaforma specifica prima di tentare
un’installazione manuale. Per esempio, in ambiente Windows è necessario eseguire l’utility oradim
per creare il processo in background di Oracle e impostare i valori relativi nel Registro di sistema.
1. Decidere la struttura delle directory per il database; si consiglia di conformarsi con gli standard
Optimal Flexible Architecture di Oracle quando si collocano i file sul disco. Fare riferimento
alla Installation Guide for Oracle relativa al proprio sistema operativo per maggiori informazio-
ni su OFA.
2. Selezionare un Oracle SID (identificatore di istanza) per distinguere l’istanza in questione
da qualunque altra in esecuzione su questo server. Spesso questa è uguale al nome di database
specificato nel parametro di inizializzazione DB_NAME. Al prompt dei comandi di Windows si
digita quanto segue:
set ORACLE_SID=rjbdb
22 CAPITOLO 2
In UNIX si utilizzerà:
export ORACLE_SID=rjbdb
oppure
setenv ORACLE_SID=rjbdb
# Archive
LOG_ARCHIVE_DEST_1='LOCATION=/u06/oracle10g/oradata/rjbdb/archive'
# New log archive format. If compatibility 10.0 and up,
# this is enforced.
LOG_ARCHIVE_FORMAT=%t_%s_%r.dbf
# The following parameter is deprecated in 10iR1
# LOG_ARCHIVE_START=TRUE
# Shared Server
# Starts shared server if set > 0.
SHARED_SERVERS=2
# Uncomment and use first DISPATCHERS parameter
# below when your listener is
# configured for SSL
# (listener.ora and sqlnet.ora)
INSTALLAZIONE DI ORACLE DATABASE 10G 23
# DISPATCHERS = "(PROTOCOL=TCPS)(SER=MODOSE)",
# "(PROTOCOL=TCPS)(PRE=oracle.aurora.server.SGiopServer)"
DISPATCHERS="(PROTOCOL=TCP)(SER=MODOSE)",
"(PROTOCOL=TCP)(PRE=oracle.aurora.server.SGiopServer)",
(PROTOCOL=TCP)
# Miscellaneous
COMPATIBLE=10.0.0
DB_NAME=rjbdb
# Network Registration
INSTANCE_NAME=rjbdb
# Pools
JAVA_POOL_SIZE=31457280
LARGE_POOL_SIZE=1048576
SHARED_POOL_SIZE=52428800
# Resource Manager
RESOURCE_MANAGER_PLAN=SYSTEM_PLAN
sqlplus /nolog
connect SYS/password as sysdba
Benché l’istanza stessa esista, non possiamo fare molto con essa in quanto il database non è
ancora stato creato.
6. Creare un file dei parametri del server (SPFILE). Se il file di inizializzazione è nella posizio-
ne predefinita, il comando che segue creerà SPFILE:
startup nomount
Dato che non è ancora stato creato un database, questa è l’unica opzione utilizzabile con il
comando startup.
24 CAPITOLO 2
8. Impartire il comando create database. Ecco un esempio (si stanno specificando le password
per gli account SYS e SYSTEM):
Sono diverse le cose che vale la pena di osservare in questo esempio. Si stanno impostando
esplicitamente le password per SYS e SYSTEM; se non venissero specificate qui, per default
sarebbero rispettivamente “change_on_install” e “manager”.
I gruppi di file redo log hanno un solo membro ciascuno; una volta che il database sia
passato all’ambiente di produzione, è necessario procedere al multiplexing. Dato che è stata
specificata una tablespace di undo con il parametro UNDO_TABLESPACE nel file dei parame-
tri di inizializzazione, qui è necessario creare la tablespace, altrimenti l’istanza non si avvierà.
Una volta completato con successo il comando create database, il database viene montato e
aperto per essere usato.
9. Creare tablespace aggiuntive per utenti, indici e applicazioni.
10. Generare delle viste del dizionario dati con gli script catalog.sql e catproc.sql forniti da
Oracle. Lo script catalog.sql crea viste delle tabelle del dizionario dati, viste di prestazioni dina-
miche e sinonimi pubblici per la maggior parte delle viste. Al gruppo PUBLIC viene concesso
accesso di sola lettura alle viste. Lo script catproc.sql imposta PL/SQL.
11. Effettuare un backup del database tramite un backup a freddo o con Recovery Manager. In
caso di errore del database nelle prime fasi della distribuzione, si avrà un database completo e
funzionante su cui ripiegare e molto probabilmente non sarà necessario ricrearlo da zero.
A questo punto il software Oracle è stato installato, il database di partenza è stato creato e
forse è stato creato un secondo database. Nel prossimo capitolo si vedrà come effettuare un
aggiornamento a Oracle Database 10g a partire da versioni precedenti del prodotto.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 3
Aggiornamento
a Oracle Database 10g
C
hi abbia già installato un versione precedente del server di
database Oracle può aggiornare il proprio database a Oracle Database 10g. I percorsi di aggior-
namento possibili sono diversi; la scelta giusta dipende da fattori come la versione di Oracle
corrente e la dimensione del database. In questo capitolo verranno presentate delle descrizioni di
questi metodi assieme ad alcune indicazioni per la loro applicazione.
Chi invece non abbia utilizzato una versione di Oracle precedente a Oracle Database 10g
può saltare questo capitolo per il momento. È probabile tuttavia che si troverà a consultarlo nel
momento in cui decida di aggiornare da Oracle Database 10g a una versione successiva o quando
dovrà migrare dei dati da un database diverso nel proprio.
Prima di iniziare l’aggiornamento, è necessario leggere la Oracle Database 10g Installation
Guide per il proprio sistema operativo. La buona riuscita di un’installazione dipende da un am-
biente correttamente configurato, compresi i livelli delle patch del sistema operativo e le
impostazioni dei parametri di sistema. Occorre mirare a ottenere un aggiornamento corretto al
primo colpo invece di tentare di riavviare un’installazione riuscita solo parzialmente.
Questo capitolo presuppone che la propria installazione del software Oracle Database 10g
software (Capitolo 2) sia stata completata con successo e che sia presente un database Oracle che
utilizza una versione precedente del software Oracle. Le opzioni disponibili per aggiornare il
database sono quattro:
■ Utilizzare il Database Upgrade Assistant come guida ed effettuare l’aggiornamento sul po-
sto. Il vecchio database diventerà un database Oracle 10g nel corso del processo.
■ Effettuare un aggiornamento manuale del database. Il vecchio database diventerà un database
Oracle 10g nel corso del processo.
■ Usare le utility Export e Import per spostare i dati da una versione precedente di Oracle al
database Oracle 10g. Verranno utilizzati due database separati: il vecchio database come origine
dell’esportazione e quello nuovo come destinazione dell’importazione.
■ Copiare i dati da una versione precedente di Oracle a un database Oracle 10g. Verranno
utilizzati due database separati: il vecchio database come origine della copia e quello nuovo
come destinazione della copia.
L’aggiornamento di un database sul posto, tramite Database Upgrade Assistant o con la
procedura manuale, prende il nome di aggiornamento diretto. Dato che un aggiornamento diret-
26 CAPITOLO 3
to non implica la creazione di un secondo database per quello che viene aggiornato, potrebbe
richiedere un tempo minore e meno spazio su disco rispetto a un aggiornamento indiretto.
all’esportazione e importazione, ogni riga del database viene selezionata e reinserita. Se il database
è molto grande, il processo di importazione potrebbe richiedere molto tempo, al punto da impe-
dire di mettere il database aggiornato a disposizione degli utenti in tempi accettabili. Per mag-
giori dettagli sulle utility Export e Import si rimanda ai Capitolo 22 e 46.
NOTA In relazione alla versione del database di origine, sarà necessario utilizza-
re una versione specifica delle utility Export e Import. Fare riferimento al paragrafo “Versioni
di Export e Import da utilizzare” più avanti nel capitolo.
Con il metodo della copia dei dati viene impartita una serie di comandi create table as select
o insert as select che attraversano i database link (Capitolo 23) per recuperare i dati di origine.
Le tabelle vengono create nel database Oracle 10g in base a query di dati di un database di
origine separato. Questo metodo consente di trasferire i dati in modo incrementale e di limitare
le righe e le colonne soggette a migrazione. Occorre tuttavia stare attenti che i dati copiati man-
tengano tutte le relazioni necessarie tra tabelle. Come per l’esportazione e importazione, questo
metodo può richiedere molto tempo per i database di grandi dimensioni.
La selezione del metodo di aggiornamento adeguato richiede la valutazione delle capacità
tecniche del team, dei dati da migrare e del tempo di fermo accettabile durante la migrazione. In
generale per i database di grandi dimensioni la scelta ricadrà sull’uso di DBUA, mentre per i
database più piccoli si può ricorrere a un metodo indiretto.
dbua
(negli ambienti UNIX) o selezionando Database Upgrade Assistant dall’opzione del menu
Configuration and Migration Tools di Oracle (negli ambienti Windows).
28 CAPITOLO 3
Una volta avviato, DBUA visualizzerà una schermata di benvenuto. Nella schermata succes-
siva occorre selezionare il database che si desidera aggiornare dall’elenco del database disponi-
bili; si può aggiornare un solo database alla volta.
Dopo aver effettuato la selezione, il processo di aggiornamento ha inizio. DBUA effettuerà
le verifiche preventive (quali la ricerca di parametri di inizializzazione obsoleti o di file troppo
piccoli), dopodiché darà vita alla tablespace SYSAUX, una tablespace standard presente in tutti
i database Oracle 10g. È possibile ignorare le opzioni predefinite di Oracle per i parametri di
posizione e dimensioni per i file dei dati utilizzate dalla tablespace SYSAUX.
DBUA a questo punto chiederà di ricompilare gli oggetti PL/SQL non validi (fare riferimen-
to alla Parte quarta del libro) in seguito all’aggiornamento. Se non si ricompilano questi oggetti
dopo l’aggiornamento, il primo utente che si troverà a doverli usare sarà costretto ad attendere
l’esecuzione della ricompilazione in fase di esecuzione da parte di Oracle.
DBUA a questo punto chiederà di eseguire un backup del database come parte del processo
di aggiornamento. Se si è già provveduto al backup del database prima dell’avvio di DBUA, si
può scegliere di saltare questo passaggio. Se invece si sceglie di lasciare che sia DBUA a effet-
tuare il backup, esso arresterà il database ed effettuerà un backup fuori linea dei file dei dati nella
directory specificata. DBUA inoltre creerà in quella stessa directory un file batch che automatizza
il ripristino di questi file nelle loro posizioni precedenti.
Il passaggio successivo consiste nella scelta se abilitare o meno Oracle Enterprise Manager
(OEM) per la gestione del database. Se si abilita questo strumento, il database aggiornato sarà
automaticamente disponibile attraverso OEM.
A questo punto il programma chiede di finalizzare le configurazione di protezione per il
database aggiornato; come avviene con il processo di creazione del database, è possibile speci-
ficare delle password per ciascun account privilegiato oppure impostare una singola password
da applicare a tutti gli account utente OEM.
Infine verranno richiesti i dettagli sulla posizione della flash recovery area (Capitolo 28),
l’impostazione per l’archive log (Capitolo 46) e la configurazione di rete. Una schermata di
riepilogo finale visualizza le scelte per l’aggiornamento, che viene avviato quando queste ultime
vengono accettate. Una volta completato l’aggiornamento, DBUA visualizza la schermata
Checking Upgrade Results, che mostra i passaggi eseguiti, i file log correlati e lo stato. La
sezione della schermata intitolata Password Management consente di gestire le password e lo
stato bloccato/sbloccato degli account nel database aggiornato.
Se non si è soddisfatti dei risultati dell’aggiornamento, è possibile scegliere l’opzione Restore.
Se si è utilizzato DBUA per effettuare il backup, il ripristino avverrà automaticamente; in caso
contrario sarà necessario procedere a un ripristino manuale.
Quando si esce da DBUA dopo aver aggiornato con successo il database, lo strumento ri-
muove la voce relativa al vecchio database nel file di configurazione del listener di rete, inserisce
una voce per il database aggiornato e ricarica il file.
del software Oracle Database 10g. Questo file dev’essere eseguito nel database da aggiornare in
qualità di utente con privilegi SYSDBA, inviando il risultato a un file log. Questi risultati mette-
ranno in luce i potenziali problemi da affrontare prima dell’aggiornamento.
Se non ci sono questioni da risolvere prima di procedere, si dovrà arrestare il database ed
effettuare un backup fuori linea prima di continuare con l’operazione di aggiornamento.
Una volta creato un backup cui ricorrere in caso di necessità, si è pronti per procedere con
l’aggiornamento. Il processo è dettagliato e si basa su script, pertanto è necessario consultare la
documentazione sull’installazione e l’aggiornamento di Oracle relativa alla propria versione e
all’ambiente. Le fasi sono le seguenti:
1. Copiare i file di configurazione (init.ora, spfile.ora, file delle password) dalla nuova posizio-
ne alla home directory del nuovo software Oracle. Per default i file di configurazione si trovano
nella sottodirectory /dbs sulle piattaforme UNIX e nella directory /database negli ambienti
Windows.
2. Rimuovere i parametri di inizializzazione obsoleti e disapprovati dai file di configurazione.
Aggiornare il parametro COMPATIBLE per Oracle 10. Accertarsi che il parametro SHARED_
POOL_SIZE sia impostato ad almeno 96MB per le piattaforme a 32 bit e almeno a 144MB per
quelle a 64 bit. Impostare PGA_AGGREGATE_TARGET ad almeno 24MB, LARGE_POOL_
SIZE ad almeno 8MB e JAVA_POOL_SIZE ad almeno 48MB. Per i parametri Windows, impo-
stare BACKGROUND_DUMP_DEST a \oradata\nome_database e USER_DUMP_DEST a
\oradata\nome_database\archive nella directory di base del software Oracle. Utilizzare percorsi
completi nei file dei parametri.
3. Se si sta aggiornando un database cluster, occorre impostare il parametro di inizializzazione
CLUSTER_DATABASE a FALSE. Dopo l’aggiornamento, questo parametro dev’essere ripor-
tato a TRUE.
4. Arrestare l’istanza.
5. Se si utilizza Windows, arrestare il servizio associato con l’istanza ed eliminare il servizio
Oracle dal prompt dei comandi. Per Oracle 8.0, utilizzare il comando ORADIM80 –DELETE –
SID nome_istanza. Per Oracle8.1 e successivi, usare ORADIM –DELETE –SID nome_istanza.
Dopodiché creare il nuovo servizio Oracle Database 10g con ORADIM nel modo indicato qui:
VARIABILE DESCRIZIONE
SID Il nome del SID (identificatore di istanza) del database che si sta aggiornando.
PASSWORD La password per la nuova istanza di database della release 10.1. Questa è la password per l’utente
connesso con privilegi SYSDBA. Se non si specifica INTPWD, viene utilizzata l’autenticazione del siste-
ma operativo e non è richiesta alcuna password.
UTENTI Il numero massimo di utenti cui è possibile concedere i privilegi SYSDBA e SYSOPER.
ORACLE_HOME La home directory della release 10.1 di Oracle. Occorre accertarsi di specificare il percorso completo
con l’opzione -PFILE, includendo la lettera dell’unità che ospita la home directory di Oracle.
6. Se il sistema operativo in uso è UNIX, occorre accertarsi che le variabili ambientali seguenti
puntino alle directory della nuova release 10.1: ORACLE_HOME, PATH, ORA_NLS33 e
LD_LIBRARY_PATH.
30 CAPITOLO 3
13. Eseguire lo script per la vecchia versione. Per esempio, se si aggiorna dalla release 8.0.6,
occorre eseguire solo lo script u0800060.sql e poi passare alla fase successiva del processo di
aggiornamento.
Aggiornamento da: Script da eseguire:
8.0.6 u0800060.sql
8.1.7 u0801070.sql
9.0.1 u0900010.sql
9.2 u0902000.sql
14. Interrompere lo spooling (con spool off) e analizzare il file di spool per rilevare eventuali
errori. Risolvere gli eventuali problemi riscontrati.
15. Eseguire il file utlu101s.sql, con TEXT come parametro di input:
@@utlu101s TEXT
Quando si esporta per effettuare un “downgrade” della versione del database è necessario
utilizzare la versione più vecchia dell’utility Export per ridurre al minimo i problemi di compa-
tibilità. Questi ultimi potrebbero comunque comparire nel caso in cui la versione più nuova del
database utilizzi caratteristiche nuove (come nuovi tipi di dati) non riconosciuti dalla versione
più vecchia.
Esecuzione dell’aggiornamento
Esportare i dati dal database di origine utilizzando la versione dell’utility Export specificata nel
paragrafo precedente. Effettuare un’esportazione coerente, oppure procedere all’esportazione
quando il database non è disponibile per aggiornamenti durante e dopo l’esportazione.
32 CAPITOLO 3
Una volta preparato il database, utilizzare Import o Data Pump Import (Capitolo 22) per
caricare i dati dal file di dump di Export nel database di destinazione. Analizzare il file log alla
ricerca di informazioni su oggetti che non sono stati importati correttamente.
■ Disabilitare tutti gli indici e i vincoli fino a quando i dati sono stati caricati.
■ Eseguire più operazioni di copia dei dati in parallelo.
■ Utilizzare l’opzione delle query parallele per migliorare le prestazioni delle query e degli
inserimenti individuali.
■ Utilizzare il suggerimento APPEND per migliorare le prestazioni degli inserimenti.
Per ulteriori consigli sulla messa a punto delle prestazioni, si rimanda al Capitolo 43.
Occorre analizzare i parametri di inizializzazione del database per accertarsi che i parametri
disapprovati e obsoleti siano stati rimossi; questi ultimi devono essere identificati durante il
processo di migrazione. Occorre accertarsi inoltre di ricompilare qualunque programma che si
affidi alle librerie del software di database.
Una volta completato l’aggiornamento, effettuare le verifiche funzionali e di prestazioni
identificate prima dell’inizio dell’aggiornamento. Se il database presenta problemi di funziona-
lità, occorre tentare di identificare le eventuali impostazioni di parametri o gli oggetti mancanti
che possono influire sui risultati dei test. Se il problema sembra non avere soluzione, potrebbe
essere necessario tornare alla versione precedente.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 4
Pianificazione
delle applicazioni Oracle:
approcci, rischi e standard
P
er poter creare e utilizzare rapidamente ed efficacemente
un’applicazione Oracle, gli utenti e gli sviluppatori devono condividere un linguaggio comune e
avere una conoscenza approfondita sia del compito specifico per cui viene utilizzata l’applica-
zione, sia degli strumenti di Oracle. I capitoli precedenti hanno offerto una descrizione generale
dei prodotti Oracle e delle operazioni necessarie per procedere all’installazione o all’aggiorna-
mento. Ora che il software è installato, è possibile realizzare applicazioni che si fondano sulla
comprensione dei processi aziendali e dei dati condivisa dai membri del reparto tecnico e di
quello aziendale.
In passato, gli analisti di sistemi studiavano le esigenze del mondo del lavoro e progettavano
un applicazione che soddisfacesse tali esigenze. L’utente veniva coinvolto solo nella fase di
descrizione del lavoro e talvolta nella revisione della funzionalità dell’applicazione progettata.
Con i nuovi strumenti e le varie modalità di approccio disponibili, e soprattutto con Oracle,
è possibile sviluppare applicazioni più adeguate alle aspettative e alle abitudini del mondo del
lavoro, a condizione però che si instauri un linguaggio comune.
Lo scopo specifico di questo libro è promuovere questa condivisione di conoscenze e fornire
agli utenti e agli sviluppatori i mezzi per sviluppare appieno le potenzialità di Oracle. L’utente
finale conoscerà dettagli del lavoro che lo sviluppatore non è in grado di comprendere. Lo
sviluppatore apprenderà funzioni e caratteristiche interne di Oracle e dell’ambiente informatico
che sarebbero tecnicamente troppo complesse per l’utente finale. Tuttavia, questi ambiti di co-
36 CAPITOLO 4
noscenza esclusiva hanno portata minore rispetto a tutto ciò che utenti e sviluppatori possono
condividere utilizzando Oracle; si tratta di un’opportunità davvero interessante.
Non è un segreto che il “mondo del lavoro” e il “mondo degli informatici” sono stati in
conflitto per molti anni. Differenze culturali e ambiti di conoscenza diversi, interessi e obiettivi
professionali differenti, oltre al senso di estraneità che la semplice separazione fisica talvolta
produce, sono alcuni dei motivi alla base di questa situazione. Per essere giusti, questa sorta di
sindrome non è tipica dell’informatizzazione; la stessa situazione si verifica anche tra persone
che si occupano di contabilità, gestione del personale o direzione generale, poiché i componenti
di ogni gruppo tendono a raggrupparsi e a separarsi dagli altri gruppi collocandosi fisicamente
su un piano, un edificio o una città diversa. Le relazioni tra individui di gruppi differenti diven-
tano formali e tese. Si instaurano delle barriere e delle procedure artificiali che prendono le
mosse da questo isolazionismo, contribuendo ad aggravare la “sindrome”.
Va bene, si potrebbe pensare, tutto questo può essere interessante per i sociologi, ma che
cosa ha a che fare con Oracle?
Il fatto è che Oracle non si fonda su un linguaggio arcano comprensibile soltanto per gli
specialisti, ma modifica la natura del rapporto tra utenti e sviluppatori. Chiunque può compren-
derlo, chiunque può utilizzarlo. Le informazioni che prima erano intrappolate nei sistemi infor-
matici finché qualcuno non creava un report di presentazione sono ora accessibili, istantanea-
mente, a chiunque, semplicemente inserendo una query in lingua inglese. In questo modo cam-
biano le regole del gioco.
Utilizzando Oracle, la comprensione tra i due campi è migliorata radicalmente, è aumentata
la conoscenza reciproca e anche le relazioni tra i due gruppi hanno cominciato a normalizzarsi,
portando di conseguenza a ottenere applicazioni e risultati finali di qualità superiore.
Fin dalla prima versione, Oracle è stato impostato su un modello relazionale di facile com-
prensione (spiegato tra breve); in questo modo i non esperti possono comprendere prontamente
che cosa fa Oracle e come lo fa. Ciò lo ha reso di facile approccio.
Alcuni individui non lo accettano né comprendono, né capiscono l’importanza vitale del
fatto che le vecchie e artificiali barriere tra “utenti” e “sistemi” continuino a crollare, ma l’avvento
dello sviluppo cooperativo avrà un’influenza profonda sulle applicazioni e sulla loro utilità.
Tuttavia, molti sviluppatori di applicazioni sono caduti in una trappola: proseguire con me-
todi inutili ereditati dalla progettazione di sistemi della generazione precedente. C’è molto da
disimparare. Molte delle tecniche (e dei limiti) che erano indispensabili in precedenza non sono
soltanto inutili nella progettazione con Oracle, ma del tutto controproducenti. Nell’affrontare
l’apprendimento di Oracle ci si deve liberare dal peso di queste abitudini e di questi approcci
datati: ora sono disponibili nuove e stimolanti possibilità.
L’intento fondamentale di questo testo è spiegare Oracle in maniera semplice e chiara, in
termini comprensibili e condivisibili sia dagli utenti, sia dai tecnici. Per quanto concerne invece
le modalità di progettazione e gestione datate o inadeguate, verrà proposto il modo migliore per
sostituirle.
cientemente espressivo anche per il lavoro più complesso. Un database relazionale a oggetti
presenta tutte le caratteristiche di un database relazionale, ma consente anche di sviluppare con-
cetti e funzioni orientati agli oggetti. Oracle può essere utilizzato come RDBMS (Relational
Database Management System, sistema per la gestione di database relazionali) per sfruttare le
sue caratteristiche orientate agli oggetti.
Purtroppo, proprio coloro che possono trarre più utilità da un database relazionale, ovvero
gli utenti che se ne servono per lavoro, in genere ne sanno di meno. Gli sviluppatori di applica-
zioni, che costruiscono i sistemi che questi utenti utilizzano nella loro attività, spesso pensano
che i concetti che stanno alla base del software relazionale siano troppo difficili per poter essere
spiegati in termini semplici. È necessario un linguaggio comune perché l’approccio cooperativo
funzioni.
Nelle prime due parti di questo testo viene illustrato, con termini di comprensibilità imme-
diata, che cos’è esattamente un database relazionale e come utilizzarlo efficacemente nella pro-
pria attività. A prima vista, potrebbe sembrare che questa trattazione sia esclusivamente a bene-
ficio degli “utenti”, quindi un tecnico esperto di applicazioni relazionali potrebbe avere la ten-
denza a saltare questi primi capitoli per utilizzare il libro semplicemente come testo elementare
di consultazione su Oracle. Anche se molto del materiale può apparire come una panoramica di
base, per i progettisti di applicazioni si tratta di un’opportunità per acquisire un terminologia
chiara, coerente e gestibile di cui servirsi per conversare con gli utenti riguardo alle loro esigen-
ze e alle modalità per soddisfarle velocemente. Per i lettori di questo tipo, questa trattazione può
anche essere utile per abbandonare alcune abitudini inutili e probabilmente inconsce tipiche dei
tecnici, molte delle quali vengono svelate durante la presentazione dell’approccio relazionale. È
importante comprendere che persino il potenziale di Oracle può essere limitato considerevol-
mente da metodi di progettazione adatti soltanto allo sviluppo di software non relazionale.
Per gli utenti finali, la comprensione dei concetti fondamentali dei database relazionali a
oggetti consente di esprimere meglio le proprie esigenze agli sviluppatori di applicazioni e di
capire come possano essere soddisfatte. Mediamente un operatore può passare da principiante a
esperto in breve tempo. Oracle offre la capacità di raccogliere e utilizzare informazioni, di avere
il controllo immediato dei report e dei dati e una visione chiara di come funziona l’applicazione.
L’utente di Oracle può gestire un’applicazione o una query in maniera avanzata e sapere se non
sta utilizzando tutta la flessibilità e il potenziale disponibile.
L’utente finale ha anche la possibilità di liberare i programmatori dal loro compito meno
gradevole: compilare nuovi report. Nelle grandi aziende, ben il 95 per cento di tutto il cumulo di
lavoro arretrato è composto da richieste di nuovi report. Dato che l’utente è in grado di compilar-
li autonomamente, in termini di minuti e non di mesi, sarà gratificante averne la responsabilità.
rappresentato dai dati e dalle tre operazioni che possono essere effettuate con essi: acquisirli,
memorizzarli e richiamarli.
Una volta chiarite le nozioni di base, si può procedere effettuando conteggi, spostando i dati
da una collocazione all’altra e modificandoli. Ciò viene definito elaborazione e, fondamental-
mente, coinvolge le tre fasi con cui vengono organizzate le informazioni.
Tutte queste operazioni potrebbero essere effettuate con carta e matita, ma con l’aumentare
del volume dei dati tendenzialmente cambiano anche gli strumenti. È possibile utilizzare un
classificatore, calcolatrici, matite e carta. A un certo punto diventa sensato passare ai computer,
anche se i compiti da eseguire rimangono gli stessi.
Un sistema di gestione di database relazionale (o RDBMS, acronimo di Relational DataBase
Management System) come Oracle consente di svolgere questi compiti in maniera comprensibi-
le e ragionevolmente semplice. In pratica con Oracle è possibile svolgere tre compiti:
■ inserire dati;
■ mantenere i dati in memoria;
■ reperire i dati e gestirli.
Nella Figura 4.1 viene illustrata la semplicità di tutto ciò.
Oracle supporta questo approccio in tre fasi e fornisce strumenti intelligenti che consentono
un notevole livello qualitativo nelle modalità con cui i dati vengono reperiti, visualizzati, modi-
ficati e inseriti, mantenuti al sicuro ed estrapolati per manipolarli e costruire report sulla base
delle informazioni che contengono.
Output
Input
Archivio
CLIMA
Citta Temperatura Umidita Condizione
ATENE........ 36 89 SOLE
CHICAGO...... 19 88 PIOGGIA
LIMA......... 7 79 PIOGGIA
MANCHESTER... 19 98 NEBBIA
PARIGI....... 27 62 NUVOLOSO
SPARTA....... 23 63 NUVOLOSO
SYDNEY....... 20 99 SOLE
Si tratta delle tre caratteristiche principali della maggior parte delle tabelle stampate: colon-
ne, righe e nome. Lo stesso accade per un database relazionale. I termini e i concetti rappresen-
tati sono comprensibili da tutti, perché le parole utilizzate per descrivere i componenti di una
tabella in un database di Oracle sono le stesse utilizzate nelle conversazioni quotidiane. Non si
tratta di termini dal significato particolare, insolito o esoterico: hanno esattamente il significato
che suggeriscono.
Tabelle di informazioni
Oracle memorizza le informazioni in tabelle, delle quali è possibile vedere un esempio nella
Figura 4.3. In ciascuna di queste tabelle sono presenti una o più colonne. Le intestazioni delle
colonne come Citta, Temperatura, Umidita e Condizione visibili nella Figura 4.3 sono utilizzate
per descrivere il tipo di informazione contenuta nella colonna. Le informazioni vengono memo-
rizzate riga dopo riga (città dopo città). Ogni singolo insieme di dati, come la temperatura,
l’umidità e la condizione per la città di Manchester, occupa la sua colonna specifica.
Con Oracle viene evitata la terminologia specializzata, accademica, al fine di rendere il
prodotto di più facile approccio. Nei documenti di ricerca sulla teoria relazionale, una colonna
può essere definita “attributo”, una riga “tupla” e una tabella può essere definita come “entità”.
Nome tabella
Colonna
CLIMA
Citta Temperatura Umidita Condizione
------------- ----------- ------- ----------
ATENE 36 89 SOLE
CHICAGO 19 88 PIOGGIA
LIMA 7 79 PIOGGIA
Riga
MANCHESTER 19 98 NEBBIA
PARIGI 27 62 NUVOLOSO
SPARTA 23 63 NUVOLOSO
SYDNEY 20 99 SOLE
Per l’utente finale, tuttavia, questi termini possono generare confusione. Inoltre, si tratta di una
ridenominazione non necessaria di elementi per i quali esistono già termini generalmente com-
presi nel linguaggio quotidiano. Con Oracle si utilizza questo linguaggio quotidiano e anche i
tecnici possono adeguarsi. È indispensabile prendere coscienza del muro di sfiducia e incom-
prensione che viene prodotto dall’uso di gergo tecnico non necessario. Come Oracle, quindi,
anche questo testo si basa su “tabelle”, “colonne” e “righe”.
SQL
Oracle è stata la prima azienda a presentare un prodotto che utilizzava il linguaggio di interroga-
zione strutturato SQL (Structured Query Language), basato sulla lingua inglese. Questo lin-
guaggio consente agli utenti finali di estrarre le informazioni in modo autonomo, senza rivolger-
si ai sistemisti per ogni piccolo report.
Il linguaggio di interrogazione di ORACLE è dotato di struttura, proprio come la lingua
inglese o qualunque altra lingua. Ci sono regole grammaticali e sintattiche, ma sono fondamen-
talmente le stesse di un discorso corretto e risultano quindi di immediata comprensione.
Come verrà illustrato tra breve, SQL è uno strumento sorprendentemente potente, il cui
utilizzo non richiede nessuna esperienza di programmazione.
Ecco un esempio di possibile impiego: se qualcuno chiede di selezionare dalla tabella CLI-
MA la città con umidità pari a 89, si può facilmente rispondere “Atene”. Se venisse chiesto di
selezionare le città con temperatura pari a 19 gradi, la risposta sarebbe “Chicago e Manchester”.
Anche Oracle è in grado di rispondere alle stesse domande, quasi con la stessa facilità di un
operatore e in risposta a una query semplice, molto simile alle domande poste poc’anzi. Le
parole chiave utilizzate in una query per ORACLE sono select, from, where e order by. Si tratta
di spunti che consentono a Oracle di comprendere la domanda e presentare la risposta corretta.
Citta
----------
Atene
Citta
----------
Manchester
Chicago
PIANIFICAZIONE DELLE APPLICAZIONI ORACLE 41
Come si può vedere, ciascuna di queste query usa le parole chiave select, from e where. Che
dire di order by? Si supponga di voler visualizzare tutte le città in ordine di temperatura. Occor-
rerebbe semplicemente digitare:
Citta Temperatura
---------- -----------
LIMA 7
MANCHESTER 19
CHICAGO 19
SYDNEY 20
SPARTA 23
PARIGI 27
ATENE 36
Oracle ha rapidamente riordinato la tabella per temperatura (in questa tabella sono elencate
per prime le temperature più basse; più avanti verrà spiegato come specificare l’ordinamento).
Con gli strumenti di interrogazione di Oracle è possibile impostare molte altre domande,
tuttavia gli esempi riportati dimostrano quanto sia facile ricavare informazioni da un database
Oracle nella forma più corrispondente alle esigenze dell’utente. Si possono costruire richieste
complesse partendo da informazioni semplici, ma il metodo utilizzato rimane sempre facilmente
comprensibile. Per esempio, si possono combinare i parametri where e order by, entrambi ele-
menti semplici, per chiedere al programma di selezionare le città in cui la temperatura è superio-
re a 26 gradi e di visualizzarle in ordine di temperatura crescente. In questo caso occorre digitare:
Citta Temperatura
---------- -----------
PARIGI 27
ATENE 36
Oppure si potrebbe impostare una richiesta ancora più specifica, chiedendo quali sono le
città in cui la temperatura è superiore a 26 gradi e l’umidità inferiore a 70:
CLIMA
Citta Temperatura Umidita Condizione
---------- ----------- ------- ----------
ATENE 36 89 SOLE
CHICAGO 19 88 PIOGGIA
LIMA 7 79 PIOGGIA
MANCHESTER 19 98 NEBBIA
PARIGI 27 62 NUVOLOSO
SPARTA 23 63 NUVOLOSO
SYDNEY 20 99 SOLE
DISLOCAZIONE
Citta Paese
---------- -----
ATENE GRECIA
CHICAGO STATI UNITI
CONAKRY GUINEA
LIMA PERU
MADRAS INDIA
MADRID SPAGNA
MANCHESTER INGHILTERRA
MOSCA RUSSIA
PARIGI FRANCIA
ROMA ITALIA
SHENYANG CINA
SPARTA GRECIA
SYDNEY AUSTRALIA
TOKIO GIAPPONE
CLIMA e, una volta individuato, ci si sposta lungo la riga per trovare i valori di Temperatura,
Umidita e Condizione: 20, 99 e SOLE.
Anche se le tabelle sono indipendenti, si può facilmente constatare che risultano correlate:
un nome di città in una tabella è correlato a un nome di città nell’altra (Figura 4.5). Il termine
database relazionale fa riferimento a questo tipo di relazione.
Questa è la nozione fondamentale di database relazionale (talvolta definito modello
relazionale). I dati vengono organizzati in tabelle, composte da colonne, righe e nomi. Le tabelle
possono essere correlate tra loro se hanno una colonna con un tipo di informazione comune.
Tutto qui, nulla di più complicato.
CLIMA
Citta Temperatura Umidita Condizione
---------- ----------- ------- ----------
ATENE 36 89 SOLE
CHICAGO 19 88 PIOGGIA
LIMA 7 79 PIOGGIA
MANCHESTER 19 98 NEBBIA
PARIGI 27 62 NUVOLOSO
SPARTA 23 63 NUVOLOSO
SYDNEY 20 99 SOLE
DISLOCAZIONE
Citta Paese
---------- -----
ATENE GRECIA
CHICAGO STATI UNITI
CONAKRY GUINEA
Relazione
LIMA PERU
MADRAS INDIA
MADRID SPAGNA
MANCHESTER INGHILTERRA
MOSCA RUSSIA
PARIGI FRANCIA
ROMA ITALIA
SHENYANG CINA
SPARTA GRECIA
SYDNEY AUSTRALIA
TOKIO GIAPPONE
il modo di considerarle. Molte delle tabelle che si osservano più comunemente potrebbero essere
inserite in Oracle, così da poterle utilizzare per rispondere velocemente a domande per le quali
sarebbe necessario molto tempo in qualsiasi altro modo.
Nella Figura 4.6 è rappresentata una tipica tabella sull’andamento della borsa. Si tratta di
una piccola parte di un elenco alfabetico molto denso che comprende molte colonne ravvicinate
distribuite su diverse pagine in un giornale. Per quale azienda è stato scambiato il numero mag-
giore di azioni? Quale ha avuto la variazione percentuale più elevata, in positivo o in negativo?
Per ottenere queste risposte con Oracle è sufficiente impostare delle semplici query; i tempi di
risposta sono molto più rapidi di quelli impiegati dovendo scorrere le colonne sulla pagina di un
giornale.
Nella Figura 4.7 è riprodotto un indice di giornale. Che cosa si trova nella sezione F? Se si
leggesse il giornale dall’inizio alla fine, in che ordine apparirebbero gli articoli? Anche in questo
caso, per ottenere le risposte a queste domande con Oracle è sufficiente impostare delle semplici
query. In questo libro viene illustrato come impostare tutte queste query e anche come costruire
le tabelle in cui conservare le informazioni.
In tutto il libro gli esempi utilizzeranno dati e oggetti che si incontrano frequentemente sul
lavoro e nella vita quotidiana. Non dovrebbe essere difficile trovare dati simili da usare per i
propri esercizi. Nelle pagine a seguire si imparerà a inserire e recuperare dati con il ricorso a
esempi basati su origini dati tratte dalla vita quotidiana.
Come accade per qualsiasi nuova tecnologia o per un nuovo avvenimento dall’incerto profi-
lo, è importante considerare attentamente non solo i benefici e le opportunità che si presentano,
ma anche i costi e i rischi. Se a ciò si aggiunge un database relazionale con una serie di strumenti
potenti e facili da utilizzare, come Oracle, la possibilità di essere guidati verso il disastro proprio
a causa di questa semplicità diventa reale. Se si utilizzano anche funzioni orientate agli oggetti e
al Web, il pericolo aumenta. Nei paragrafi che seguono vengono discussi alcuni dei pericoli che
progettisti e utenti dovrebbero considerare.
annuo. I costi di lavorazione, d’altro canto, hanno continuato a crescere, il che significa che
qualsiasi lavoro che possa essere trasferito da operatori umani alle macchine rappresenta un
buon investimento.
Come è stato applicato questo incredibile cambiamento alla progettazione di applicazioni?
Assolutamente non in maniera uniforme. Il vero progresso si è verificato negli ambienti, come
accadde inizialmente con il lavoro visionario svolto da Xerox presso il Palo Alto Research Center
(PARC), poi su Macintosh e ora nei browser Web e negli altri sistemi con interfaccia grafica
basati su icone. Questi ambienti sono molto più semplici da apprendere e comprendere rispetto
a quelli precedenti, basati su comandi scritti, e le persone che li utilizzano riescono a produrre in
pochi minuti ciò che prima richiedeva diversi giorni di lavoro. I progressi in alcuni casi sono stati
così rilevanti da far dimenticare quanto determinati compiti risultassero complessi in passato.
Purtroppo, questo concetto di ambiente semplice e agevole non è stato afferrato da molti
sviluppatori di applicazioni, che pur lavorando su questi ambienti, non abbandonano le vecchie
abitudini ormai inadeguate.
numeri, a parità di caratteri, occupano la metà dello spazio rispetto alle lettere, e i codici riduco-
no ancora di più le prestazioni richieste alla macchina.
Dato che le macchine erano costose, i progettisti dovettero utilizzare codici per ottenere che
ogni cosa funzionasse. Si trattava di una soluzione tecnica a un problema economico. Per gli
utenti costretti a imparare ogni genere di codici senza senso, la situazione era pressante. Le
macchine erano troppo lente e troppo costose per soddisfare gli uomini, perciò questi furono
addestrati per adattarsi alle macchine. Fu un male necessario.
Questa giustificazione economica svanì anni fa. I computer ora sono sufficientemente eco-
nomici e veloci per adattarsi al modo di lavorare degli uomini e utilizzare parole comprensibili
alle persone. Era ora che accadesse! Eppure, senza porsi il problema consapevolmente, sviluppatori
e progettisti continuano volenti o nolenti a utilizzare i codici.
Il primo punto, troppi articoli in ciascuna categoria, è più sostanziale, ma comunque molto
meno di quanto sembri a prima vista. Un’idea proposta è quella secondo la quale è necessario
minore sforzo (e quindi meno costo) per digitare codici numerici invece dei valori stringa effet-
tivi, come i titoli dei libri. Questa giustificazione non vale nel caso di Oracle. Non soltanto è più
costoso addestrare le persone a conoscere il codice corretto per clienti, prodotti, transazioni e
altro, senza contare il costo degli errori (che sono molti nei sistemi basati su codici); utilizzare i
codici significa anche non utilizzare Oracle in maniera completa. In Oracle è possibile digitare i
primi caratteri di un titolo e ottenere che il resto del nome venga inserito automaticamente. La
stessa operazione è possibile con nomi di prodotti, transazioni (una “a” può diventare automati-
camente “acquisto” e una “v” “vendita”) e così via, per tutta l’applicazione. Tutto ciò avviene
grazie a sofisticate capacità di ricerca dell’elemento appropriato.
zioni e le categorie naturali, e quindi creando con attenzione un database e uno schema di deno-
minazione che rifletta in maniera semplice e accurata queste scoperte.
Le fasi fondamentali di questo processo sono tre:
1. normalizzazione dei dati;
2. scelta delle denominazioni per le tabelle e le colonne;
3. scelta delle denominazioni per i dati.
Ciascuno di questi punti viene descritto seguendo l’ordine indicato. Lo scopo è quello di
sviluppare un’applicazione in cui i dati siano organizzati in tabelle e colonne con nomi familiari
agli utenti e in cui i dati stessi siano descritti con termini familiari, non con codici.
Normalizzazione
Le relazioni tra paesi, o tra settori di una società, o tra utenti e progettisti, sono solitamente il
prodotto di particolari circostanze storiche, che possono definire le relazioni attuali anche se tali
circostanze appartengono al passato remoto. Il risultato può essere quello di relazioni anormali,
oppure, secondo una definizione attuale, di disfunzioni. La storia e le circostanze spesso hanno
lo stesso effetto sui dati (sulle modalità con cui vengono raccolti, organizzati e riportati). Anche
i dati possono diventare anormali e presentare disfunzioni.
La normalizzazione è il processo che serve per riportare le cose alla dimensione corretta,
rendendole normali. L’origine del termine è la parola latina norma, che indicava una squadra da
carpentiere utilizzata per ottenere angoli retti. In geometria, quando una linea forma un angolo
retto con un’altra, si definisce “normale” rispetto a questa. In un database relazionale il termine
ha anche un preciso significato matematico, che riguarda il concetto di separazione degli ele-
menti dei dati (come nomi, indirizzi o compiti) in gruppi di affinità e che definisce la relazione
“normale” tra di essi.
I concetti di base della normalizzazione vengono presentati in questo contesto in modo che
gli utenti possano contribuire alla progettazione dell’applicazione che utilizzeranno, o compren-
dere meglio un’applicazione già impostata. Tuttavia, sarebbe un errore pensare che questo pro-
cesso sia veramente applicabile soltanto allo sviluppo di un database o ad un’applicazione per
computer. I processi di normalizzazione hanno per effetto una comprensione più profonda delle
informazioni utilizzate in una procedura e delle modalità di correlazione dei vari elementi che
compongono quelle informazioni. Ciò si dimostrerà utile anche in aree diverse da quella dei
database e dei computer.
Il modello logico
Una delle fasi iniziali del processo di analisi è la costruzione di un modello logico, che è sempli-
cemente un diagramma normalizzato dei dati utilizzati nella procedura. Conoscere i motivi e le
modalità per cui i dati vengono suddivisi e separati è essenziale per comprendere il modello, e
quest’ultimo è essenziale per creare un’applicazione che supporti la procedura per un lungo
periodo senza dover ricorrere a elementi aggiuntivi.
In genere si parla di normalizzazione in termini di forma: la prima, la seconda e la terza
forma normale sono le più comuni, laddove la terza rappresenta lo status più altamente norma-
lizzato. Esistono anche delle definizioni per il quarto e il quinto livello di normalizzazione,
tuttavia non rientrano nell’ambito della nostra discussione.
Si consideri una biblioteca: per ciascun libro è possibile memorizzare informazioni come
titolo, autore, editore e diverse categorie di termini descrittivi a esso relativi. Si supponga che
questi dati relativi ai libri diventino la struttura di una tabella in Oracle. La tabella potrebbe
essere chiamata BIBLIOTECA, mentre le colonne potrebbero essere Titolo, Editore, Autore1,
50 CAPITOLO 4
Autore2, Autore3, Categoria1, Categoria2 e Categoria3. Gli utenti di questa tabella hanno già un
problema: nella tabella BIBLIOTECA è possibile elencare solo tre autori o categorie per un
singolo libro.
Cosa accade quando l’elenco delle categorie accettabili cambia? Qualcuno sarà costretto a
scorrere tutte le categorie della tabella BIBLIOTECA e correggere i valori precedenti. E se uno
degli autori cambia nome? Ancora una volta è necessario modificare tutti i record correlati. E nel
caso in cui ci sia un quarto autore che contribuisce alla stesura di un libro?
I problemi appena elencati non sono questioni legate all’uso del computer o tecniche, anche
se vengono alla luce durante la progettazione di un database. Si tratta soprattutto di questioni di
base sulle modalità di organizzare in modo attento e logico le informazioni relative a un dato
compito mediante procedimenti di normalizzazione. Occorre riorganizzare passo dopo passo gli
elementi dei dati in gruppi di affinità, eliminando le relazioni non funzionali e stabilendo rela-
zioni normali.
Chiave primaria
per attuare l’intero processo. È sufficiente impostare i dati in modo che le colonne di ciascuna
tabella, invece che essere dipendenti dalla chiave primaria, siano dipendenti soltanto dalla chia-
ve primaria completa. La terza forma normale può essere quindi definita come “la chiave, la
chiave completa e nient’altro che la chiave”.
CLASSIFICAZIONE CATEGORIA
Classificazione NomeCategoria
DescrizioneClassificazione CategoriaPadre
SottoCategoria
AUTORE
NomeAutore Commenti
--------------------- -------------------------------------------
DIETRICH BONHOEFFER TEOLOGO TEDESCO, UCCISO IN CAMPO DI CONCENTRAMENTO
ROBERT BRETALL STUDIOSO DI KIERKEGAARD
ALEXANDRA DAY AUTRICE DI LIBRI ILLUSTRATI PER BAMBINI
STEPHEN JAY GOULD GIORNALISTA SCIENTIFICO, PROFESSORE AD HARVARD
SOREN KIERKEGAARD FILOSOFO E TEOLOGO DANESE
HARPER LEE ROMANZIERE AMERICANO, HA PUBBLICATO UN SOLO ROMANZO
LUCY MAUD MONTGOMERY SCRITTRICE CANADESE
JOHN ALLEN PAULOS PROFESSORE DI MATEMATICA
J. RODALE ESPERTO DI GIARDINAGGIO
CLASSIFICAZIONE
Classificazione DescrizioneClassificazione
--------------- --------------------------
1 EVASIONE
2 INFORMAZIONI DI BASE
3 CONSIGLIATO
4 VIVAMENTE CONSIGLIATO
5 LETTURA INDISPENSABILE
CATEGORIA
NomeCategoria CategoriaPadre SottoCategoria
------------- -------------- --------------
CONSADULTI ADULTI CONSULTAZIONE
NARRADULTI ADULTI NARRATIVA
SAGGIADULTI ADULTI SAGGI
ILLUSRAGAZZI RAGAZZI ILLUSTRATI
NARRRAGAZZI RAGAZZI NARRATIVA
SAGGIRAGAZZI RAGAZZI SAGGI
AUTORE_BIBLIOTECA
Titolo NomeAutore
------------------------------ ---------------------
TO KILL A MOCKINGBIRD HARPER LEE
WONDERFUL LIFE STEPHEN JAY GOULD
INNUMERACY JOHN ALLEN PAULOS
KIERKEGAARD ANTHOLOGY ROBERT BRETALL
KIERKEGAARD ANTHOLOGY SOREN KIERKEGAARD
ANNE OF GREEN GABLES LUCY MAUD MONTGOMERY
GOOD DOG, CARL ALEXANDRA DAY
LETTERS AND PAPERS FROM PRISON DIETRICH BONHOEFFER
BIBLIOTECA
Titolo Editore NomeCategoria Classificazione
------------------------------ --------------------- ------------- ------
TO KILL A MOCKINGBIRD HARPERCOLLINS NARRADULTI 5
WONDERFUL LIFE W.W.NORTON & CO. SAGGIADULTI 5
INNUMERACY VINTAGE BOOKS SAGGIADULTI 4
KIERKEGAARD ANTHOLOGY PRINCETON UNIV PR CONSADULTI 3
ANNE OF GREEN GABLES GRAMMERCY NARRRAGAZZI 3
GOOD DOG, CARL LITTLE SIMON ILLUSRAGAZZI 1
LETTERS AND PAPERS FROM PRISON SCRIBNER SAGGIADULTI 4
Quando si cerca To Kill A Mockingbird nella tabella BIBLIOTECA, si effettua una ricerca in
base alla chiave primaria di quest’ultima. Per trovare l’autore di questo libro, è sufficiente inver-
tire il percorso di ricerca precedente, cercando nella tabella AUTORE_BIBLIOTECA i record
che hanno quel valore nella colonna Titolo: questa colonna rappresenta una chiave esterna per la
tabella AUTORE_BIBLIOTECA. Quando la chiave primaria per BIBLIOTECA appare in un’altra
tabella, come avviene nella tabella AUTORE_BIBLIOTECA, essa prende il nome di chiave
esterna per quella tabella.
Osservando queste tabelle si possono anche trarre conclusioni sul mondo reale: ci sono
classificazioni e categorie non ancora utilizzate dai libri presenti nella biblioteca. Dato che i dati
sono organizzati in modo logico, è possibile mantenere un record delle categorie, delle classificazioni
e degli autori potenziali anche se nessuno dei libri attualmente presenti utilizza tali valori.
Si tratta di una forma di organizzazione dell’informazione di tipo logico e attento, anche se
le “tabelle” sono scritte in un libro mastro o su schede cartacee rudimentali. Naturalmente occor-
re ancora qualche aggiustamento per trasformare il tutto in un vero database. Per esempio,
NomeAutore probabilmente dovrebbe essere suddiviso in Nome e Cognome, e si potrebbe voler
trovare un modo per indicare l’autore principale oppure il fatto che ci sia un curatore al posto di
un autore.
Tutto questo processo viene definito normalizzazione e non è più complesso di quanto sia
stato illustrato finora. Benché per ottenere un buon risultato occorra analizzare anche altre que-
stioni, gli elementi fondamentali dell’analisi delle relazioni “normali” tra i vari elementi dei dati
sono effettivamente semplici come quelli appena presentati. La vera discriminante è costituita
dall’utilizzo o meno di un database relazionale o di un computer.
In ogni caso occorre una precisazione importante. La normalizzazione fa parte del processo
di analisi, non è la progettazione, che comprende molte altre considerazioni, ed è un errore grave
credere che le tabelle normalizzate del modello logico rappresentino il “progetto” effettivo per
un database. Questa confusione di fondo tra analisi e progetto contribuisce a creare le storie
riportate dalla stampa sul fallimento di grandi applicazioni relazionali. Questi problemi vengono
trattati in maniera specifica per gli sviluppatori più avanti nel capitolo.
Gli utenti sono in grado di comprendere il codice perché le parole utilizzate risultano fami-
liari, non si tratta di termini oscuri o mal definiti. Quando occorre definire tabelle con molte più
54 CAPITOLO 4
colonne, denominare queste ultime può essere più difficile, tuttavia alcuni principi cardine risul-
tano di grandissima utilità. Si considerino alcune delle difficoltà comunemente causate dalla
mancanza di convenzioni sui nomi. Che cosa accadrebbe se fossero stati scelti i nomi seguenti?
tipo di attenzione logica, altrimenti il compito di creare un’applicazione viene esplicato in ma-
niera impropria.
NOTA È possibile costringere Oracle a creare tabelle e colonne con nomi che
contengono lettere sia maiuscole sia minuscole, tuttavia questa pratica rende più complessa la
formulazione delle query e il lavoro con i dati. Si consiglia pertanto di utilizzare il comporta-
mento predefinito, che prevede l’uso del maiuscolo.
La capacità di dar vita a tabelle che distinguono tra maiuscole e minuscole viene indicata
come un vantaggio poiché, per esempio, permette ai programmatori di creare molte tabelle con
nomi simili. Si può creare una tabella lavoratore, una Lavoratore, una lAVORAtore e così via,
all’infinito. Sono tutte tabelle diverse. Come si può supporre però che qualcuno, compreso il
programmatore, sia in grado ricordare le differenze? In realtà è un difetto, non un vantaggio, e i
progettisti di Oracle sono stati abili nel non cadere in questa trappola.
Lo stesso discorso si può fare per i dati memorizzati in un database. Esistono modalità di
ricerca delle informazioni in un database senza distinzioni tra caratteri maiuscoli o minuscoli,
ma con questi metodi viene imposto un fardello non necessario. Tranne poche eccezioni, come i
testi di carattere legale o paragrafi di lettere modulari, è molto più semplice memorizzare i dati
nel database in caratteri maiuscoli. In questo modo le query sono più semplici e i report hanno un
aspetto più coerente. Se e quando è necessario che alcuni dati vengano digitati in minuscolo, o
utilizzando sia caratteri maiuscoli sia minuscoli (come nel caso di nome e indirizzo su una lette-
56 CAPITOLO 4
ra), allora si può ricorrere alle funzioni di Oracle che effettuano la conversione dei caratteri. È
generalmente meno complicato e crea meno confusione memorizzare e visualizzare i dati in
caratteri maiuscoli. È possibile interagire con Oracle in modi che consentono di utilizzare query
che non distinguono tra maiuscolo e minuscolo, ma in genere è più semplice sviluppare applica-
zioni effettuando scelte coerenti sull’uso di maiuscole e minuscole per i dati.
Se si ritorna indietro in questo capitolo, si osserverà che questa prassi non è stata seguita. Da
questo punto in poi, ora che l’argomento è stato introdotto e inquadrato nel contesto appropriato,
i dati del database saranno riportati in caratteri maiuscoli, con l’eccezione di una o due tabelle e
alcuni casi isolati.
Questo paragrafo è dedicato a stabilire quale metodo di approccio utilizzare per un progetto
di sviluppo che tenga in considerazione le operazioni commerciali effettive che l’utente finale
dev’essere in grado di eseguire. Tutto ciò differisce dal più comune orientamento ai dati di molti
sviluppatori e di numerose tecnologie di sviluppo. La normalizzazione dei dati e le tecnologie
CASE (Computer Aided Software Engineering) sono diventate a tal punto il centro d’attrazione
nello sviluppo di applicazioni relazionali, che il concentrarsi sui dati e sui problemi di integrità
referenziale, sulle chiavi, sulla normalizzazione e sui diagrammi delle tabelle è diventato quasi
un’ossessione. Tutti questi fattori vengono spesso confusi con la progettazione e, a volte, viene
spesso accolto con sorpresa il fatto che ciò che si crede essere progettazione si tratta, in realtà, di
analisi.
La normalizzazione è analisi, non progettazione. Essa rappresenta solo una parte dell’anali-
si necessaria per capire un’operazione commerciale e per costruire un’applicazione utile. Lo
scopo dello sviluppo di un’applicazione, in fondo, è quello di aiutare ad avere maggior successo
negli affari; l’obiettivo viene raggiunto migliorando la velocità e l’efficienza nell’adempiere le
operazioni commerciali e anche rendendo l’ambiente nel quale si lavora il più possibile signifi-
cativo e di aiuto. Date alle persone il controllo sulle proprie informazioni e un accesso intuitivo
e diretto a esse, e quelle persone risponderanno con gratitudine e produttività. Assegnate il con-
trollo a un gruppo remoto, rendete vaghe le informazioni per mezzo di codici e interfacce ostili
agli utenti, e le stesse persone saranno infelici e improduttive.
I metodi descritti in questo paragrafo non sono intesi come una trattazione rigorosa del
processo, e gli strumenti di trattamento delle strutture e dei flussi di dai che si utilizzano, e con
i quali si ha familiarità, sono probabilmente sufficienti per i propri scopi. Lo scopo che ci si
prefigge è quello di descrivere un approccio efficace per la creazione di applicazioni rapide,
adeguate e adattabili.
per computer? L’uso di esseri umani come periferiche di inserimento dei dati, in particolare per
dati voluminosi, di formato regolare (come avviene nei moduli) e con un ambito di variazione
limitato, rappresenta un costoso e antiquato, per non dire disumano, metodo di raccolta dei dati.
Come è successo per l’utilizzo di codici per adattarsi ai limiti della macchina, questa idea ha
fatto il suo tempo.
Quanto esposto può suonare come semplice filosofia, tuttavia ha una ricaduta pratica sul
modo in cui viene intrapresa la progettazione delle applicazioni. Le persone utilizzano i dati, ma
per svolgere dei compiti, e non possono portare a termine tali compiti uno per volta. Le persone
svolgono numerosi compiti che sono fasi secondarie gli uni degli altri, o che si intersecano tra
loro e devono svolgerli contemporaneamente, in parallelo.
Quando i progettisti acconsentono a fare in modo che sia questa idea a guidare l’analisi e la
creazione di un’applicazione, invece di concentrarsi sull’orientamento ai dati che è storicamente
stato dominante, l’autentica natura degli sforzi compiuti cambia in modo significativo. Gli am-
bienti a finestre hanno avuto il ben noto successo in quanto consentono all’utente di passare
rapidamente attraverso piccoli programmi, mantenendoli tutti attivi contemporaneamente senza
che sia necessario uscire da un programma per poterne avviare un altro. L’ambiente a finestre si
avvicina a una rappresentazione di come le persone in effetti pensano e lavorano più di quanto
non lo facesse il vecchio buon approccio di tipo “una cosa per volta”. La lezione che se ne ricava
non deve andare perduta. È su tale lezione, infatti, che si deve costruire.
Comprendere i compiti dell’applicazione significa andare ben oltre l’identificazione degli
elementi relativi ai dati, la loro normalizzazione e la creazione di finestre, programmi di elabo-
razione e report. La comprensione delle funzioni dell’applicazione significa comprendere che
cosa gli utenti fanno e quali siano i loro compiti, in modo da progettare un’applicazione che
risponda a tali esigenze, e non alla semplice esigenza di raccogliere i dati. In effetti, quando
l’orientamento è verso i dati, il progetto risultante distorce inevitabilmente i compiti dell’utente
anziché agevolarli.
Nel progettare applicazioni più reattive ai compiti che non ai dati, il trucco migliore consiste
nel comprendere semplicemente che ciò è necessario. In questo modo, l’approccio all’analisi di
un’applicazione economica è visto da una prospettiva nuova.
Il primo passo nell’analisi procedurale consiste nel comprendere i compiti da svolgere. Qual
è il compito per cui i membri di questo gruppo hanno effettivamente bisogno di utilizzare il
computer? Qual è il vero servizio o bene prodotto? Queste possono sembrare domande fonda-
mentali e persino semplicistiche, ma un numero sorprendentemente alto di uomini d’affari è
decisamente poco chiaro nelle risposte. Un gran numero di settori d’impresa, dalla sanità al
sistema bancario, dalle spedizioni alla produzione, è convinto di operare nel settore dell’elabora-
zione dei dati. Dopo tutto, in tali settori si inseriscono dati nei computer, li si elabora e se ne
traggono delle relazioni. Questo fraintendimento non è che un altro sintomo dell’orientamento
ai dati della progettazione dei nostri sistemi, orientamento che ha condotto decine di aziende a
tentare di commercializzare ciò che esse ritenevano essere il “vero” prodotto, l’elaborazione dei
dati, con risultati disastrosi per la maggior parte di esse.
Da ciò l'importanza di apprendere ciò che riguarda un’applicazione commerciale. Occorre
mantenere una buona apertura mentale, e spesso è necessario sfatare le opinioni preferite di
qualcuno sulla natura degli affari trattati, per scoprire la vera essenza di tale natura. Si tratta di un
processo utile, seppure a volte difficoltoso.
E proprio come è essenziale che gli uomini d’affari divengano utenti esperti del linguaggio
SQL e comprendano i fondamenti del modello relazionale, è altrettanto importante che i progettisti
di applicazioni comprendano realmente il servizio o prodotto fornito e i compiti necessari per
realizzarlo. Un gruppo di progettazione che comprenda utenti finali ai quali sono stati impartiti
i fondamenti del linguaggio SQL e dell’approccio relazionale, per esempio grazie alla lettura di
PIANIFICAZIONE DELLE APPLICAZIONI ORACLE 59
questo volume, e progettisti che siano sensibili alle esigenze degli utenti finali e comprendano il
valore di un ambiente applicativo orientato ai compiti da svolgere e sviluppato in un linguaggio
leggibile, consente di realizzare sistemi di qualità straordinariamente alta. I membri di un grup-
po di sviluppo di questo genere supporteranno e apporteranno miglioramenti agli sforzi degli
altri componenti.
Un tipo di approccio a questo processo prevede lo sviluppo di due documenti convergenti;
un documento dei compiti e un documento dei dati. È nella fase di preparazione della documen-
tazione dei compiti che entra in gioco la profonda comprensione dell’applicazione. La docu-
mentazione dei dati agevola l’implementazione della visione e assicura che si tengano presenti
tutti i dettagli e le regole, mentre il documento dei compiti definisce la visione di quale sia la
natura degli affari trattati.
C’è un’enorme tentazione di stipare in questa prima frase ogni più piccolo dettaglio sugli
affari trattati e sui sogni relativi. Questo non è il comportamento più opportuno. Lo sforzo di
tagliare gli eccessi descrittivi sino a ottenere una frase semplice mette meravigliosamente ordine
nella mente. Se non si è in grado di descrivere il lavoro in dieci parole, non lo si è ancora
compreso.
Il progetto dell’applicazione non è chiamato a creare da solo questa frase: il compito verrà
svolto in collaborazione con l’utente e darà inizio alla fase di documentazione dei compiti da
svolgere. La frase sintetica descrittiva dà l’opportunità di iniziare a riflettere seriamente su quali
siano gli affari trattati e su come vengano svolti. Questa fase è di grande valore per gli affari
stessi, a prescindere del fatto che ne venga realizzata un’applicazione. In questo modo si affron-
tano numerosi compiti principali e secondari, procedure e regole che alla prova si dimostreranno
senza significato o di importanza molto marginale. Normalmente questi sono retaggi sia di pre-
cedenti problemi, risolti da tempo, o di informazioni, o richieste di relazioni, da parte di dirigenti
da tempo non più presenti.
Qualche burlone ha suggerito che il metodo per risolvere il problema della creazione di un
numero troppo alto di relazioni sia quello di smettere semplicemente di produrle e stare a vedere
se qualcuno se ne accorge. Questa è una battuta, ma il nocciolo di verità in essa contenuto dovrà
fare parte del procedimento di documentazione dei compiti. Esso infatti si è dimostrato piuttosto
60 CAPITOLO 4
utile negli sforzi per rimediare al problema del passaggio all’anno 2000, in quanto per molti
programmi e report non è stato necessario apportare correzioni perché non erano più utilizzati.
L’approccio della cerchia di persone che si sforzano di documentare i compiti da svolgere
consente di porre domande decisamente scettiche e individuare (per valutarne l’utilità) ciò che
potrebbe essere un semplice retaggio. Il progettista deve comunque essere conscio del fatto che,
appunto in quanto tale, non può comprendere gli affari trattati nel modo approfondito in cui li
conosce l’utente. C’è una linea di demarcazione ben precisa tra afferrare l’opportunità, durante
il progetto di sviluppo di un’applicazione, per razionalizzare i compiti svolti e spiegarne i moti-
vi, e rischiare di offendere gli utenti presumendo di comprendere la “vera” natura dei loro affari
meglio di quanto essi stessi sappiano.
È necessario chiedere all’utente di descrivere ciascun compito in dettaglio e di spiegare la
ragione di ogni singolo passo. Se tale ragione è debole, quale “abbiamo sempre fatto così” o
“qualcuno utilizzerà pure questa cosa”, deve scattare il semaforo rosso. È consigliabile dire
chiaramente che non si capisce e chiedere una nuova spiegazione. Se la risposta resta
insoddisfacente, si annoti il compito e la domanda posta su un elenco separato, per una succes-
siva risoluzione. Ad alcune delle domande verrà risposto semplicemente da qualcuno che cono-
sce meglio la materia, altre richiederanno colloqui con i dirigenti più esperti, alla fine numerosi
compiti verranno eliminati in quanto non più necessari. Una prova della validità di un procedi-
mento di analisi è il miglioramento delle procedure esistenti, a prescindere dall’implementazione
di una nuova applicazione informatica, e normalmente molto prima di essa.
a termine indipendentemente. Se due compiti dipendono sempre l’uno dall’altro, tali compiti
non sono inscindibili. Il vero compito inscindibile li comprende ambedue.
Nella maggioranza degli affari si scopre rapidamente che numerosi compiti non rientrano
perfettamente in uno solo dei compiti principali (livello zero), ma sembrano allargarsi a due o
più compiti principali e funzionano in modo reticolare o “trasversale”. Tale situazione è pratica-
mente sempre la prova dell’impropria definizione dei compiti principali o dell’incompleta
inscindibilità dei compiti di livello più basso. L’obiettivo è quello di trasformare ciascun compi-
to in un “oggetto” concettuale, con un’idea ben definita di cosa fa (il suo scopo nella vita) e di
quali risorse (dati, calcolo, pensiero, carta, penna e via dicendo) utilizza per raggiungere i propri
scopi.
lizzo che viene fatto del dato inserito, tale elemento dev’essere annotato nell’elenco dei proble-
mi da risolvere. Questo procedimento elimina una quantità enorme di cose non necessarie.
Una volta identificati, gli elementi relativi ai dati devono essere esaminati accuratamente. I
codici numerici e alfabetici sono sempre sospetti. Essi nascondono vere informazioni dietro
simboli non intuitivi e senza significato proprio. Esistono momenti e compiti in cui i codici sono
comodi, facili da ricordare o resi necessari da grandi volumi. Ma nella progettazione finale que-
sti casi devono essere rari e ovvi. Se così non è, significa che si è smarrita la retta via.
Nel vaglio degli elementi relativi ai dati esistenti, i codici devono essere oggetto di una
particolare attenzione. In ciascun caso è necessario domandarsi perché tale dato debba essere
espresso con un codice. Il continuo utilizzo del dato sotto forma di codice dev’essere visto con
sospetto. Per mantenere la codifica devono esserci buoni motivi e ragioni di forza maggiore. Il
procedimento per convertire i dati codificati nella lingua locale è piuttosto semplice, ma è frutto
di uno sforzo congiunto. I codici vengono in primo luogo elencati, per elemento di dato, insieme
al loro significato. I codici vengono quindi esaminati da utenti e progettisti, e brevi versioni in
italiano dei significati vengono proposte, discusse e approvate in via provvisoria.
Durante la stessa discussione, i progettisti e gli utenti finali devono decidere i nomi degli
elementi informativi. Tali nomi sono destinati a diventare nomi di colonne nel database e ad
essere utilizzati regolarmente nelle query. I nomi devono pertanto essere descrittivi (evitando le
abbreviazioni, a parte quelle comuni in ambito commerciale) e singolari. A causa dell’intima
relazione tra il nome della colonna e i dati in questa contenuti, i due nomi devono essere speci-
ficati contemporaneamente. La scelta ragionata del nome di una colonna semplifica di gran
lunga la determinazione del nome ai suoi nuovi contenuti in lingua.
Devono essere rigorosamente esaminati anche i dati non rappresentati da codici. A partire da
ciò ci sono ottime ragioni per credere che tutti gli elementi di dati identificati siano necessari per
le operazioni commerciali da svolgere, ma che essi non siano necessariamente ben organizzati.
Ciò che appare essere un elemento di dati nel compito esistente può in effetti rivelarsi come un
gruppo di più elementi mescolati tra di loro e che richiedano di essere separati. I nomi, gli
indirizzi e i numeri di telefono sono esempi molto comuni di tale situazione, ma in ogni applica-
zione se ne possono trovare innumerevoli altri.
Nomi e cognomi sono stati mischiati, per esempio, nella tabella AUTORE. La tabella
NomeAutore conteneva sia il nome, sia il cognome, anche se le tabelle erano nella terza forma
normale. Questo sarebbe stato un modo estremamente farraginoso per implementare realmente
un’applicazione, malgrado il fatto che le regole di normalizzazione venissero tecnicamente ri-
spettate. Per rendere un’applicazione pratica e preparare l’applicazione stessa per query in italia-
no, la colonna NomeAutore dev’essere scomposta in almeno due colonne nuove, Cognome e
Nome. Lo stesso procedimento di suddivisione in categorie è regolarmente necessario per la
razionalizzazione di altri elementi di dati ed è spesso decisamente indipendente dalla
normalizzazione.
Il grado di scomposizione dipende da come i particolari elementi di dati vengono probabil-
mente utilizzati. È possibile spingersi troppo avanti e operare la suddivisione in categorie che,
per quanto formate da pezzi separabili, non danno nessun ulteriore vantaggio nel loro nuovo
stato. La suddivisione dipende dall’applicazione e dev’essere valutata elemento per elemento.
Una volta terminata la suddivisione, ai nuovi elementi creati, destinati a diventare colonne, de-
v’essere assegnato un nome adeguato, e i dati che essi contengono devono essere esaminati. I
dati di testo che ricadano entro un numero definito di valori devono essere revisionati per l’asse-
gnazione di un nome. Tali nomi di colonne e valori, come quelli dei codici, risultano essere
provvisori.
PIANIFICAZIONE DELLE APPLICAZIONI ORACLE 63
Il modello commerciale
A questo punto, sia chi progetta l’applicazione, sia gli utenti finali dovrebbero avere una chiara
visione degli affari trattati, dei relativi compiti da svolgere e dei dati utilizzati. Una volta corretto
e approvato il modello commerciale, il processo di sintesi dei compiti e dei modelli di dati in un
modello commerciale complessivo ha inizio. Questa parte del procedimento ordina gli elementi
di dati comuni a più compiti, completa la normalizzazione finale su larga scala e individua nomi
coerenti e definitivi per tutte le parti.
Tutto ciò può essere un’operazione di portata decisamente vasta per le applicazioni princi-
pali, con documentazione di supporto che comprende i compiti, i modelli di dati (con nomi
corretti per gli elementi, basati sul modello completo) e un elenco di tutte le tabelle a scala intera
e dei relativi nomi delle colonne, tipi di dati e contenuti. La verifica finale degli sforzi prodigati
avviene seguendo il percorso di accesso ai dati di ciascuna transazione nel modello commerciale
completo, per fare in modo che tutti i dati richiesti per la transazione siano disponibili per la
selezione o l’inserimento e che nessun compito preveda l’inserimento di dati essenziali per l’in-
tegrità referenziale del modello, con elementi mancanti.
Fatta eccezione per gli sforzi devoluti nell’individuazione di nomi adeguati per le varie
tabelle e colonne e per i valori comuni, praticamente tutto quanto fatto sino a questo punto fa
parte dell’analisi e non della progettazione. L’obiettivo è la promozione della comprensione
degli affari trattati e delle relative componenti.
altro, se necessario. In termini pratici, tutto ciò comporta spesso l’utilizzo di una tabella princi-
pale utilizzata dal compito, e di altre tabelle sulle quali possano essere eseguite query per ricava-
re i valori cercati o che potranno essere aggiornate in caso di accesso alla tabella principale.
Vi sono però anche occasioni in cui semplicemente non esiste una tabella principale, ma al
suo posto sono presenti numerose tabelle correlate, ciascuna delle quali fornisce o riceve dati a
supporto del compito svolto. Tali finestre appaiono e si comportano in modo decisamente diver-
so da quelle tipiche orientate alla tabella sviluppate per molte applicazioni, ma ampliano in
modo significativo l’efficienza del lavoro dei propri utenti e i relativi contributi alle operazioni
commerciali. E questo è precisamente l’unico scopo del nostro approccio.
L’interazione tra utente e macchina è fondamentale, le maschere di inserimento e le query
devono essere coerentemente orientate ai compiti e descrittive, in lingua corrente. Anche l’uti-
lizzo di icone e interfacce grafiche gioca un ruolo importante. Le maschere devono riflettere il
modo con cui il lavoro viene effettivamente portato a termine ed essere costruite in modo da
rispondere nella lingua in cui gli affari vengono trattati.
Query e report
Se c’è qualcosa che distingue l’approccio relazionale e il linguaggio SQL da ambienti applicati-
vi più tradizionali, è la possibilità per gli utenti finali di imparare ed eseguire agevolmente query
ad hoc. Si tratta di report e di query occasionali che non fanno parte del gruppo di base normal-
mente sviluppato e fornito insieme al codice dell’applicazione.
Con SQL*Plus, una utility a linea di comando per la creazione e l’interrogazione di oggetti
di database, gli utenti finali ottengono un controllo senza precedenti sui propri dati. Sia gli
utenti, sia gli sviluppatori beneficiano di tale possibilità: gli utenti perché vengono messi in
grado di costruire dei report, analizzare le informazioni, modificare le query ed eseguirle nuova-
mente nel giro di pochi minuti; gli sviluppatori in quanto vengono sollevati dall’indesiderato
compito di creare nuovi report.
Agli utenti viene consentito di osservare in profondità i propri dati, analizzarli e rispondere
con una velocità e un’immediatezza inimmaginabile solo pochi anni or sono. Questo salto di
produttività viene grandemente aumentato se le tabelle, le colonne e i valori dei dati sono scru-
polosamente riportati in italiano, mentre viene enormemente pregiudicato se si permette a catti-
ve convenzioni per l’assegnazione dei nomi e a codici e abbreviazioni senza senso di inficiare il
progetto. Il tempo impiegato nel procedimento del progetto per assegnare agli oggetti nomi
coerenti e descrittivi in italiano viene presto ricompensato dagli utenti e di conseguenza dall’an-
damento degli affari.
Alcuni, normalmente chi non ha mai realizzato applicazioni relazionali di grandi dimensio-
ni, temono che il passaggio dei dispositivi di query agli utenti finali possa sovraccaricare la
macchina su cui tali dispositivi vengono utilizzati. Si teme che gli utenti scrivano query ineffica-
ci che consumano un numero esorbitante di cicli della CPU, rallentando la macchina e tutti gli
altri utenti. L’esperienza mostra che ciò non è sempre vero. Gli utenti imparano rapidamente a
capire quali tipi di query funzionano rapidamente e quali no. Inoltre, la maggior parte degli
strumenti di business intelligence e di generazione di report attualmente disponibili sono in
grado di stimare la quantità di tempo necessaria per l’esecuzione di una query e di limitare
l’accesso, in base all’utente, all’ora del giorno o ad entrambi i criteri, alle query che consume-
rebbero una quantità sproporzionata di risorse. In pratica, le fatiche imposte dagli utenti a una
macchina sfuggono loro di mano solo occasionalmente, mentre i benefici ottenuti superano di
gran lunga i costi in termini di elaborazione. Praticamente ogniqualvolta sia possibile spostare
uno sforzo da una persona a una macchina, si risparmia denaro.
PIANIFICAZIONE DELLE APPLICAZIONI ORACLE 65
Lo scopo effettivo del progetto è quello di rendere chiare e soddisfare le esigenze commer-
ciali e degli utenti. Se deve esistere un’imparzialità, questa dovrà sempre essere orientata a ren-
dere l’applicazione più semplice da comprendere e utilizzare, in particolare a spese della CPU o
del disco, ma in misura minore se il prezzo di ciò è una complessità interna tanto grande che la
manutenzione e le modifiche diventano difficoltose e lente.
lunghezza coerenti, rendendo l’implementazione più congruente in tutta l’impresa. Tuttavia l’uso
dei tipi di dati astratti in questo modo implica l’adozione delle seguenti pratiche:
■ una corretta definizione dei tipi di dati sin dall’inizio, in modo da evitare la necessità di
modificare un tipo di dato in un secondo momento;
■ supporto dei requisiti di sintassi dei tipi di dati astratti.
Chiavi esterne
Una difficoltà dell’uso di nomi di colonna brevi è la comparsa occasionale di una chiave esterna
in una tabella in cui vi sia un’altra colonna che ha lo stesso nome della chiave esterna nella
propria tabella di base. Una possibile soluzione a lungo termine consiste nel consentire l’utilizzo
del nome completo della chiave esterna, incluso il nome della tabella di base di quest’ultima,
come nome della colonna nella tabella locale (come per esempio BIBLIOTECA.Titolo come
nome di colonna).
La necessità pratica di risolvere i problemi legati a colonne con lo stesso nome richiede di
intraprendere una delle azioni seguenti.
■ Inventare un nome che comprenda la tabella sorgente della chiave esterna senza utilizzare il
punto (per esempio ricorrendo al trattino di sottolineatura).
■ Inventare un nome che incorpori un’abbreviazione della tabella sorgente della chiave esterna.
■ Inventare un nome differente da quello utilizzato nella tabella sorgente.
■ Cambiare il nome della colonna che crea conflitto.
Nessuna delle soluzioni precedenti è particolarmente allettante, ma se si incorre in un dilem-
ma di nomi identici, è necessario adottare una di queste soluzioni.
Nomi singolari
Un’area di grande confusione è rappresentata dalla domanda se gli oggetti debbano avere nomi
singolari o plurali. Tabella AUTORE o AUTORI? Colonna Nome o Nomi?
Esistono due modalità che vengono in aiuto nella risoluzione di questo problema. Per prima
cosa si considerino alcune colonne comuni a quasi ogni database: Nome, Indirizzo, Citta, Pro-
vincia, Cap. A parte la prima, a qualcuno è mai capitato di vedere i nomi di queste colonne scritti
al plurale? È praticamente scontato, quando si considerano i nomi di queste colonne, che essi
descrivano il contenuto di un’unica riga, un record. Anche se i database relazionali sono “orien-
tati agli insiemi”, è chiaro che l’unità fondamentale di un insieme è una riga ed è al contenuto di
questa riga che fanno riferimento i nomi singolari delle colonne. Il progetto di una schermata di
inserimento dei dati per catturare il nome e l’indirizzo di una persona potrebbe essere simile al
seguente?
Nomi: _______________________________________________________
Indirizzi: ___________________________________________________
Oppure i nomi delle colonne vengono scritti al singolare sullo schermo, poiché si riferisco-
no al nome e all’indirizzo di una persona alla volta, mentre occorre avvisare l’utente che quando
scrive le query deve convertirli al plurale? è sicuramente molto più intuitivo e lineare specificare
i nomi delle colonne al singolare.
PIANIFICAZIONE DELLE APPLICAZIONI ORACLE 67
Se tutti gli oggetti sono stati denominati in modo coerente, né il progettista né l’utente deve
cercare di ricordare le regole secondo cui utilizzare il plurale oppure no. Il vantaggio dovrebbe
essere ovvio. Si supponga di decidere che d’ora in poi tutti gli oggetti saranno plurali. Si avranno
“i”, o “e” come finali del nome di ciascun oggetto, magari anche alla fine di ciascuna parola nei
nomi lunghi composti da più parole. Che vantaggi può portare questa scelta? Tutto ciò è facile da
utilizzare, da capire, da ricordare? Ovviamente no!
La soluzione migliore pertanto è la seguente: tutti i nomi di oggetti sono sempre singolari.
L’unica eccezione a questa regola è rappresentata da qualunque termine ampiamente accettato e
già comunemente utilizzato nel mondo degli affari, come “vendite”.
Brevità
Come si è già detto in precedenza, la chiarezza non dovrebbe mai essere sacrificata a beneficio
della concisione, ma dati due nomi ugualmente significativi, mnemonici e descrittivi, conviene
sempre scegliere il più breve. Durante lo sviluppo delle applicazioni, conviene proporre nomi di
colonne e tabelle alternativi come quelli presentati al gruppo di utenti e sviluppatori e ascoltare
le loro proposte per quanto riguarda la scelta del nome più chiaro. Come si fa a costruire un
elenco di alternative? Si può utilizzare un dizionario normale e uno dei sinonimi. In un gruppo di
lavoro dedicato a sviluppare applicazioni produttive superiori, a ciascun membro dovrebbe esse-
re fornito un dizionario e un dizionario dei sinonimi e ricordata più volte l’importanza di asse-
gnare con cura i nomi agli oggetti.
altri codici e altro. Inoltre, le difficoltà che si riscontrano con le chiavi sovraccariche si applicano
anche a colonne non chiave costruite con più di una porzione di dati significativi.
Una descrizione tipica di una chiave sovraccarica o di un valore di colonna è la seguente: “Il
primo carattere rappresenta il codice della regione. I successivi quattro caratteri rappresentano il
numero del catalogo. La cifra finale è il codice del costo centrale, a meno che questo non sia una
parte importata, nel qual caso una ‘I’ viene accodata al numero, o a meno che si tratti di un
elemento voluminoso, per esempio viti, in cui vengono utilizzate solo tre cifre per il numero del
catalogo e il codice della regione è HD”.
L’eliminazione delle chiavi sovraccariche e dei valori delle colonne è essenziale in un buon
progetto di tipo relazionale. Le dipendenze costruite su parti di queste chiavi (solitamente chiavi
esterne in altre tabelle) sono tutte a rischio nel caso di manutenzione della struttura. Sfortunata-
mente, molte aree applicative possiedono chiavi sovraccariche che sono state utilizzate per anni
e sono profondamente inglobate nell’attività della società. Alcune di esse vennero create durante
i primi tentativi di automazione, con database che non erano in grado di gestire colonne a più
chiavi per chiavi composte. Altre derivano da un retaggio storico, che utilizza codici brevi, soli-
tamente numerici, per gestire più significati e coprire più casi di quanti non ne fossero inizial-
mente previsti. L’eliminazione di chiavi sovraccariche esistenti può avere conseguenze pratiche
che ne rendono impossibile l’attuazione immediata. Ciò rende più difficile la costruzione di una
nuova applicazione relazionale.
La soluzione a questo problema consiste nel creare un nuovo gruppo di chiavi, sia primarie
sia esterne, che normalizzino in modo appropriato i dati; successivamente è necessario assicurar-
si che gli utenti possano accedere alle tabelle solo attraverso queste chiavi. La chiave sovracca-
rica viene quindi mantenuta come una colonna aggiuntiva e unica della tabella. L’accesso a
quest’ultima è ancora possibile utilizzando i metodi passati (per esempio trovando le corrispon-
denze della chiave sovraccarica in una query), ma le chiavi con la nuova struttura vengono sug-
gerite come metodo preferenziale di accesso ai dati. Nel tempo, con un addestramento opportu-
no, gli utenti si rivolgeranno verso queste nuove chiavi. Alla fine, le chiavi sovraccariche (e gli
altri valori di colonna sovraccarichi) potranno semplicemente essere annullate (impostandole a
NULL) o rimosse dalla tabella.
Se non si riescono a eliminare chiavi e valori sovraccarichi, si incrementa notevolmente il
costo e la difficoltà di operazioni quali l’estrazione di informazioni dal database, la convalida dei
valori, l’integrità dei dati e la modifica della struttura.
4.14 Il decalogo
A questo punto tutti i principali problemi legati alla progettazioni di applicazioni destinate a un
ambiente produttivo sono stati analizzati. Probabilmente è utile riassumere gli aspetti affrontati
in un unico elenco, ed ecco così “Il decalogo”. La loro presentazione non ha alcun intento di dire
al lettore ciò che dovrebbe fare, ma piuttosto dà per scontato che egli sia in grado di apportare
modifiche razionali e possa beneficiare dell’esperienza di altri che hanno affrontato le stesse
sfide. Lo scopo non è quello di descrivere il ciclo di sviluppo, che il lettore probabilmente cono-
sce già fin troppo bene, ma piuttosto quello di influenzare questo sviluppo con un orientamento
che modifichi radicalmente il modo in cui appare e viene utilizzata l’applicazione. Se si tengono
nella dovuta considerazione queste idee, è possibile migliorare notevolmente la produttività e
l’umore degli utenti di un’applicazione
Ecco quindi i dieci comandamenti della progettazione.
PIANIFICAZIONE DELLE APPLICAZIONI ORACLE 69
1. Far partecipare gli utenti. Inserirli nel gruppo di progettazione e insegnare loro il modello
relazionale e SQL.
2. Scegliere i nomi delle tabelle, delle colonne e delle chiavi assieme agli utenti. Sviluppare un
dizionario dei sinonimi per l’applicazione in modo da assicurare nomi coerenti.
3. Utilizzare parole significative, facilmente memorizzabili, descrittive, brevi e al singolare. Se
si utilizzano i trattini di sottolineatura, lo si faccia coerentemente, oppure non li si utilizzi affatto.
4. Non mescolare tra loro livelli differenti all’interno dei nomi.
5. Evitare l’utilizzo di codici e abbreviazioni.
6. Utilizzare chiavi significative dove possibile.
7. Scomporre le chiavi sovraccariche.
8. Effettuare l’analisi e la progettazione tenendo conto delle operazioni richieste, non sola-
mente dei dati. Tenere presente che la normalizzazione non fa parte della progettazione.
9. Spostare le operazioni da svolgere dagli utenti alla macchina. È utile spendere di più in cicli
e operazioni di memorizzazione, se si ottiene una maggiore facilità di utilizzo.
10. Non farsi tentare dalla velocità di sviluppo. Dedicare tempo e attenzione all’analisi, alla
progettazione, alle prove e alla messa a punto.
C’è un motivo ben preciso per cui si è scelto di proporre questo capitolo prima di quelli
dedicati a comandi e funzioni: se la progettazione è di scarso livello, l’applicazione ne soffrirà a
prescindere dai comandi utilizzati. La pianificazione deve quindi mirare alla funzionalità, alle
prestazioni, alle capacità di recupero, alla sicurezza e alla disponibilità, tenendo come fine ulti-
mo il successo.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Parte seconda
SQL E SQL*PLUS
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 5
Le parti fondamentali
del discorso in SQL
5.1 Stile
5.2 Creazione della tabella GIORNALE
5.3 Uso di SQL per selezionare dati
da tabelle
5.4 I comandi select, from, where e order by
5.5 Logica e valore
5.6 Un altro impiego delle subquery
con where
5.7 Combinazione di tabelle
5.8 Creazione di una vista
C
on SQL (Structured Query Language), è possibile interroga-
re Oracle per ottenere le informazioni che si desidera selezionare (select), inserire (insert), ag-
giornare (update) o cancellare (delete). Questi sono i quattro verbi fondamentali che si utilizza-
no per fornire istruzioni a Oracle. A partire da Oracle9i è inoltre possibile utilizzare un comando
aggiuntivo, merge, per eseguire operazioni di inserimento e aggiornamento con un singolo co-
mando. Con Oracle Database 10g, le capacità del comando merge sono state ampliate in modo
da includere un maggiore controllo sulle operazioni di inserimento, aggiornamento e persino di
cancellazione effettuate nell’ambito di una singola istruzione. Sempre a partire dall’ultima ver-
sione di Oracle questi comandi di base sono stati ulteriormente potenziati in modo da offrire
supporto per le query di versione flashback e altre funzionalità.
Nella Parte prima si è visto che cosa si intende con il termine “relazionale”, come vengono
organizzate le tabelle in colonne e righe e come dare istruzioni a Oracle per selezionare determi-
nate colonne da una tabella e visualizzare le informazioni contenute riga dopo riga. In questo
capitolo e nei seguenti viene illustrata in maniera più completa l’esecuzione di queste procedure
per i diversi tipi di dati supportati da Oracle. In questa parte viene spiegato come interagire con
SQL*Plus, un prodotto di Oracle molto potente che consente di raccogliere le istruzioni fornite
dall’utente, controllarne la correttezza e quindi sottoporle a Oracle, e successivamente modifica-
re o riformulare la risposta fornita da Oracle sulla base degli ordini o delle direttive impartiti.
All’inizio comprendere la differenza tra ciò che viene eseguito da SQL*Plus e ciò che viene
eseguito da Oracle può apparire un po’ complicato, soprattutto perché i messaggi di errore pro-
dotti da Oracle vengono semplicemente passati all’utente da SQL*Plus; tuttavia, proseguendo
con la lettura di questo testo le differenze risulteranno più evidenti. Nelle fasi di apprendimento
SQL*Plus può essere considerato come un semplice collaboratore, un assistente che segue le
istruzioni dell’utente e lo aiuta a eseguire il lavoro in maniera più veloce. L’interazione con
questo collaboratore avviene semplicemente digitando con la tastiera.
Si possono seguire gli esempi proposti in questo capitolo e nei seguenti semplicemente
digitando i comandi illustrati, ottenendo dai programmi Oracle e SQL*Plus esattamente le stes-
74 CAPITOLO 5
se risposte. Occorre tuttavia assicurarsi che le tabelle utilizzate in questo testo siano state carica-
te nella propria copia di Oracle.
In ogni caso è possibile comprendere le procedure descritte anche senza effettivamente met-
terle in pratica; per esempio, è possibile utilizzare i comandi illustrati sulle proprie tabelle. Tut-
tavia tutto risulterà probabilmente più chiaro e più semplice se si utilizzano in Oracle le stesse
tabelle proposte in questo testo e ci si esercita impostando le stesse query.
Il CD-ROM allegato al libro contiene le istruzioni per caricare tali tabelle. Presupponendo
che ciò sia già stato fatto, è possibile connettersi a SQL*Plus e iniziare a lavorare digitando:
sqlplus
(Se si desidera eseguire SQL*Plus dal proprio computer desktop client, occorre selezionare
l’opzione di programma SQL Plus dall’opzione di menu Application Development sotto l’opzio-
ne di menu del software Oracle). Così facendo viene avviato SQL*Plus (si osservi che non è
necessario digitare l’asterisco * situato a metà della denominazione ufficiale del prodotto e che
l’asterisco non appare nemmeno nel nome del programma. Dal momento che in Oracle sono
previsti accurati strumenti di protezione dei dati memorizzati, quando ci si connette è necessario
immettere un ID e una password. Viene visualizzato un messaggio di copyright e quindi la ri-
chiesta di nome utente e password. Occorre connettersi al database utilizzando l’account e la
password creati per contenere le tabelle di esempio. Quando si forniscono un nome utente e una
password validi, viene visualizzato un messaggio che segnala che l’utente è connesso a Oracle e
quindi il seguente prompt:
SQL>
significa che sono stati inseriti in maniera errata il nome utente o la password, oppure che il
proprio nome utente non è stato ancora impostato nella copia di Oracle in uso. Dopo tre tentativi
di inserimento di nome utente o di password falliti, SQL*Plus blocca il tentativo di connessione
visualizzando questo messaggio:
quit
5.1 Stile
Innanzi tutto, alcune osservazioni sullo stile. Per SQL*Plus non è importante se i comandi SQL
vengono digitati in maiuscolo o minuscolo. Per esempio, il comando:
LE PARTI FONDAMENTALI DEL DISCORSO IN SQL 75
Nei capitoli successivi del libro si vedrà come interpretare tutte le clausole di questo coman-
do. Per il momento lo si può leggere nel modo seguente: “Creare una tabella chiamata GIORNA-
LE, che avrà tre colonne denominate Argomento (una colonna di caratteri a lunghezza variabi-
le), Sezione (una colonna di caratteri a lunghezza fissa) e Pagina (una colonna numerica). I
76 CAPITOLO 5
valori della colonna Argomento possono avere una lunghezza massima di 15 caratteri e tutte le
righe devono avere un valore. I valori di Sezione avranno tutti lunghezza pari a un carattere”.
Nei capitoli successivi si vedrà come estendere questo semplice comando in modo da ag-
giungere vincoli, indici e storage clause (clausole di memorizzazione). Per il momento, la tabel-
la GIORNALE verrà mantenuta il più possibile semplice in modo che gli esempi possano con-
centrarsi sul linguaggio SQL.
ARGOMENTO S PAGINA
--------------- - ----------
Notizie A 1
Sport D 1
Editoriali A 12
Economia E 1
Meteo C 2
Televisione B 7
Nascite F 7
Annunci F 8
Vita moderna B 1
Fumetti C 4
Film B 4
Bridge B 2
Necrologi F 6
Salute F 6
14 rows selected.
Che cosa c’è di diverso tra la tabella creata in precedenza e quella visualizzata nell’output
della Figura 5.1? In entrambe sono riportate le stesse informazioni, ma il formato cambia e
l’ordine delle righe può essere diverso. Per esempio, le intestazioni di colonna sono leggermente
diverse da quelle richiamate con il comando select.
Si osservi che la colonna denominata Sezione appare indicata soltanto con la lettera S; inol-
tre, anche se sono state utilizzate lettere maiuscole e minuscole per digitare la linea di comando:
Annunci F 8
Bridge B 2
Economia E 1
Editoriali A 12
Film B 4
Fumetti C 4
Meteo C 2
Nascite F 7
Necrologi F 6
Notizie A 1
Salute F 6
Sport D 1
Televisione B 7
Vita moderna B 1
presupposizioni, tuttavia finché non si assegnano modalità diverse, ecco come viene trasformato
da SQLPLUS ciò che l’utente digita:
■ tutte le intestazioni di colonna sono riportate in caratteri maiuscoli;
■ l’ampiezza delle colonne è fissata dal valore definito in Oracle;
■ vengono eliminati gli spazi tra le parole, se l’intestazione di colonna rappresenta una funzio-
ne (come verrà dimostrato nel Capitolo 7).
Il primo punto risulta evidente: i nomi di colonna digitati sono visualizzati in caratteri maiu-
scoli. Il secondo punto non è così ovvio. Come vengono definiti i parametri per le colonne? Per
scoprirlo, è sufficiente chiederlo a Oracle. È sufficiente chiedere a SQL*Plus di descrivere la
tabella, come illustrato di seguito:
describe GIORNALE
Viene visualizzata una tabella descrittiva in cui sono elencate le colonne e la loro definizio-
ne per quanto concerne la tabella GIORNALE; il comando describe funziona per qualsiasi ta-
bella. Si osservi che i dettagli di questa descrizione corrispondono al comando create table
fornito in precedenza nel capitolo.
Nella prima colonna sono indicate le denominazioni delle colonne nella tabella descritta.
Nella seconda colonna, Null?, viene indicata la regola seguita per la colonna citata a sinistra.
Al momento della creazione della tabella GIORNALE, la regola NOT NULL ha indicato a Oracle
di non consentire ad alcun utente di aggiungere una nuova riga alla tabella nel caso in cui la
colonna Argomento risulti vuota (NULL significa vuoto). Forse in una tabella come GIORNALE
sarebbe stato opportuno impostare la stessa regola per tutte e tre le colonne. Che senso ha cono-
78 CAPITOLO 5
scere il titolo di un argomento senza sapere in quale sezione e in quale pagina si trova? Tuttavia,
per questioni di semplicità, in questo caso solo la colonna Argomento è stata impostata con la
regola specifica di non poter essere vuota.
Il fatto che Sezione e Pagina non abbiano nessun parametro nella colonna Null? significa
che queste colonne della tabella GIORNALE possono avere delle righe vuote.
Nella terza colonna, Type, sono contenute informazioni sulla natura delle singole colonne.
Argomento è una colonna di tipo VARCHAR2 (numero di caratteri variabile) in cui possono
essere inseriti fino a 15 caratteri (lettere, numeri, simboli o spazi).
Anche Sezione è una colonna in cui è possibile inserire caratteri, tuttavia può contenerne
uno solo. Chi ha creato la tabella sapeva che le sezioni del giornale sono rappresentate con una
singola lettera, per cui la colonna è stata definita con l’ampiezza strettamente necessaria. È stato
inoltre impostato il tipo di dati CHAR, utilizzato per stringhe di caratteri di lunghezza prefissata.
Quando SQL*Plus ha visualizzato il risultato della query impostata:
Oracle ha trasmesso l’informazione che la colonna Sezione poteva contenere al massimo un solo
carattere. Si è quindi presupposto che non fosse necessario utilizzare uno spazio maggiore di
quello impostato, per cui è stata visualizzata una colonna con ampiezza sufficiente per un solo
carattere e il nome della colonna è stato conseguentemente ridotto alla sola iniziale: in questo
caso soltanto la lettera S.
La terza colonna della tabella GIORNALE è Pagina e contiene semplicemente un numero.
Si osservi che la colonna Pagina viene visualizzata con ampiezza pari a dieci caratteri, anche se
non ci sono pagine il cui numero ha più di due cifre: per i numeri generalmente non viene
definita un’ampiezza massima, per cui viene automaticamente impostata una larghezza suffi-
ciente per iniziare.
Inoltre il margine dell’intestazione della sola colonna composta unicamente da numeri, Pa-
gina, è allineato a destra, mentre le intestazioni delle colonne che contengono caratteri sono
allineate a sinistra. Si tratta dell’allineamento delle intestazioni di colonna impostato da SQL*Plus.
È possibile modificare le caratteristiche di allineamento a seconda delle necessità, come avviene
con le altre caratteristiche che riguardano il formato delle colonne.
Infine, con SQL*Plus è possibile sapere quante righe sono presenti nella tabella GIORNA-
LE di Oracle (si osservi l’annotazione “14 rows selected” nella parte sottostante la tabella GIOR-
NALE). Questa caratteristica viene chiamata feedback. È possibile impostare SQL*Plus in modo
da non visualizzare questi messaggi impostando l’opzione feedback nel modo illustrato di se-
guito:
set feedback 25
Con quest’ultimo esempio si indica a Oracle che non si desidera conoscere il numero di
righe visualizzate se questo non è almeno 25. Se non si specifica un valore diverso, l’opzione
feedback è impostata a 6.
set è un comando di SQL*Plus, ovvero si tratta di un’istruzione che indica a SQL*Plus le
modalità da seguire. Sono molte le caratteristiche di SQL*Plus che è possibile impostare, come
feedback; diverse vengono illustrate e utilizzate in questo capitolo e in quelli seguenti. Per un
elenco completo, è possibile consultare la voce set nel Capitolo 48.
LE PARTI FONDAMENTALI DEL DISCORSO IN SQL 79
Il comando set ha una controparte nel comando show, con il quale vengono visualizzate le
istruzioni impostate. Per esempio, si possono verificare le impostazioni di feedback digitando:
show feedback
Anche il parametro dell’ampiezza impostata per visualizzare i numeri è stato modificato con
il comando set. Si può verificarlo digitando:
show numwidth
numwidth 9
Dato che il valore 9 rappresenta una larghezza ampia per la visualizzazione di numeri di
pagine che non contengono mai più di due cifre, si può restringerla digitando quanto segue:
set numwidth 5
Ciò tuttavia implica che tutte le colonne di numeri siano di ampiezza pari a cinque caratteri.
Se si prevede di dover utilizzare numeri con più di cinque cifre, occorre impostare un valore più
alto. Le singole colonne visualizzate possono essere impostate anche indipendentemente l’una
dall’altra. Questo argomento verrà trattato nel Capitolo 6.
ARGOMENTO S PAGINA
--------------- - ------
Nascite F 7
Annunci F 8
Necrologi F 6
Salute F 6
80 CAPITOLO 5
Viene controllata ogni riga della tabella GIORNALE prima della visualizzazione, saltando
le righe che non riportano unicamente la lettera ‘F’ nella colonna Sezione. Vengono invece sele-
zionate e visualizzate le righe in cui la Sezione è ‘F’.
Per indicare a Oracle che si desidera che le informazioni vengano visualizzate in un determi-
nato ordine, si utilizza il comando order by. Si possono richiedere vari gradi di selezione nell’or-
dine. Si considerino questi esempi:
ARGOMENTO S PAGINA
--------------- - ------
Annunci F 8
Nascite F 7
Necrologi F 6
Salute F 6
Se si ordina per pagina, la sequenza viene quasi capovolta, come illustrato qui di seguito:
ARGOMENTO S PAGINA
--------------- - ------
Salute F 6
Necrologi F 6
Nascite F 7
Annunci F 8
Nell’esempio seguente, le righe vengono innanzi tutto ordinate per pagina (si osservi nel-
l’elenco precedente la sequenza ordinata soltanto per pagina). Successivamente vengono ordina-
te per argomento, elencando “Necrologi” prima di “Salute”.
ARGOMENTO S PAGINA
--------------- - ------
Necrologi F 6
Salute F 6
Nascite F 7
Annunci F 8
Anche con order by è possibile invertire l’ordine normale, come in questo caso:
ARGOMENTO S PAGINA
--------------- - ------
Annunci F 8
LE PARTI FONDAMENTALI DEL DISCORSO IN SQL 81
Nascite F 7
Necrologi F 6
Salute F 6
La parola chiave desc sta per descending (decrescente). In questo caso segue la parola “Pa-
gina” nella riga di order by, quindi significa che i numeri delle pagine devono essere visualizzati
in ordine decrescente. L’effetto ottenuto sarebbe lo stesso sulla colonna Argomento, se si inseris-
se la parola chiave desc dopo “Argomento” nella riga di order by.
Si osservi che i comandi select, from, where e order by presentano modalità specifiche nella
strutturazione delle parole che seguono. In termini relazionali, i gruppi di parole che compren-
dono queste parole chiave sono spesso definiti clausole, come mostrato nella Figura 5.2.
ARGOMENTO S PAGINA
--------------- - ------
Necrologi F 6
Salute F 6
Il segno di uguale prende il nome di operatore logico, perché opera effettuando una verifica
logica, ovvero confrontando i valori posti alla sua sinistra e alla sua destra, in questo caso il
valore Pagina e il valore 6, per controllare se sono uguali.
In questo esempio il valore da verificare non è stato racchiuso tra doppi apici, perché la
colonna nella quale il valore dev’essere verificato (la colonna Pagina) è stata definita come tipo
di dati NUMBER. Per i valori numerici non è necessario digitare doppi apici per effettuare la
verifica.
Dato che su alcune tastiere manca il punto esclamativo o l’accento circonflesso (^), Oracle preve-
de tre modi per specificare l’operatore di disuguaglianza. L’alternativa finale, <>, va considerata
come operatore di disuguaglianza perché filtra i numeri minori di 6 (in questo esempio) o maggiori
di 6, ma non il 6.
LIKE
Argomento LIKE ‘Vi%’ Argomento inizia con le lettere ‘Vi’.
Argomento LIKE ‘__I%’ Argomento ha una ‘I’ nella terza posizione.
Argomento LIKE ‘%0%0%’ Argomento contiene due ‘o’.
LIKE esegue una ricerca per modelli. Un carattere di sottolineatura rappresenta uno e un solo
carattere. Un segno di percentuale rappresenta un numero qualsiasi di caratteri, anche zero.
NULL consente di verificare se in una riga di una colonna esistono dati. Se la colonna è comple-
tamente vuota, è NULL. Con NULL e NOT NULL va utilizzato IS, perché con essi i segni di uguale,
maggiore o minore non funzionano.
ARGOMENTO S PAGINA
--------------- - ------
Televisione B 7
Vita moderna B 1
Film B 4
Bridge B 2
ARGOMENTO S PAGINA
--------------- - ------
Editoriali A 12
Televisione B 7
Nascite F 7
Annunci F 8
Necrologi F 6
Salute F 6
Il test seguente riguarda le sezioni maggiori di B (ovvero con lettere che seguono B nell’or-
dine alfabetico):
ARGOMENTO S PAGINA
--------------- - ------
Sport D 1
Economia E 1
Meteo C 2
Nascite F 7
Annunci F 8
Fumetti C 4
Necrologi F 6
Salute F 6
Si può impostare un test per valori maggiori di un valore dato, o anche per valori minori,
come mostrato di seguito:
ARGOMENTO S PAGINA
--------------- - ----------
Notizie A 1
Sport D 1
Economia E 1
Meteo C 2
Televisione B 7
Nascite F 7
Vita moderna B 1
84 CAPITOLO 5
Fumetti C 4
Film B 4
Bridge B 2
Necrologi F 6
Salute F 6
L’opposto della verifica di uguaglianza è la verifica “diverso da”, come in questo esempio:
ARGOMENTO S PAGINA
--------------- - ----------
Editoriali A 12
Meteo C 2
Televisione B 7
Nascite F 7
Annunci F 8
Fumetti C 4
Film B 4
Bridge B 2
Necrologi F 6
Salute F 6
LIKE
Una delle caratteristiche logiche più potenti di SQL è un operatore straordinariamente efficace
denominato LIKE, con il quale è possibile effettuare una ricerca nelle righe di una colonna di un
database per valori che assomigliano a un dato pattern descritto. Vengono utilizzati due caratteri
speciali per contrassegnare il tipo di verifica da effettuare: il segno di percentuale, detto caratte-
re jolly, e un trattino di sottolineatura detto marcatore di posizione. Per trovare tutti gli argomen-
ti che iniziano con la lettera ‘N’ si procede in questo modo:
ARGOMENTO S PAGINA
--------------- - ----------
Nascite F 7
Necrologi F 6
Il segno di percentuale (%) significa che qualsiasi carattere può essere accettato in quella
posizione: un carattere, cento o nessuno. Se la prima lettera è ‘N’, viene visualizzata la riga
LE PARTI FONDAMENTALI DEL DISCORSO IN SQL 85
trovata mediante l’operatore LIKE. Se invece fosse stata utilizzata ‘n%’ come condizione di ri-
cerca, allora non sarebbe stata visualizzata nessuna riga, poiché le lettere minuscole e maiuscole
nei valori dei dati devono essere indicate con precisione.
Se si desidera trovare gli argomenti in cui compare la lettera ‘i’ come terza lettera del titolo,
senza alcuna condizione riguardo ai due caratteri precedenti e a quelli seguenti, si utilizzano due
trattini di sottolineatura ( _ _ ) per specificare che qualsiasi carattere precedente è accettabile.
Nella posizione tre deve trovarsi una ‘i’ minuscola; il segno di percentuale indica che qualsiasi
carattere è accettabile nella posizione seguente.
ARGOMENTO S PAGINA
--------------- - ----------
Editoriali A 12
Bridge B 2
Si possono anche utilizzare più segni di percentuale. Per trovare le parole in cui siano pre-
senti due ‘o’ minuscole in qualsiasi posizione, vengono utilizzati tre segni di percentuale, come
in questo esempio:
ARGOMENTO S PAGINA
--------------- - ----------
Necrologi F 6
Si confronti la query con la stessa query in cui però l’elemento da ricercare è rappresentato
da due ‘i’:
ARGOMENTO S PAGINA
--------------- - ----------
Editoriali A 12
Televisione B 7
Questa funzionalità di ricerca può avere un ruolo importante nel rendere un’applicazione
più facile da utilizzare, semplificando le ricerche per nome, prodotto, indirizzo e altri elementi
che potrebbero essere ricordati solo parzialmente. Nel Capitolo 8 si vedrà come utilizzare le
ricerche avanzate di espressioni regolari disponibili a partire da Oracle Database 10g.
Con la query seguente si possono facilmente scoprire la città e le date in cui le precipitazioni
non sono state misurate:
È possibile utilizzare gli operatori relazionali (=, != e così via) con NULL, ma questo tipo di
condizione non fornisce risultati significativi. Occorre utilizzare IS o IS NOT per operare con
NULL.
Con numeri:
ARGOMENTO S PAGINA
--------------- - ----------
Notizie A 1
Editoriali A 12
Televisione B 7
Nascite F 7
Annunci F 8
Vita moderna B 1
Film B 4
Bridge B 2
Necrologi F 6
Salute F 6
ARGOMENTO S PAGINA
--------------- - ----------
Sport D 1
Economia E 1
Meteo C 2
Fumetti C 4
ARGOMENTO S PAGINA
--------------- - ----------
Televisione B 7
Nascite F 7
Annunci F 8
88 CAPITOLO 5
Questi test logici possono anche essere combinati, come in questo caso:
ARGOMENTO S PAGINA
--------------- - ----------
Annunci F 8
Il comando AND è stato utilizzato per combinare due espressioni logiche; ogni riga esami-
nata viene verificata per entrambi i parametri; sia “Sezione = ‘F’”, sia “Pagina > 7” devono
essere vere perché una riga venga visualizzata. In alternativa si può utilizzare OR: in questo caso
vengono visualizzate le righe che soddisfano almeno una delle due espressioni logiche:
ARGOMENTO S PAGINA
--------------- - -------
Editoriali A 12
Nascite F 7
Annunci F 8
Necrologi F 6
Salute F 6
Nell’esempio precedente alcune righe vengono visualizzate anche se la Sezione non è ugua-
le a ‘F’, perché il numero di Pagina è maggiore di 7, mentre altre sono visualizzate anche se il
numero di Pagina è minore o uguale a 7, perché la Sezione corrispondente è uguale a ‘F’.
Infine si possono selezionare le righe nella Sezione F tra la pagina 7 e la pagina 10 impo-
stando la seguente query:
ARGOMENTO S PAGINA
--------------- - -------
Nascite F 7
Annunci F 8
Sono disponibili anche altri operatori a più valori il cui utilizzo è più complesso; verranno
illustrati nel Capitolo 9. È anche possibile consultare il Capitolo 48 per trovare ulteriori informa-
zioni al riguardo.
Si supponga di voler trovare nel giornale le rubriche che risultano più nascoste, quelle che
sono da qualche parte dopo la pagina 2 della sezione A o B. Si potrebbe provare così:
ARGOMENTO S PAGINA
--------------- - -------
Notizie A 1
Editoriali A 12
Televisione B 7
Film B 4
Si osservi che il risultato ottenuto non è quello desiderato. In qualche modo, la pagina 1
della sezione A è stata inclusa nelle righe visualizzate. Come si spiegano questi risultati? Esiste
un modo per ottenere da Oracle una risposta corretta? Anche se gli operatori AND e OR sono
entrambi connettori logici, AND è prevalente, perché collega le espressioni logiche alla sua sini-
stra e alla sua destra in maniera più forte di quanto accada con OR (tecnicamente, si dice che ha
precedenza superiore). Ciò significa che la clausola where:
viene interpretata in italiano come “dove Sezione = ‘A’, o dove Sezione = ‘B’ e Pagina > 2”.
Se si osserva l’esempio con risultato errato proposto in precedenza, si può verificare quale effet-
to ha avuto questa interpretazione sul risultato. L’operatore AND viene sempre considerato per
primo.
Si può superare questo ostacolo utilizzando delle parentesi che racchiudano le espressioni
da interpretare insieme. Le parentesi prevalgono sull’ordine di precedenza normale:
ARGOMENTO S PAGINA
------------------ - ------
Editoriali A 12
Televisione B 7
Film B 4
Ora il risultato visualizzato è esattamente quello desiderato. Si osservi che, benché sia pos-
sibile digitare la stessa espressione con le sezioni citate all’inizio, il risultato è identico perché le
parentesi indicano a Oracle quali sono gli elementi da interpretare insieme. Si confrontino inve-
ce i risultati diversi ottenuti cambiando l’ordine nel primo esempio, in cui non venivano utilizza-
te le parentesi.
90 CAPITOLO 5
S
-
F
ARGOMENTO
---------------
Nascite
Annunci
Necrologi
Salute
L’argomento “Salute” è collocato nella sezione F insieme agli altri visualizzati. Le due query
impostate potevano essere combinate insieme? Sì, come nell’esempio seguente:
ARGOMENTO
---------------
Nascite
Annunci
Necrologi
Salute
valore singolo e non funziona con elenchi di valori; quindi, se la subquery ha per risultato più di
una riga, viene visualizzato un messaggio di errore come questo:
Tutti gli operatori logici che si utilizzano per verificare valori singoli possono funzionare
nelle subquery, a patto che il risultato di queste sia una riga singola. Per esempio, si può chiedere
di visualizzare tutte le rubriche nel giornale che si trovino in sezioni contrassegnate da lettere
“minori” (ossia in posizione precedente nell’alfabeto) della sezione in cui si trova l’argomento
“Salute”. L’asterisco dopo select è un’abbreviazione per richiedere tutte le colonne in una tabel-
la senza doverle elencare una per una. Le colonne vengono visualizzate nell’ordine in cui sono
state create originariamente nella tabella.
ARGOMENTO S PAGINA
--------------- - -------
Notizie A 1
Sport D 1
Editoriali A 12
Economia E 1
Meteo C 2
Televisione B 7
Vita moderna B 1
Fumetti C 4
Film B 4
Bridge B 2
10 rows selected.
In questo giornale locale altre dieci rubriche sono poste prima dell’argomento “Salute”.
CITTA PAESE
-------------------------- ---------------------------
ATENE GRECIA
92 CAPITOLO 5
CITTA CONDIZIONE
----------- -----------
LIMA PIOGGIA
PARIGI NUVOLOSO
MANCHESTER NEBBIA
ATENE SOLE
CHICAGO PIOGGIA
SYDNEY SOLE
SPARTA NUVOLOSO
CITTA
-----------
PARIGI
SPARTA
Successivamente si crea un elenco che comprenda quelle città e lo si utilizza per impostare
una query riguardante la tabella DISLOCAZIONE:
CITTA PAESE
-------------------------- ---------------------------
PARIGI FRANCIA
SPARTA GRECIA
Lo stesso risultato si ottiene impostando una subquery, in cui si utilizza il comando select
tra parentesi per creare l’elenco di città verificate mediante l’operatore IN, come mostrato di
seguito:
CITTA PAESE
-------------------------- ---------------------------
PARIGI FRANCIA
SPARTA GRECIA
Gli altri operatori a valori multipli funzionano in maniera analoga. Il compito fondamentale
è quello di creare una subquery che produca un elenco che possa essere verificato logicamente.
È importante considerare i seguenti aspetti.
■ La subquery deve avere una sola colonna, oppure deve confrontare le colonne selezionate
con le diverse colonne poste tra parentesi nella query principale (per ulteriori informazioni, si
consulti il Capitolo 13).
■ La subquery dev’essere racchiusa tra parentesi.
■ Le subquery che hanno come risultato soltanto una riga possono essere utilizzate sia con
operatori a valori singoli, sia con operatori a valori multipli.
■ Le subquery che hanno come risultato più di una riga possono essere utilizzate soltanto con
operatori a valori multipli.
Se sono necessari dei riferimenti geografici più precisi, occorre interrogare la tabella
DISLOCAZIONE:
Ci sono molte più informazioni di quelle necessarie, però mancano le informazioni sul tem-
po. Eppure le tabelle CLIMA e DISLOCAZIONE hanno una colonna in comune: Citta. È quindi
possibile collegare le informazioni delle due tabelle unendole. È sufficiente utilizzare una query
con where per indicare a Oracle ciò che le due tabelle hanno in comune:
Si osservi che le righe presenti in questa tabella combinata sono quelle che riportano i valori
delle stesse città presenti in entrambe le tabelle originarie. La query con where funziona con la
stessa logica esaminata in precedenza nel caso della tabella GIORNALE. Si tratta ovviamente
della relazione logica tra le due tabelle che è stata impostata mediante la query digitata. È come
dire “seleziona le righe nella tabella CLIMA e nella tabella DISLOCAZIONE in cui le città sono
uguali”. Se una città è riportata soltanto in una tabella, manca il termine di uguaglianza nell’altra
tabella. La notazione utilizzata con il comando select è TABELLA.NomeColonna, in questo caso
CLIMA.Citta.
Mediante il comando select vengono selezionate le colonne delle due tabelle che si desidera
vedere visualizzate insieme; qualsiasi colonna in una delle due tabelle che non è stata richiesta
viene semplicemente ignorata. Se nella prima riga fosse stato scritto semplicemente:
non sarebbe stato possibile per Oracle determinare la città cui si faceva riferimento. In questo
caso Oracle avrebbe visualizzato un messaggio in cui si segnalava il nome di colonna Citta come
ambiguo. La sintassi corretta della query con select è “CLIMA.Citta” oppure “DISLOCA-
ZIONE.Citta”. In questo esempio, utilizzare una o l’altra alternativa non fa alcuna differenza,
tuttavia vi sono casi in cui colonne con nome identico di due o più tabelle contengono dati molto
diversi.
Nella clausola where è inoltre necessario indicare i nomi delle tabelle accanto al nome iden-
tico della colonna mediante la quale le due tabelle vengono combinate: “dove clima punto città
LE PARTI FONDAMENTALI DEL DISCORSO IN SQL 95
equivale a dislocazione punto città”, ovvero, dove la colonna Citta della tabella CLIMA equivale
alla colonna Citta nella tabella DISLOCAZIONE.
Si osservi che il prodotto della combinazione delle due tabelle ha l’aspetto di un’unica tabella
con sette colonne e sette righe. Tutto ciò che è stato escluso impostando la query non compare
nella nuova visualizzazione. Non ci sono colonne Umidita, anche se una colonna con questo
nome fa parte della tabella CLIMA. Non ci sono colonne Paese, anche se una colonna con questo
nome fa parte della tabella DISLOCAZIONE. Inoltre, delle 14 città della tabella DISLOCA-
ZIONE, sono presenti in questa tabella soltanto quelle della tabella CLIMA. Utilizzando la
clausola where, gli altri elementi non sono stati selezionati.
Una tabella creata combinando colonne da più tabelle viene talvolta definita proiezione o
tabella risultante.
View created.
Ora si può agire esattamente come se INVASIONE fosse una vera tabella con le proprie
righe e colonne. Si può anche impostare una query per ottenere da Oracle la descrizione della
nuova tabella:
describe INVASIONE
È anche possibile interrogare direttamente la tabella (si osservi che non occorre specificare
da quale tabella sono tratte le colonne Citta, perché questa relazione logica è implicita nella
vista):
Alcune funzioni di Oracle utilizzabili su una tabella comune non possono invece essere
usate su una vista, ma sono poche e per lo più riguardano la modifica di righe e l’impostazione di
indici di tabelle, argomenti che vengono discussi nei capitoli successivi. Nella maggior parte dei
casi, una vista può dare risultati ed essere manipolata esattamente come qualsiasi altra tabella.
NOTA Le viste non contengono dati, che invece sono contenuti nelle tabelle. Ben-
ché sia possibile creare “viste materializzate” che contengono dati, esse sono effettivamente
delle tabelle, non delle viste.
Si supponga ora che non sia più necessario avere informazioni su Chicago o altre città fuori
dalla Grecia; pertanto, si cerca di modificare in tal senso la query. La seguente impostazione può
funzionare?
Perché? Anche se Paese è una colonna effettiva di una delle tabelle originarie della vista
INVASIONE, non si trova nella parte selezionata durante la creazione della vista. È proprio
come se non esistesse. Quindi, occorre tornare al comando create view per includere nella nuova
tabella soltanto la Grecia.
View created.
Utilizzando il comando create or replace view è possibile creare una nuova versione della
vista senza perdere quella precedente. Con questo comando risulta più semplice amministrare i
privilegi di utente per accedere alla vista, come viene descritto nel Capitolo 18.
LE PARTI FONDAMENTALI DEL DISCORSO IN SQL 97
La logica della clausola where ora è stata ampliata per includere entrambe le tabelle di
origine e un test a valore singolo su una colonna in una delle tabelle di origine. Ora è possibile
impostare la query per Oracle e ottenere questa risposta:
In questo modo è possibile avvertire gli ateniesi della probabile apparizione degli spartani
da sud-ovest, accaldati e stanchi per la marcia. Impostando qualche operazione di trigonometria
è anche possibile calcolare la distanza percorsa.
Se l’utente imposta la query per DISLOCAZIONI_PERU, non gli sarà possibile visualizzare
nessuna riga di un paese diverso dal Perù.
Le query utilizzate per definire le viste possono anche fare riferimento a pseudocolonne.
Una pseudocolonna è una “colonna” che restituisce un valore quando viene selezionata, ma non
è un’autentica colonna di una tabella. Selezionando la pseudocolonna User, viene sempre
visualizzato il nome dell’utente di Oracle che ha impostato la query. Pertanto, se una colonna
della tabella contiene nomi utente, tali valori potranno essere confrontati con la pseudocolonna
User per applicare restrizioni alle relative righe, come nell’esempio seguente. In questo esem-
pio, viene eseguita una query sulla tabella NOME. Se il valore della colonna omonima è identico
al nome dell’utente che ha impostato la query, allora vengono visualizzate le righe.
98 CAPITOLO 5
Questo tipo di vista risulta molto utile quando gli utenti richiedono l’accesso a determinate
righe di una tabella; in questo modo non possono vedere tutte le righe che corrispondono al loro
nome utente per Oracle.
Le viste sono strumenti molto potenti. Questo argomento verrà trattato in maniera più ap-
profondita nel Capitolo 17.
La clausola where può essere utilizzata per unire due tabelle che hanno una colonna comu-
ne. L’insieme di dati risultante può essere trasformato in una vista (con una nuova denominazio-
ne), che può essere trattata come se fosse a sua volta una tabella normale. L’efficacia di una vista
si rivela nella possibilità di limitare o modificare le modalità di visualizzazione dei dati da parte
di un utente, mantenendo immutate le tabelle originarie.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 6
Report e comandi
fondamentali
di SQL*PLUS
S
QL*Plus viene generalmente considerato uno strumento per
manipolare dati ed effettuare query ad hoc sui database; può anche fungere da compilatore di
report interattivo. Questo strumento utilizza SQL per ottenere informazioni dal database Oracle
e offre la possibilità di creare report in quanto permette di gestire facilmente titoli, intestazioni di
colonna, totali parziali e totali, riformattazione di numeri e testo e molto altro ancora. Inoltre,
può essere utilizzato per modificare il database tramite i comandi insert, update e delete in SQL.
SQL*Plus può anche essere impiegato come generatore di codice: con una serie di comandi si
può creare dinamicamente un programma e quindi eseguirlo.
La maggior parte delle applicazioni di produzione adotta compilatori di report più avanzati,
come report costruiti su parametri legati al Web. SQL*Plus viene utilizzato molto più comune-
mente per semplici query e report stampati. Per fare in modo che SQL*Plus formatti le informa-
zioni nei report secondo il proprio gusto e le proprie esigenze è sufficiente qualche comando,
delle parole chiave che diano istruzioni a SQL*Plus su come operare. Questi comandi sono
elencati nella Tabella 6.1, mentre nel Capitolo 48 è possibile trovare esempi, spiegazioni detta-
gliate e caratteristiche aggiuntive per ciascuno di questi comandi.
In questo capitolo verrà presentato un semplice report compilato con SQL*Plus e verranno
illustrate le caratteristiche utilizzate per crearlo. Se la creazione di un report risulta all’inizio un
po’ faticosa, non è il caso di preoccuparsi. Una volta provati i diversi passaggi della procedura,
questi risulteranno semplici da comprendere e diventeranno presto familiari.
È possibile compilare report SQL*Plus mentre si lavora in maniera interattiva con SQL*Plus;
ossia si possono digitare comandi riferiti a intestazioni di pagina, titoli di colonna, formattazione,
interruzioni, totali e così via, per poi eseguire una query SQL, e SQL*Plus produrrà immediata-
mente il report formattato secondo le indicazioni specificate. Si tratta di un approccio interes-
sante nel caso di risposte rapide a domande semplici che non hanno probabilità di essere riproposte.
Accade più spesso tuttavia di dover generare report complessi che devono essere prodotti perio-
dicamente, e soprattutto che sia necessario stamparli invece di visualizzarli semplicemente sullo
schermo. Purtroppo, quando si esce da SQL*Plus, vengono immediatamente dimenticate tutte le
istruzioni impostate. Se si utilizzasse SQL*Plus soltanto in questa modalità interattiva, l’esecu-
zione successiva dello stesso report significherebbe inserire nuovamente tutti i dati.
L’alternativa è molto semplice: digitare i comandi in un file linea per linea. SQL*Plus potrà
poi leggere questo file come se si trattasse di uno script, ed eseguire i comandi come se venissero
digitati. In effetti ciò equivale alla creazione di un programma di report senza ricorrere a un
programmatore o ad un compilatore. Questo file viene creato con uno qualsiasi dei comuni
editor disponibili, o anche (con alcune limitazioni) con un elaboratore di testi.
100 CAPITOLO 6
set headsep Il separatore di titolo identifica il singolo carattere che indica a SQLPLUS di suddividere un titolo in due o
più righe.
column Fornisce a SQLPLUS una varietà di istruzioni su titolo, formato e trattamento di una colonna.
break on Indica a SQLPLUS dove inserire degli spazi tra le sezioni di un report o dove interrompere per subtotali e
totali.
set linesize Imposta il massimo numero di caratteri consentiti su qualsiasi riga del report.
spool Reindirizza in un file un report che normalmente verrebbe visualizzato sullo schermo, in modo che sia
possibile stamparlo.
/**/ Contrassegna l’inizio e la fine di un commento in una query SQL. È simile a remark.
-- Contrassegna l’inizio di un commento in linea in una query SQL. Tutto quanto si trova dal contrassegno
alla fine della riga è considerato un commento. È simile a remark.
save Salva la query SQL che si sta creando nel file indicato.
L’editor non fa parte di Oracle. Questi editor sono disponibili in centinaia di varietà e ognu-
no ha il suo preferito. Oracle si è resa conto di questa situazione e ha deciso di permettere
all’utente di scegliere l’editor da utilizzare invece di fornire un editor integrato e obbligare gli
utenti a usarlo. Quando si è pronti per utilizzare il proprio editor, è necessario sospendere
SQL*Plus, passare all’editor, creare o modificare il programma di report di SQL*Plus (detto
anche file di avvio), quindi ritornare a SQL*Plus esattamente nel punto in cui lo si era lasciato ed
eseguire quel report (Figura 6.1).
In SQL*Plus è disponibile anche un editor incorporato, talvolta definito editor a linea di
comando, che consente di modificare rapidamente una query SQL senza uscire da SQL*Plus.
L’uso dell’editor verrà illustrato più avanti in questo capitolo.
REPORT E COMANDI FONDAMENTALI DI SQL*PLUS 101
mioeditor
FILE
AVVIO
SQLPLUS (programma
report)
SQL>edit activity.sql
che SQLPLUS
SQL>start activity.sql
può eseguire
per produrre
un report
activity.1st
Figura 6.2
REPORT
remark
La prima linea della Figura 6.3, contrassegnata dal numero 1, è la documentazione relativa al file
di avvio. Le linee di documentazione iniziano con
rem
(abbreviazione di remark). SQL*Plus ignora qualsiasi cosa si trovi in una linea che inizia con
queste lettere, il che consente di aggiungere commenti, annotazioni e spiegazioni a qualunque
file di avvio creato. È sempre opportuno introdurre questi commenti all’inizio del file di avvio,
indicando il nome del file, l’autore e la data di creazione, il nome di chi ha apportato modifiche,
102 CAPITOLO 6
Giorni
NOME TITOLO DPRESTITO DRESTITUZ Fuori
-------------------- -------------------- --------- --------- -------
DORAH TALBOT EITHER/OR 02-JAN-02 10-JAN-02 8.00
POLAR EXPRESS 01-FEB-02 15-FEB-02 14.00
GOOD DOG, CARL 01-FEB-02 15-FEB-02 14.00
MY LEDGER 15-FEB-02 03-MAR-02 16.00
******************** -------
avg 13.00
-------
avg 22.58
dalla Biblioteca
la data delle modifiche, gli elementi modificati e una breve spiegazione dello scopo del file. Si
tratta di un accorgimento che si rivela indispensabile in seguito, quando si sviluppano report più
complessi o quando iniziano ad accumularsi decine di report.
REPORT E COMANDI FONDAMENTALI DI SQL*PLUS 103
set headsep
La punteggiatura al termine della linea set headsep (“heading separator”, separatore di intesta-
zione), contrassegnata dal numero 2 nella Figura 6.3, indica a SQL*Plus come verrà segnalato il
punto in cui si intende interrompere un titolo di pagina o un’intestazione di colonna che siano
più lunghi di una riga. La prima volta che si attiva SQL*Plus, il carattere headsep predefinito è
una barra verticale ( | ), tuttavia se si preferisce usare le barre verticali nei titoli, nulla vieta di
utilizzare un carattere headsep differente.
set headsep !
set headsep ! 2
set linesize 80 10
set pagesize 60
set newpage 0
set feedback off
spool activity.lst 11
spool off
L’ istruzione di selezione visibile verso la fine della Figura 6.3, che inizia con il termine “select”
e termina con un punto e virgola (;), è espressa in SQL, il linguaggio utilizzato per dialogare
con il database Oracle. Ogni altro comando visibile nella pagina è un comando SQL*Plus, utiliz-
zato per formattare i risultati di una query SQL in un report.
Il comando start fa in modo che SQL*Plus legga il file activity.sql ed esegua le istruzioni presenti
in esso. Osservando con attenzione, ci si accorge che questo file di avvio contiene le istruzioni
SQL*Plus di base da utilizzare per produrre report o modificare le modalità con cui si interagisce
con SQL*Plus. In relazione all’esperienza di ciascuno, questo file può apparire avanzato o di
livello elementare; è costituito da una serie di istruzioni semplici per SQL*Plus.
La Figura 6.3 mostra il file di avvio SQL*Plus che ha prodotto questo report (in questo caso
activity.sql). Per eseguire questo programma per report in SQL*Plus è necessario digitare quanto
segue:
start activity.sql
ttitle e btitle
Si consideri la riga seguente:
qui vengono date istruzioni a SQL*Plus per impostare questo titolo di testa (top title) all’inizio di
ogni pagina del report. Il titolo scelto dovrà essere racchiuso tra apici. Si consideri la riga se-
guente:
essa funziona in maniera analoga alla precedente con ttitle, tranne per il fatto che il titolo deve
essere posto in fondo alla pagina (“b” sta per “bottom”, in fondo); anche questa notazione de-
v’essere racchiusa tra apici. Dato che gli apici servono per racchiudere il titolo intero, un apo-
strofo (che sulla tastiera corrisponde allo stesso carattere) ingannerebbe SQL*Plus facendogli
credere erroneamente che il titolo è finito.
Quando si utilizza ttitle nel modo illustrato, SQL*Plus centrerà sempre il titolo scelto in base
alle dimensioni di linea impostate (linesize verrà trattato più avanti in questo capitolo) e inserirà
sempre nell’angolo superiore sinistro il giorno della settimana, il mese e il giorno del mese in cui
il report è stato eseguito, e nell’angolo superiore destro il numero di pagina.
I comandi repheader e repfooter possono essere utilizzati per creare le intestazioni e i piè di
pagina dei report. Per le descrizioni di repheader e repfooter, si rimanda al Capitolo 48.
column
Con column è possibile modificare l’intestazione e il formato di qualsiasi colonna contenuta in
un’istruzione select. Si osservi il report presentato in precedenza nella Figura 6.2. La quinta
REPORT E COMANDI FONDAMENTALI DI SQL*PLUS 105
colonna, “Giorni fuori”, non è una colonna del database e prende il nome di GiorniFuori nella
query illustrata nella Figura 6.3. La linea:
assegna alla colonna una nuova etichetta e una nuova intestazione. Questa intestazione si
divide in due linee perché in essa è incorporato il carattere headsep (!). Si consideri la riga
seguente:
essa imposta la larghezza di visualizzazione della colonna Nome a 20. La “a” indica a
SQL*Plus che si tratta di una colonna di caratteri alfabetici e non numerici. La larghezza può
essere impostata praticamente a qualsiasi valore, senza considerare come è stata definita la co-
lonna nel database.
La colonna Nome è definita con ampiezza pari a 25 caratteri, quindi è possibile che qualche
nome abbia più di 20 caratteri. Se nella definizione di questa colonna nel report non è stato
specificato nient’altro, qualsiasi nome con più di 20 caratteri andrà a capo alla riga successiva.
La colonna Titolo è stata definita come VARCHAR2(100), tuttavia è formattata come a20 (si
veda il numero 5).
Invece di utilizzare il formato word_wrapped, si potrebbe scegliere truncated, che non
visualizza i caratteri che vanno oltre la lunghezza di formato specificata per la colonna.
Al punto 6 della Figura 6.3 viene mostrato un esempio di formattazione di un numero:
In questo modo, la colonna è stata definita per contenere cinque cifre e un punto decimale.
Se però si contano gli spazi nel report per la colonna GiorniFuori, si osserverà che sono sette. Se
invece si considera soltanto il comando column, si è portati a credere che la colonna debba avere
una larghezza pari a sei spazi. In questo modo però non vi sarebbe spazio per un eventuale segno
meno, nel caso in cui il numero sia negativo; per questo motivo con i numeri viene sempre
previsto uno spazio in più a sinistra. Nel punto 7 della Figura 6.3 si fa riferimento a una colonna
che non appariva nella tabella quando è stato chiesto a SQL*Plus di descriverla:
Che cosa significa GiorniFuori? Si osservi l’istruzione select nella parte inferiore della Fi-
gura 6.3. GiorniFuori appare nella linea seguente:
Questa indica a SQL di eseguire calcoli aritmetici sulle date, ossia di contare il numero di
giorni trascorsi tra due date e di assegnare a questo calcolo un nome di colonna più semplice. Di
conseguenza, SQL*Plus visualizza una colonna di nome GiorniFuori e tutte le opzioni di
formattazione e gli altri comandi sono attivi come se si trattasse di una vera colonna della tabel-
la. Il comando column per GiorniFuori ne è un esempio. “GiorniFuori” viene indicato come un
alias di colonna, ossia un altro nome da utilizzare quando si fa riferimento alla colonna.
break on
Si osservi il punto 8 nella Figura 6.3. Nel report della Figura 6.2, si noti che i record estratti per
ogni nome sono stati raggruppati insieme. Questo effetto è stato ottenuto con la linea:
106 CAPITOLO 6
e con la linea:
L’output del report nella Figura 6.2 mostra una media di GiorniFuori per l’intero report. Per
ottenere il totale complessivo di un report occorre aggiungere un’altra interruzione utilizzando il
comando break on report. Si raccomanda di prestare attenzione quando si aggiungono delle
interruzioni, poiché devono essere create tutte con un unico comando; se si inseriscono due
comandi break on consecutivi, le istruzioni del primo comando vengono sostituite dal secondo.
Si osservi il punto 8 per vedere il comando break on utilizzato nel report:
compute avg
Le medie calcolate per ciascuna sezione del report sono state prodotte con il comando compute
avg evidenziato al punto 9. Questo comando funziona sempre congiuntamente al comando bre-
ak on e i totali calcolati sono sempre riferiti alla sezione specificata da tale comando. Può quindi
essere opportuno considerare questi due comandi correlati come una singola unità:
In altre parole, si indica a SQL*Plus di calcolare la media di GiorniFuori per ciascun Nome.
SQL*Plus calcolerà questo valore prima per DORAH TALBOT, poi per tutti i nomi successivi.
Ogni volta che SQL*Plus rileva un nuovo nome, calcola e visualizza una media per i valori di
GiorniFuori precedenti. Inoltre, il comando compute avg inserisce una riga di asterischi sotto la
colonna utilizzata in quel momento da break on e visualizza la parola “avg” al di sotto di essa.
Per quei report in cui è necessario aggiungere parecchie colonne, per ogni calcolo si usa un’istru-
REPORT E COMANDI FONDAMENTALI DI SQL*PLUS 107
zione compute avg separata (oppure compute sum, se si calcolano i totali). In un report lungo
(per Nome, Titolo, date, per esempio) è anche possibile avere molti tipi diversi di interruzioni,
insieme a comandi compute avg correlati.
Si può utilizzare un comando break on anche senza compute sum, come nel caso in cui si
debba organizzare il proprio report in sezioni in cui non è necessario impostare dei totali (per
esempio, indirizzi con break on per Città), tuttavia non è vero il contrario.
NOTA Ogni comando compute avg deve essere guidato da un comando break on,
e la porzione on di entrambi i comandi deve corrispondere (come on Nome nell’esempio prece-
dente: break on Nome skip 1 on report e compute avg of GiorniFuori on Nome).
set linesize
I quattro comandi al punto 10 della Figura 6.3 controllano le dimensioni generali del report. Con
set linesize si imposta il numero massimo di caratteri che possono comparire in una singola riga.
Per documenti delle dimensioni di una lettera, questo numero è generalmente intorno a 70 o 80,
a meno che la stampante non utilizzi un tipo di carattere molto compresso.
Se in una query SQL si inseriscono più colonne di informazioni di quante siano state stabi-
lite con il parametro linesize, le colonne in sovrappiù vengono collocate sulla riga successiva e
ammassate una sotto l’altra. In realtà, si può utilizzare questa disposizione ottenendo un buon
effetto quando è necessario presentare numerosi dati.
Il comando linesize serve anche per determinare il punto in cui dev’essere centrato ttitle e
quello in cui collocare la data e la numerazione di pagina. Questi due dati compaiono entrambi
nella prima riga e la distanza tra la prima lettera della data e l’ultimo numero della numerazione
di pagina deve sempre essere equivalente al valore di linesize impostato.
set pagesize
Con il comando set pagesize si imposta il numero totale di righe che SQL*Plus inserirà in ogni
pagina, compresi ttitle, btitle, le intestazioni di colonna e qualsiasi eventuale riga vuota. Per il
formato da lettera e quello generalmente utilizzato per i computer, questo numero solitamente è
66 (6 linee per pollice, moltiplicato per 11 pollici). Il comando set pagesize è correlato al co-
mando set newpage.
A partire da Oracle Database 10g, il valore predefinito di pagesize è 14, mentre nelle versio-
ni precedenti è 24.
set newpage
Una definizione migliore per il comando set newpage (che in inglese significa “imposta nuova
pagina”) avrebbe potuto essere “imposta righe vuote”, in quanto questo comando visualizza
108 CAPITOLO 6
delle righe vuote prima della prima riga (quella in cui compaiono data e numerazione di pagina)
di ogni pagina del report. Si tratta di una funzione utile sia per adattare la posizione dei report
che vengono stampati su pagine singole con una stampante laser, sia per saltare le perforazioni
tra le pagine tipiche della carta per moduli continui.
NOTA Con set pagesize non vengono impostate le dimensioni del corpo del report
(il numero di linee visualizzate dalla data fino al btitle), bensì la lunghezza totale della pagina,
misurata in righe.
Pertanto, se si digita:
set pagesize 66
set newpage 9
SQL*Plus produrrà un report che inizia con 9 righe vuote, seguite da 57 righe di informazio-
ni (contando dalla data fino al btitle). Se si aumenta la dimensione di newpage, SQL*Plus
visualizzerà meno righe di informazioni su ciascuna pagina, producendo però più pagine insie-
me.
Tutto ciò è facilmente comprensibile, ma che cosa è successo al punto 10 della Figura 6.3?
set pagesize 60
set newpage 0
Si tratta di una dimensione insolita per la pagina di un report. L’istruzione di inserire zero righe
vuote tra le pagine è stata impostata da SQL*Plus? No. Il numero zero dopo newpage attiva una
proprietà speciale: il comando set newpage 0 produce un carattere di inizio pagina (general-
mente hex 13) proprio prima della data su ciascuna pagina. Per la maggior parte delle stampanti
moderne ciò equivale a uno spostamento immediato all’inizio della pagina successiva, dove
inizierà la stampa del report. La combinazione dei due comandi set pagesize 60 e set newpage
0 ha per effetto la produzione di un report il cui corpo di informazioni è lungo esattamente 60
righe, con un carattere di inizio pagina all’inizio di ogni pagina. Si tratta di un modo più sempli-
ce per controllare la stampa delle pagine rispetto al destreggiarsi tra righe vuote e numero di
linee per pagina. È anche possibile utilizzare il comando set newpage none, con il risultato di
non avere nessuna linea vuota e nessun carattere di inizio pagina tra le pagine del report.
spool
Ai primordi dell’era informatica, la memorizzazione dei file avveniva nella maggior parte dei
casi su bobine di filo magnetico o nastro. Scrivere informazioni su un file ed eseguire lo spooling
di un file erano praticamente la stessa cosa. Il termine“spooling” è comunque sopravvissuto e
oggi si riferisce in genere a qualsiasi processo di spostamento di informazioni da un luogo a un
altro. In SQL*Plus,
spool activity.lst
indica a SQL di prendere tutto l’output da SQL*Plus e trascriverlo nel file activity.list. Una
volta inserito questo comando, l’operazione viene effettuata finché non si digita il comando
opposto, ovvero:
REPORT E COMANDI FONDAMENTALI DI SQL*PLUS 109
spool off
spool work.fil
ARGOMENTO S PAGINA
--------------- - ------
Nascite F 7
Annunci F 8
Necrologi F 6
Salute F 6
set pagesize 60
column Sezione heading ‘I miei preferiti’
o qualsiasi altra cosa. Qualunque prompt prodotto da SQL*Plus, qualunque messaggio di errore,
qualsiasi cosa compaia sullo schermo del computer durante l’operazione di spooling verrà tra-
sferita nel file work.fil. L’operazione di spooling non fa distinzioni. Registra tutto quello che
accade dal momento in cui si utilizza il comando spool al momento in cui si utilizza spool off, il
quale ci riporta al report indicato al punto 11 della Figura 6.3:
spool activity.lst
Questa espressione viene collocata con attenzione come comando immediatamente prima
dell’istruzione select, dopo la quale compare immediatamente il comando spool off. Se il file
spool activity.lst fosse apparso un po’ prima, i comandi SQL*Plus eseguiti sarebbero andati a
finire nella prima pagina del file di report. Al contrario, questi vanno a finire nel file activity.lst,
ossia ciò che compare nella Figura 6.2: i risultati della query SQL, formattati secondo le istru-
zioni date, e niente altro. Ora è possibile stampare tranquillamente il file, fiduciosi che dalla
stampante uscirà un report formattato in modo chiaro.
Questo gruppo di comandi visualizzerà la query SQL sulla prima pagina dell’output, seguita
dai dati che inizieranno nella seconda pagina. Per non visualizzare la query SQL insieme all’output,
si può anche modificare l’ordine dei comandi: inserire la query SQL senza il punto e virgola
finale. Premere due volte INVIO e il comando sarà ancora nel buffer di SQL*Plus, senza essere
stato eseguito. Quindi, si potrà iniziare l’operazione di spooling e l’esecuzione del comando:
spool activity.lst
/
spool off
A partire da Oracle Database 10g è possibile aggiungere dati a file di spool esistenti. L’op-
zione predefinita prevede, come nelle versioni precedenti, la creazione di un nuovo file di output.
Ora è possibile utilizzare l’opzione append o replace del comando spool rispettivamente per
110 CAPITOLO 6
aggiungere i file a un comando esistente che corrisponda al nome fornito o per sostituire quel file
con il nuovo output.
/* */
Il punto 12 della Figura 6.3 mostra come incorporare un commento in un’istruzione SQL. Si
tratta di un metodo e di un tipo di utilizzo differente dall’istruzione remark discussa in preceden-
za. Il termine remark (o rem) deve apparire all’inizio di una linea e funziona soltanto per la linea
in cui compare. Inoltre, in un’istruzione SQL a più linee non è consentito inserire remark. Per
esempio, l’istruzione che segue è errata:
Il segreto sta nel sapere che il segno /* indica a SQL*Plus che è iniziato un commento.
Qualsiasi cosa compaia da questo punto in poi, anche se prosegue con molte parole per diverse
linee, viene considerata un commento fino all’inserimento del segno */, che indica la fine del
commento in questione. Per iniziare un commento si possono anche utilizzare i caratteri “--”
(due trattini). In questo caso, la fine della linea indica la fine del commento. Questo tipo di
commento funziona come la versione a una linea di /* */, tranne per il fatto che viene utilizzato il
segno -- (due trattini).
DataRestituzione-DataPrestito as GiorniFuori
GiorniFuori è che abbia ottenuto questa denominazione nell’istruzione select. La nuova deno-
minazione di “DataRestituzione-DataPrestito” in “GiorniFuori” viene effettuata da SQL, non da
SQL*Plus.
Questo messaggio fa capire che la parola “Argomento” è stata digitata in modo errato. No-
nostante ciò, non sarà necessario digitare nuovamente l’intera query. L’editor a linea di comando
è già pronto in attesa di istruzioni. Innanzi tutto, si chieda di visualizzare la query:
list
Si osservi che SQL*Plus visualizza tutte e tre le linee numerandole. Inoltre, inserisce un
asterisco accanto alla linea 3, per indicare la linea che si può modificare. Si desidera però modi-
ficare la linea 1, per cui sarà necessario digitare, e SQL*Plus dovrà visualizzare, quanto segue:
list 1
Viene visualizzata la linea 1 come linea corrente. Ora, questa linea potrà essere modificata
digitando:
change /Argometno/Argomento
list
Se il test è positivo, inserire una barra dopo il prompt. Questa barra non ha nulla a che fare
con il comando change o con l’editor. Al contrario, comunica a SQL*Plus di eseguire il codice
SQL memorizzato nel buffer.
ARGOMENTO S PAGINA
--------------- - ----
Nascite F 7
Annunci F 8
Necrologi F 6
Salute F 6
Per eseguire il comando change è necessario segnalare l’inizio e la fine del testo che deve
essere modificato con una barra (/) o con altri caratteri. La linea:
change $Argometno$Argomento
avrebbe ottenuto lo stesso risultato. SQL*Plus considera il primo carattere dopo la parola
“change” come quello prescelto per segnalare l’inizio e la fine del testo da correggere (questi
indicatori in genere vengono definiti delimitatori). È anche possibile cancellare la linea corrente,
come mostrato di seguito:
list
del
list
del cancellerà solo ciò che si trova nella linea corrente. Per cancellare più linee contempora-
neamente, è possibile impostare un intervallo di numeri di linea da cancellare con il comando
del, specificando il primo e l’ultimo numero di linea per l’intervallo di linee da cancellare. Per
cancellare le linee dalla 3 alla 7, occorre utilizzare del 3 7. Si osservi che in questo comando c’è
REPORT E COMANDI FONDAMENTALI DI SQL*PLUS 113
uno spazio prima del numero della prima linea da cancellare (3) e un altro prima del numero
dell’ultima linea da cancellare (7). Se non si introducono spazi tra il “3” e il “7”, SQL*Plus
cercherà di cancellare la linea 37. Per eliminare le linee dalla 2 fino alla fine del buffer, occorre
usare del 2 LAST. Lo stesso tipo di sintassi può essere usata con il comando list; per esempio, list
3 7 elencherà le linee dalla 3 alla 7. Fare riferimento alle voci relative ai comandi del e list nel
Capitolo 48 per una descrizione completa delle opzioni di sintassi.
Scrivendo lettera per lettera la parola “delete” (cancellare) vengono eliminate tutte le linee e
questa parola viene inserita alla linea 1. Ciò causerà solo dei problemi, quindi è consigliabile
evitare di digitare l’intera parola “delete”. Se lo scopo è cancellare completamente l’istruzione
select, è meglio digitare:
clear buffer
list 1
append “Dovesta”
Con append il testo indicato viene collocato esattamente alla fine della linea corrente, senza
lasciare nessuno spazio. Per inserire uno spazio, come è stato fatto in questo caso, occorre digitare
due spazi tra la parola append e il testo. È anche possibile inserire un’intera linea nuova dopo
quella corrente utilizzando il comando input, come nell’esempio seguente:
list
list
Riassumendo: l’editor a linea di comando può visualizzare l’istruzione SQL digitata con il
comando list, modificare o cancellare la linea corrente (contrassegnata da un asterisco) con i
comandi change o delete, aggiungere qualcosa alla fine della linea corrente con append, oppure
inserire un’intera linea dopo la linea corrente con input. Una volta apportate le correzioni neces-
sarie, l’istruzione SQL verrà eseguita se si inserisce una barra al prompt SQL. Tutti questi co-
mandi possono essere abbreviati digitando soltanto la prima lettera, tranne del, che dev’essere
digitato esattamente con le tre lettere.
L’editor a linea di comando può modificare solamente l’istruzione SQL, non i comandi
SQL*Plus. Se per esempio è stata digitata l’istruzione column Name format a18 e si desidera
modificarla in column Name format a20, occorre digitare nuovamente l’intero comando (questo
vale se si opera in modalità interattiva con SQL*Plus; se invece i comandi sono in un file, natu-
ralmente li si potrà modificare con l’editor). Inoltre, si osservi che, in modalità interattiva, una
volta iniziata la digitazione di un’istruzione SQL, è necessario completarla prima di poter inse-
rire qualsiasi altro comando SQL*Plus, come i formati column o ttitle. Non appena SQL*Plus
incontra la parola select, considera tutto ciò che segue questa parola come parte dell’istruzione
select finché non viene inserito un punto e virgola (;) alla fine dell’ultima linea dell’istruzione
SQL, oppure una barra (/) all’inizio della linea successiva all’ultima dell’istruzione SQL.
Queste istruzioni sono entrambe corrette:
select * from REGISTRO;
set pause
Nello sviluppo di un nuovo report, oppure quando si utilizza SQL*Plus per query semplici del
database, è generalmente utile impostare il parametro linesize a 79 o a 80, pagesize a 24 (il
valore predefinito in Oracle Database 10g è 14) e newpage a 1. Occorre accompagnare queste
impostazioni con due comandi correlati, come mostrato di seguito:
set pause 'Ancora. . .'
set pause on
Con questa combinazione si ottiene una schermata piena di informazioni per ciascuna pagi-
na del report prodotta, e la visualizzazione viene interrotta a ogni pagina per dare la possibilità di
consultarla (la dicitura “Ancora...” apparirà nell’angolo in basso a sinistra) fino a quando non si
preme INVIO. Dopo l’impostazione dei vari titoli e intestazioni di colonna, è possibile modificare
nuovamente le dimensioni della pagina con pagesize in modo da adattarle a una pagina standard
ed eliminare la pausa in questo modo:
save
Se le modifiche da apportare all’istruzione SQL sono ampie, o se semplicemente si desidera
lavorare con il proprio editor, è necessario salvare le istruzioni SQL create fino a quel momento
in modalità interattiva, trasferendole in un file, come questo:
REPORT E COMANDI FONDAMENTALI DI SQL*PLUS 115
save fred.sql
Le istruzioni SQL (ma non i comandi column, ttitle o altri comandi SQL*Plus) si trovano in
un file di nome fred.sql (o un nome di propria scelta), che può essere modificato con il proprio
editor.
Se il file esiste già, sarà necessario utilizzare l’opzione replace (abbreviata in rep) del co-
mando save per salvare la nuova query in un file con quel nome. Per questo esempio, la sintassi
sarebbe:
In alternativa è possibile aggiungere il file fred.sql con il comando save fred.sql app.
store
Il comando store può essere utilizzato per salvare in un file le impostazioni ambientali correnti
di SQL*Plus. L’istruzione che segue creerà un file di nome my_settings.sql e vi memorizzerà le
impostazioni:
Se il file my_settings.sql dovesse già esistere, si potrebbe usare l’opzione replace al posto di
create e sostituire il vecchio file con le nuove impostazioni. In alternativa si potrebbe usare
l’opzione append per aggiungere le impostazioni nuove a un file già esistente.
Editing
Ognuno ha il proprio editor preferito. Con SQL*Plus è anche possibile utilizzare programmi di
elaborazione di testi, ma soltanto se si salvano i file creati con essi in formato ASCII (si consulti
il manuale del proprio elaboratore di testi per i dettagli relativi a questa operazione). Gli editor
sono essi stessi dei programmi, che in genere vengono invocati digitando il loro nome al prompt
del sistema operativo. Quello che segue è un comando tipico dell’ambiente UNIX:
> vi fred.sql
Per prima cosa, si dovrebbe indicare a SQL*Plus il nome dell’editor. Occorre pertanto defi-
nire l’editor in SQL*Plus, in questo modo:
116 CAPITOLO 6
P er definire il proprio editor con SQL*Plus occorre inserire il comando define_editor in un file
denominato: si tratta di un file speciale, che SQL*Plus ricerca a ogni avvio. Se lo trova, ese-
gue tutti i comandi in esso contenuti come se fossero stati digitati manualmente; innanzi tutto
cerca nella directory in cui l’utente si trova al momento di digitare SQL*Plus; se non lo trova,
ricerca il file nella directory home di Oracle; se non lo trova nemmeno lì, interrompe la ricerca.
Nel file login.sql può essere inserito qualsiasi comando utilizzabile in SQL*Plus, inclusi i comandi
SQL*Plus e le istruzioni SQL; tutti vengono eseguiti prima di visualizzare il prompt SQL>. Questo
può essere un modo pratico di impostare un proprio ambiente SQL*Plus, con tutte le opzioni
preferite. Ecco l’esempio di un tipico file login.sql:
A partire da Oracle Database 10g, Oracle fornisce tre nuove variabili d’ambiente: DATE_PRIVILEGE
(‘AS SYSDBA’, ‘AS SYSOPER’ o vuoto) e _USER (lo stesso valore restituito da shw user).
Un altro file denominato glogin.sql viene utilizzato per stabilire le impostazioni predefinite di
SQL*Plus per tutti gli utenti di un database. Questo file, che in genere si trova nella directory
amministrativa di SQL*Plus, è utile per forzare impostazioni di colonna e di ambiente per più
utenti.
Il significato di tutti questi comandi è riportato nel Capitolo 42.
Si osservi che è stato inserito un trattino di sottolineatura prima della “e” di editor. SQL*Plus
ricorderà quindi il nome dell’editor (finché non si esce da SQL*Plus con il comando quit), e
consentirà di utilizzarlo ogni volta che si desidera. Per suggerimenti sulle modalità per
automatizzare questa operazione, fare riferimento alla discussione del riquadro “Uso di login.sql
per definire l’editor”.
Il comando host
Nell’eventualità improbabile che nessuno dei comandi di editing descritti nel paragrafo prece-
dente funzioni, se si desidera assolutamente utilizzare l’editor prescelto è possibile richiamarlo
digitando:
host vi fred.sql
host indica a SQL*Plus che si tratta di un comando inteso semplicemente per restituire al
sistema operativo l’esecuzione e che questo comando equivale a digitare vi fred.sql al prompt del
sistema operativo. Per inciso, questo stesso comando host può essere utilizzato per eseguire
pressoché tutti i comandi del sistema operativo da SQL*Plus, compresi dir, copy, move, erase,
cls e altri ancora.
REPORT E COMANDI FONDAMENTALI DI SQL*PLUS 117
start
Una volta tornati in SQL*Plus, si potranno verificare le modifiche apportate eseguendo il file
appena modificato:
start fred.sql
Tutti i comandi SQL*Plus e SQL presenti nel file vengono eseguiti, linea dopo linea, pro-
prio come se ognuno fosse stato inserito manualmente. Se nel file sono stati inseriti i comandi
spool e spool off, è possibile utilizzare l’editor per visualizzare i risultati del proprio lavoro. Si
tratta esattamente di ciò che era visualizzato nella Figura 6.2, il prodotto dell’avvio di activity.sql
e dello spooling dei suoi risultati in activity.lst. Per sviluppare un report, occorre eseguire
ciclicamente le fasi seguenti:
1. Utilizzare SQL*Plus per creare in modo interattivo una query SQL. Quando il risultato è
vicino alle aspettative, salvare la query con un nome come test.sql (l’estensione .sql viene gene-
ralmente utilizzata per i file di avvio, gli script che devono essere eseguiti per produrre un report).
2. Modificare il file test.sql utilizzando l’editor prescelto. Aggiungere al file i comandi column,
break, compute, set e spool. In genere si effettua lo spooling in un file con l’estensione .lst, come
test.lst. Uscire dall’editor.
3. Tornati in SQL*Plus, avviare il file test.sql con il comando start. I risultati vengono visualizzati
sullo schermo e riportati nel file test.lst. Questo file viene esaminato dall’editor.
4. Incorporare qualsiasi modifica necessaria nel file test.sql ed eseguirlo nuovamente.
5. Proseguire con questa procedura finché il report non è chiaro e corretto.
column GiorniFuori
senza altri elementi dopo il nome di colonna. SQL*Plus presenterà un elenco delle istruzio-
ni impartite per quella colonna, come mostrato di seguito:
COLUMN GiorniFuori ON
HEADING 'Giorni!Fuori' headsep '!'
118 CAPITOLO 6
FORMAT 999.99
Se si digita soltanto la parola column, senza specificare il nome della colonna, verranno
elencate tutte le colonne: Si vedranno tutte le colonne impostate da Oracle per default più quelle
definite in proprio:
COLUMN Titolo ON
FORMAT a20
word_wrap
COLUMN GiorniFuori ON
HEADING 'Giorni!Fuori' headsep '!'
FORMAT 999.99
COLUMN Nome ON
FORMAT a20
Le istruzioni impostate con i comandi ttitle, btitle, break e compute vengono visualizzate sempli-
cemente digitando i nomi dei comandi, senza altri elementi. SQL*Plus risponde immediatamen-
te con le definizioni correnti. La prima linea in ciascuno degli esempi successivi è la richiesta
impostata dall’utente; le linee seguenti sono le risposte di SQL*Plus:
ttitle
ttitle ON and is the following 40 characters:
Registro prestiti dal 1/1/02 al 31/3/02
btitle
btitle ON and is the following 20 characters:
from the Biblioteca
break
break on report nodup
on Nome skip 1 nodup
compute
COMPUTE avg LABEL 'avg' OF GiorniFuori ON Nome
COMPUTE avg LABEL 'avg' OF GiorniFuori ON report
Per visualizzare le impostazioni (dette anche parametri) che seguono il comando set occorre
utilizzare show:
show headsep
headsep “!” (hex 21)
show linesize
linesize 80
show pagesize
pagesize 60
show newpage
newpage 0
Le impostazioni ttitle e btitle possono essere disabilitate con i comandi btitle off e ttitle off. Il
listato seguente mostra questi comandi (si osservi che SQL*Plus non risponde ai comandi):
ttitle off
btitle off
clear columns
columns cleared
clear breaks
breaks cleared
clear computes
computes cleared
6.4 I fondamenti
Questo capitolo è molto denso, soprattutto per i gli utenti che si avvicinano solo ora a SQL*Plus;
riflettendoci però i lettori concorderanno probabilmente sul fatto che i concetti presentati non
sono veramente difficili. Se la Figura 6.3 poteva apparire complessa quando si è iniziata la lettu-
ra del capitolo, ora appare sicuramente diversa. Probabilmente, tutte le linee risultano
comprensibili e si riesce almeno ad avere un’idea di ciò che avviene e delle motivazioni. Volen-
do, è possibile copiare il file activity.sql in un altro file con un nome diverso e iniziare a modifi-
carlo in modo che risponda ai propri gusti, adattandolo alle tabelle impostate. La struttura di
qualsiasi report prodotto sarà in definitiva molto simile.
Gli elementi nel file activity.sql sono molti, tuttavia esso è composto da unità di costruzione
semplici. Questo è l’approccio utilizzato per tutto il testo. Oracle fornisce unità di costruzione in
gran quantità, tuttavia ciascuna di esse considerata singolarmente risulta comprensibile e rivela
la propria utilità.
Nei capitoli precedenti è stato illustrato come selezionare i dati dal database, scegliendo
determinate colonne e ignorandone altre e scegliendo determinate righe sulla base dei vincoli
logici impostati, nonché come combinare due tabelle per ottenere informazioni non disponibili
con una sola di esse. In questo capitolo si è visto come impartire ordini che SQL*Plus possa
seguire nella formattazione e produzione delle pagine e delle intestazioni di report chiaramente
comprensibili.
Nei prossimi capitoli, si imparerà a modificare e formattare i dati riga per riga. Il livello di
conoscenza e familiarità dovrebbe crescere capitolo dopo capitolo; al termine della Parte secon-
da di questo libro, l’utente dovrebbe essere in grado di produrre velocemente report molto sofi-
sticati, con grande vantaggio per sé e per l’azienda per cui lavora.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 7
Ottenere e modificare
informazioni di testo
I
n questo capitolo vengono introdotte le funzioni di stringa, stru-
menti software che consentono di manipolare una stringa di lettere o di altri caratteri. Per un
riferimento immediato alle singole funzioni, si rimanda al Capitolo 48, dove le funzioni sono
elencate per nome. Questo capitolo si concentra sulla manipolazione delle stringhe di testo; per
eseguire ricerche di parole (comprese quelle provenienti da radici comuni e le corrispondenze
imperfette), si dovrebbe utilizzare Oracle Text, come descritto nel Capitolo 25.
In Oracle le funzioni operano in due modi. Alcune creano oggetti nuovi partendo da quelli
vecchi; queste producono un risultato che è una modifica dell’informazione originale, come la
trasformazione di caratteri minuscoli in maiuscoli. Altre funzioni invece producono un risultato
che fornisce indicazioni sulle informazioni, come la quantità di caratteri contenuti in una parola
o in una frase.
Le stringhe che possono comprendere qualsiasi mescolanza di lettere, numeri, spazi e altri
simboli (come i segni di interpunzione e i caratteri speciali) prendono il nome di stringhe di
caratteri, o semplicemente caratteri per brevità.
In Oracle sono disponibili due tipi di dati di stringa. Le stringhe di tipo CHAR hanno sem-
pre una lunghezza prefissata. Se si imposta un valore di stringa con lunghezza inferiore a quella
di una colonna di tipo CHAR, Oracle inserisce automaticamente nella stringa degli spazi vuoti.
Quando vengono confrontate stringhe di tipo CHAR in Oracle, queste vengono considerate del-
la stessa lunghezza con l’inserimento di spazi vuoti. Ciò significa che, se si mettono a confronto
le stringhe “carattere ” e “carattere” nelle colonne di tipo CHAR, Oracle considererà le due
stringhe uguali. Il tipo di dati VARCHAR2 è una stringa a lunghezza variabile. Il tipo di dati
VARCHAR è sinonimo di VARCHAR2, tuttavia questa equivalenza potrebbe cambiare nelle
prossime versioni di Oracle, quindi si dovrebbe evitare di usare VARCHAR. CHAR si utilizza
per campi con stringhe di caratteri a lunghezza prefissata, mentre VARCHAR2 ricorre in tutti gli
altri campi con stringhe di caratteri.
Le semplici funzioni di stringa di Oracle spiegate in questo capitolo sono elencate nella
Tabella 7.1.
7.3 Notazione
Le funzioni sono indicate con questo tipo di notazione in tutto il libro:
Il nome della funzione è scritto in caratteri maiuscoli. Gli elementi cui è riferita (in genere
una stringa) sono visualizzati in corsivo minuscolo. Ogni volta che compare la parola stringa,
essa rappresenta effettivamente una stringa di caratteri oppure il nome di una colonna di caratteri
in una tabella. Quando si utilizza una vera funzione di stringa, qualsiasi stringa di caratteri dovrà
essere racchiusa tra apici, mentre un nome di colonna non dovrà avere nessun apice.
In tutte le funzioni compare soltanto una coppia di parentesi. Il valore su cui opera questa
funzione, così come le informazioni aggiuntive che è possibile passare alla funzione, devono
essere racchiusi tra parentesi. Alcune funzioni hanno delle opzioni, elementi che non sono indi-
spensabili ma che si possono comunque utilizzare per controllarne il funzionamento. Le opzioni
sono sempre visualizzate tra parentesi quadre [ ]. Per un esempio di come vengono impiegate le
opzioni, fare riferimento alla discussione su LPAD e RPAD del prossimo paragrafo.
OTTENERE E MODIFICARE INFORMAZIONI DI TESTO 123
Di seguito, viene illustrato un semplice esempio del formato della funzione LOWER:
LOWER(stringa)
LOWER('CAMP DOUGLAS')
ASCII Fornisce la rappresentazione decimale del primo carattere della stringa nel set di caratteri del database.
CHR Restituisce il carattere avente l’equivalente binario della stringa nel set di caratteri del database o nel set di
caratteri nazionale.
INITCAP Pone in maiuscolo la prima lettera di una parola o di una serie di parole.
LPAD Riempie una stringa fino a una certa lunghezza aggiungendo a sinistra una determinata serie di caratteri.
LTRIM Elimina tutti i caratteri che rientrano in una serie specificata dalla parte sinistra di una stringa.
RPAD Riempie una stringa fino a una certa lunghezza aggiungendo a destra una determinata serie di caratteri.
RTRIM Elimina tutti i caratteri che rientrano in una serie specificata dalla parte destra di una stringa.
SOUNDEX Trova parole che si pronunciano in modo simile a quelle specificate (in inglese).
TRIM Elimina tutti i caratteri che rientrano in una serie specificata da entrambe le estremità di una stringa.
camp douglas
All’inizio della seconda colonna, nella funzione LOWER, la parola CITTA non è racchiusa
tra apici. In questo modo si indica a Oracle che si tratta di un nome di colonna e non di un
elemento letterale.
All’inizio della terza colonna, nella funzione LOWER, la parola “CITTA” è racchiusa tra
apici. Ciò significa che si desidera letteralmente che la funzione LOWER operi sulla parola
“CITTA” (ovvero, la stringa costituita dalle lettere C-I-T-T-A), e non sulla colonna omonima.
stringa || stringa
Queste naturalmente possono essere sia nomi di colonna, sia elementi letterali. Ecco un
esempio:
CITTA || PAESE
--------------------------------------------------
ATENEGRECIA
CHICAGOSTATI UNITI
CONAKRYGUINEA
LIMAPERU
MADRASINDIA
MANCHESTERINGHILTERRA
OTTENERE E MODIFICARE INFORMAZIONI DI TESTO 125
MOSCARUSSIA
PARIGIFRANCIA
SHENYANGCINA
ROMAITALIA
TOKYOGIAPPONE
SYDNEYAUSTRALIA
SPARTAGRECIA
MADRIDSPAGNA
In questo caso, i nomi di città hanno una lunghezza variabile da 4 a 12 caratteri. I nomi dei
paesi risultano attaccati sulla destra. La funzione di concatenazione opera esattamente con que-
sta modalità: unisce colonne o stringhe senza nessuno spazio intermedio.
La lettura del risultato non è però molto agevole. Per facilitare leggermente la lettura, si
potrebbero elencare le città e i Paesi separandoli con una virgola e uno spazio. A tal fine è
sufficiente concatenare le colonne Citta e Paese con una stringa letterale formata da una virgola
e da uno spazio, come in questo caso:
Ciascuna di queste funzioni svolge una parte della procedura. Per esempio, LENGTH con-
sente di conoscere il numero di caratteri contenuti in una stringa. SUBSTR consente di ritagliare
e utilizzare una sottostringa, una porzione di una stringa, che inizia e termina in determinate
posizioni all’interno della stringa. Con INSTR è possibile trovare la collocazione di un gruppo di
caratteri all’interno di un’altra stringa. Con LPAD e RPAD si possono facilmente concatenare
spazi o altri caratteri a sinistra o a destra di una stringa. LTRIM e RTRIM tagliano i caratteri da
una delle estremità delle stringhe, mentre TRIM riesce a tagliare i caratteri da entrambe le estre-
mità contemporaneamente. La cosa più interessante è che tutte queste funzioni possono essere
utilizzate in combinazione l’una con l’altra, come verrà mostrato tra breve.
RPAD e LPAD
RPAD e LPAD sono funzioni molto simili. La prima consente di “riempire” il lato destro di una
colonna con qualsiasi gruppo di caratteri. È possibile impostare caratteri di vario tipo: spazi,
punti, virgole, lettere o numeri, accenti circonflessi (^) e anche punti esclamativi (!). LPAD ha la
stessa funzione di RPAD, ma agisce sul lato sinistro della colonna.
La sintassi per le funzioni RPAD e LPAD è la seguente:
R P A D ( s t r i n g a ,l u n g h e z z a [ , ' c a r ' ] )
L P A D ( s t r i n g a ,l u n g h e z z a [ , ' c a r ' ] )
Qui stringa è il nome di una colonna di tipo CHAR o VARCHAR2 del database (o una
stringa letterale), lunghezza è il numero totale di caratteri del risultato (in altre parole, la larghez-
za della colonna), mentre car è l’insieme di caratteri utilizzati per il riempimento. Il gruppo di
caratteri dev’essere racchiuso tra apici. Con le parentesi quadre si segnala che il gruppo di carat-
teri (e la virgola che lo precede) sono facoltativi. Se non viene impostato questo parametro, il
riempimento avviene automaticamente con il ricorso a degli spazi. Talvolta questa opzione pren-
de il nome di opzione predefinita; ovvero, se non si indica alla funzione quale gruppo di caratteri
utilizzare, questa per default utilizzerà gli spazi. Molti utenti creano tabelle con puntini come
aiuto visivo per collegare un lato della pagina all’altro. Ecco come ottenere questa impostazione
con la funzione RPAD. In questo esempio il riempimento con i puntini avviene fino alla lunghez-
za 35:
RPAD(CITTA,35,'.') TEMPERATURA
----------------------------------- -----------
LIMA............................... 7
PARIGI............................. 27
MANCHESTER......................... 19
ATENE.............................. 36
CHICAGO............................ 19
SYDNEY............................. 20
SPARTA............................. 74
Si osservi che cosa è accaduto. RPAD ha preso ogni città, da Lima a Sparta, ha concatenato
dei puntini alla destra di ogni città, aggiungendone per ognuna un numero sufficiente a fare in
modo che il risultato (città più puntini) fosse lungo esattamente 35 caratteri. La funzione di
concatenamento ( || ) non avrebbe potuto ottenere questo risultato. Avrebbe aggiunto lo stesso
numero di puntini per ogni città, lasciando sulla destra un bordo irregolare.
OTTENERE E MODIFICARE INFORMAZIONI DI TESTO 127
Con LPAD si ottiene lo stesso risultato, ma sul lato sinistro. Si supponga di voler formattare
nuovamente le città e le temperature in modo che i nomi di città siano giustificati a destra (ovve-
ro, allineati a destra). Per questo esempio, il riempimento avviene sino alla lunghezza 11:
LPAD(CITTA,1 TEMPERATURA
------------ -----------
LIMA 7
PARIGI 27
MANCHESTER 19
ATENE 36
CHICAGO 19
SYDNEY 20
SPARTA 23
TITOLO
-------------------------------------
THE BARBERS WHO SHAVE THEMSELVES.
”HUNTING THOREAU IN NEW HAMPSHIRE”
THE ETHNIC NEIGHBORHOOD
RELATIONAL DESIGN AND ENTHALPY
”INTERCONTINENTAL RELATIONS.”
Qui stringa è il nome della colonna del database (o una stringa letterale), e car è la collezio-
ne dei caratteri che si desidera eliminare. Se non viene specificato nessun set di caratteri, vengo-
no rimossi gli spazi. Si può eliminare più di un carattere per volta; a questo scopo, occorre
semplicemente creare un elenco (una stringa) dei caratteri che si desidera rimuovere. Innanzi
tutto, si eliminano le virgolette e i punti sulla destra, come mostrato di seguito:
Insieme di caratteri
da eliminare
128 CAPITOLO 7
RTRIM(TITOLO,'."')
-----------------------------------
THE BARBERS WHO SHAVE THEMSELVES
"HUNTING THOREAU IN NEW HAMPSHIRE
THE ETHNIC NEIGHBORHOOD
RELATIONAL DESIGN AND ENTHALPY
"INTERCONTINENTAL RELATIONS
Con RTRIM sono stati rimossi sia i punti sia le virgolette dalla destra dei titoli. Il gruppo di
caratteri che si intende rimuovere può avere una lunghezza desiderata. Viene controllato e
ricontrollato il lato destro di ogni titolo finché non è stato rimosso ogni carattere della stringa,
ovvero finché non si incontra il primo carattere della stringa che non era stato indicato nel grup-
po di caratteri da eliminare.
si è ottenuto come risultato il contenuto della colonna Titolo, come mostrato di seguito:
RTRIM(Titolo,'."')
è prendere ciascuna di queste stringhe e rimuovere le virgolette dal lato destro, producendo
in realtà un risultato che equivale a una nuova colonna il cui contenuto è visualizzato di seguito:
LTRIM(stringa,'car')
Funzione LTRIM
LTRIM(RTRIM(TITOLO,'."'),'"')
-----------------------------------
THE BARBERS WHO SHAVE THEMSELVES
HUNTING THOREAU IN NEW HAMPSHIRE
THE ETHNIC NEIGHBORHOOD
RELATIONAL DESIGN AND ENTHALPY
INTERCONTINENTAL RELATIONS
select LTRIM(
RTRIM(Titolo,'."')
,'"')
from RIVISTA;
Così lo scopo di quello che si cerca di fare risulta ovvio, e il tutto funzionerà ugualmente
anche se digitato su quattro linee separate e con molti spazi. SQL*Plus ignora gli spazi in più.
Ora, si supponga di voler eliminare l’articolo “THE” dall’inizio dei due titoli, con lo spazio
che lo segue (e naturalmente le virgolette che sono state rimosse in precedenza). Si potrebbe
procedere così:
LTRIM(RTRIM(TITOLO,'."'),'"I ')
-----------------------------------
BARBERS WHO SHAVE THEMSELVES
130 CAPITOLO 7
Che cosa è accaduto? La seconda e la terza riga sono state troncate più di quanto desiderato.
Perché? Perché la funzione LTRIM era impegnata a cercare ed eliminare qualsiasi cosa fosse una
virgoletta, T, H, E o spazio. Non stava cercando l’articolo “THE”, bensì le lettere in esso conte-
nute, dimenticandosi di terminare l’operazione la prima volta che ha incontrato una delle lettere
che stava cercando. È infatti terminata nel momento in cui ha visto un carattere che non era
compreso nel gruppo.
Nell’insieme '"THE'
In altre parole, con tutte le combinazioni seguenti, e con molte altre combinazioni di queste
lettere si ottiene lo stesso effetto, quando vengono impostate come gruppo di un comando LTRIM
o RTRIM.
'"THE'
'HET"'
'E"TH'
'H"TE'
'ET"H'
L’ordine delle lettere del gruppo non ha nessun effetto sulle modalità operative della funzio-
ne. Tuttavia, si noti che il carattere maiuscolo o minuscolo delle lettere è importante. Oracle
controllerà il carattere maiuscolo o minuscolo delle lettere sia nel gruppo sia nella stringa. Ven-
gono rimosse soltanto le lettere esattamente corrispondenti.
LTRIM e RTRIM sono progettate per rimuovere qualsiasi carattere contenuto in un gruppo
partendo dal lato sinistro o destro di una stringa: il loro obiettivo non è rimuovere le parole. Per
ottenere questo risultato occorre utilizzare in maniera accorta le funzioni INSTR, SUBSTR e
anche DECODE, illustrate nel Capitolo 16.
L’esempio precedente chiarisce un punto: è meglio accertarsi che i dati vengano ripuliti o
modificati prima di essere memorizzati nel database. Vi sarebbero stati molti meno problemi se
le persone che hanno inserito i titoli degli articoli della rivista avessero semplicemente evitato
l’utilizzo di virgolette, punti e della parola “THE”.
stessi dati da entrambe le estremità della stringa, è possibile ricorrere alla funzione TRIM al
posto di una combinazione di LTRIM/RTRIM.
TRIM utilizza una sintassi unica. L’esempio seguente illustra l’impiego della funzione TRIM
e della clausola ad essa associata, from. In questo esempio, le virgolette vengono rimosse dal-
l’inizio e dalla fine dei titoli degli articoli contenuti nella rivista. Dato che una virgoletta è una
stringa di caratteri, viene racchiusa tra due apici:
TRIM('"' FROMTITOLO)
-------------------------------------
THE BARBERS WHO SHAVE THEMSELVES.
HUNTING THOREAU IN NEW HAMPSHIRE
THE ETHNIC NEIGHBORHOOD
RELATIONAL DESIGN AND ENTHALPY
INTERCONTINENTAL RELATIONS.
Le virgolette sono state rimosse dall’estremità iniziale e da quella finale delle stringhe. Se si
desidera tagliare soltanto un’estremità delle stringhe, si potrebbero utilizzare le clausole leading
o trailing, come mostrato nel listato seguente.
L’uso di leading fa sì che TRIM si comporti come LTRIM, mentre con trailing si comporta
come RTRIM. L’aspetto più utile di TRIM è la sua capacità di operare contemporaneamente su
entrambe le estremità di una stringa, semplificando il codice da scrivere, in quanto dalle due
estremità della stringa verranno rimossi gli stessi caratteri.
In ogni funzione sono presenti delle parentesi che racchiudono la colonna su cui opera la
funzione stessa, quindi il vero trucco per comprendere le funzioni combinate nelle istruzioni
select consiste nel leggere dall’esterno verso l’interno sia a sinistra sia a destra, osservando (e
anche contando) le coppie di parentesi.
132 CAPITOLO 7
LOWER(stringa)
UPPER(stringa)
INITCAP(stringa)
Ritornando alla tabella CLIMA, in cui ogni città era memorizzata in lettere maiuscole:
LIMA
PARIGI
ATENE
CHICAGO
MANCHESTER
SYDNEY
SPARTA
produce:
Si osservino con attenzione il risultato prodotto in ciascuna colonna e le funzioni che hanno
prodotto questo risultato nell’istruzione SQL. Nella quarta colonna è visualizzata la modalità di
applicazione della funzione INITCAP a LOWER(Citta): i nomi delle città compaiono nella forma
normale, anche se sono memorizzati in lettere maiuscole. Un altro esempio è costituito dalla
colonna Nome come appare memorizzata nella tabella RIVISTA:
NOME
----------------
BERTRAND MONTHLY
LIVE FREE OR DIE
PSYCHOLOGICA
FADED ISSUES
ENTROPY WIT
OTTENERE E MODIFICARE INFORMAZIONI DI TESTO 133
Questa viene richiamata con la combinazione delle funzioni INITCAP e LOWER, come mo-
strato di seguito:
INITCAP(LOWER(NO
----------------
Bertrand Monthly
Live Free Or Die
Psychologica
Faded Issues
Entropy Wit
Ed ecco come appare dopo l’applicazione delle stesse funzioni a Nome, al titolo ripulito e al
numero di pagina (si osservi che vengono anche rinominate le colonne):
LENGTH
Si tratta di una funzione di facile utilizzo. Con LENGTH viene segnalata la lunghezza di una
stringa, ovvero il numero di caratteri che la costituiscono, compresi lettere, spazi e qualsiasi
altro elemento. La sintassi per la funzione LENGTH è la seguente:
LENGTH(stringa)
Ecco un esempio:
NOME LENGTH(NOME)
---------------- ------------
BERTRAND MONTHLY 16
LIVE FREE OR DIE 16
PSYCHOLOGICA 12
FADED ISSUES 12
ENTROPY WIT 11
Di per sé, non è normalmente una funzione molto utile, tuttavia può essere utilizzata come
parte di un’altra funzione, per il calcolo dello spazio necessario in un report, o come parte di
clausole come where o order by.
134 CAPITOLO 7
NOTA Non è possibile eseguire funzioni come LENGTH su una colonna che utiliz-
za un tipo di dato LONG.
SUBSTR
È possibile utilizzare la funzione SUBSTR per estrapolare una parte di una stringa. La sintassi
per la funzione SUBSTR è la seguente:
S U B S T R ( s t r i n g a , i n i z i o [, c o n t a ] )
Con questa notazione si indica a SQL di estrapolare una sottosezione della stringa, iniziando
dalla posizione segnalata da inizio e proseguendo per conta caratteri. Se non viene specificata la
posizione conta, SUBSTR inizierà l’operazione partendo da inizio e continuando fino alla fine
della stringa. Per esempio, con l’istruzione:
si ottiene:
SUBS
----
AND
FREE
OLOG
ISS
PY W
Il modo di operare della funzione è abbastanza chiaro. Sono state ritagliate parti del nome
della rivista iniziando dalla posizione 6 (contando da sinistra) e comprendendo un totale di quat-
tro caratteri.
Un impiego più pratico di questa funzione potrebbe essere la selezione di numeri telefonici
da una rubrica personale. Per esempio, si supponga di avere una tabella INDIRIZZO in cui siano
contenuti, tra le altre cose, cognomi, nomi e numeri di telefono, come nel caso seguente:
Successivamente, dato che non è necessario digitare il prefisso quando si chiamano i numeri
urbani con prefisso 415, è possibile eliminare questo prefisso utilizzando un altro comando con
la funzione SUBSTR:
Si osservi che in questo caso è stata utilizzata la versione predefinita della funzione SUBSTR.
SUBSTR(Telefono,5) indica a SQL di estrapolare la sottostringa del numero di telefono, inizian-
do dalla posizione 5 e proseguendo fino alla fine della stringa. In questo modo viene eliminato il
prefisso.
Naturalmente, questo comando:
SUBSTR(Telefono,5)
SUBSTR(Telefono,5,8)
NOME TELEFONO
------------------------- ------------------------- --------
ADAMS, JACK 555-7530
136 CAPITOLO 7
Per aggiungere una linea punteggiata dopo il nome, si fa ricorso alla funzione RPAD:
NOME TELEFONO
------------------------- --------
ADAMS, JACK.............. 555-7530
ZACK, JACK............... 555-6842
YARROW, MARY............. 555-2178
WERSCHKY, ARNY........... 555-7387
BRANT, GLEN.............. 555-7512
EDGAR, THEODORE.......... 555-6252
Nella funzione SUBSTR è anche possibile inserire numeri negativi. Normalmente, il valore
di posizione specificato per la posizione iniziale riguarda il punto di inizio della stringa. Quando
per il valore di posizione si usa un numero negativo, questo riguarda la fine della stringa. Per
esempio, l’istruzione:
SUBSTR(Telefono,-4)
come punto iniziale verrebbe utilizzata la quarta posizione dalla fine del valore della colon-
na Telefono. Dato che in questo esempio non viene specificato nessun parametro di lunghezza, si
ottiene tutta la parte rimanente della stringa.
NOTA È opportuno utilizzare questa caratteristica soltanto per colonne con tipo
di dati VARCHAR2, evitando di utilizzarla con colonne impostate con tipo di dati CHAR. Le
colonne di tipo CHAR hanno lunghezza prefissata, quindi i valori sono completati con spazi in
modo da occupare la lunghezza totale della colonna. Se si utilizza un numero negativo come
valore di posizione SUBSTR in una colonna CHAR, la posizione di inizio viene determinata
relativamente alla fine della colonna, non alla fine della riga.
Nell’esempio seguente viene illustrato il risultato dell’uso di un numero negativo nella fun-
zione SUBSTR applicato a una colonna VARCHAR2:
select SUBSTR(Telefono,-4)
from INDIRIZZO
where Telefono like '415-5%';
SUBS
----
7530
6842
2178
7387
7512
6252
OTTENERE E MODIFICARE INFORMAZIONI DI TESTO 137
Il valore conta della funzione SUBSTR deve sempre essere positivo, qualora venga specifi-
cato. L’uso di un numero negativo per il valore conta comporterà la restituzione di un risultato
NULL.
INSTR
La funzione INSTR consente di effettuare ricerche semplici o complesse di un dato set di carat-
teri in una stringa, in maniera analoga alle funzioni LTRIM e RTRIM, con la differenza che con
INSTR non viene eliminato alcunché. Con questa funzione infatti viene semplicemente visualizzata
la posizione dell’elemento ricercato all’interno della stringa. Si tratta di una caratteristica simile
all’operatore logico LIKE descritto nel Capitolo 5, con la differenza che LIKE può essere utilizza-
to soltanto in una clausola where o having, mentre INSTR può essere utilizzato in qualunque
clausola, con l’eccezione di quelle con from. Naturalmente, LIKE può essere utilizzato per ricer-
che complesse di modelli che sarebbe molto difficile, se non impossibile, effettuare utilizzando
INSTR. La sintassi per la funzione INSTR è la seguente:
Con INSTR viene ricercato un determinato gruppo di caratteri in una stringa. È possibile
impostare due opzioni, che si trovano una all’interno dell’altra; la prima è quella predefinita:
cercherà il gruppo di caratteri partendo dalla posizione 1. Se si specifica la posizione da cui
iniziare, tutti i caratteri precedenti al punto indicato vengono saltati e la ricerca comincia esatta-
mente da quel punto. La seconda opzione è occorrenza. Un gruppo di caratteri può essere ricor-
rente in una stringa e talvolta si è interessati proprio a tale ricorrenza. Per default, INSTR ricerca
la prima occorrenza del gruppo di caratteri. Aggiungendo l’opzione occorrenza con valore pari
a 3, per esempio, si può ottenere che vengano saltate le prime due occorrenze del gruppo di
caratteri e che venga invece localizzata la terza.
Tutto ciò diventa più semplice da comprendere con l’ausilio di qualche esempio. Si riprenda
la tabella con gli articoli di una rivista. Ecco un elenco degli autori:
AUTORE
-------------------------
BONHOEFFER, DIETRICH
CHESTERTON, G.K.
RUTH, GEORGE HERMAN
WHITEHEAD, ALFRED
CROOKES, WILLIAM
Per trovare la posizione della prima occorrenza della lettera ‘O’, viene utilizzata la funzione
INSTR senza nessuna opzione e con il gruppo di caratteri indicato come ‘O’ (si osservi la presen-
za degli apici, poiché si tratta di un elemento letterale), come mostrato nel listato seguente:
AUTORE INSTR(AUTORE,'O')
------------------------- -----------------
BONHOEFFER, DIETRICH 2
CHESTERTON, G.K. 9
RUTH, GEORGE HERMAN 9
WHITEHEAD, ALFRED 0
CROOKES, WILLIAM 3
138 CAPITOLO 7
Nel caso in cui INSTR debba ricercare la seconda occorrenza della lettera ‘O’ , il risultato
sarebbe:
AUTORE INSTR(AUTORE,'O',1,2)
------------------------- ---------------------
BONHOEFFER, DIETRICH 5
CHESTERTON, G.K. 0
RUTH, GEORGE HERMAN 0
WHITEHEAD, ALFRED 0
CROOKES, WILLIAM 4
Con INSTR viene trovata la seconda ‘O’ nel nome Bonhoeffer, alla posizione 5, e nel nome
Crookes, alla posizione 4. Nel nome Chesterton c’è una sola ‘O’ e quindi, come per Ruth, e
Whitehead il risultato è zero, perché non è stata trovata una seconda ‘O’.
Per indicare a INSTR di cercare la seconda occorrenza, occorre indicare anche la posizione
in cui iniziare la ricerca (in questo caso, la posizione 1). Il valore predefinito per inizio è 1,
ovvero il valore che è utilizzato se non ne vengono specificati altri, tuttavia per impostare l’opzione
occorrenza occorre stabilire una posizione iniziale con l’opzione inizio, quindi è necessario
specificarle entrambe. Se il gruppo di caratteri non è composto da un solo carattere ma da molti,
con INSTR viene fornita la posizione della prima lettera del gruppo, come in questo esempio:
AUTORE INSTR(AUTORE,'WILLIAM')
------------------------- -----------------------
BONHOEFFER, DIETRICH 0
CHESTERTON, G.K. 0
RUTH, GEORGE HERMAN 0
WHITEHEAD, ALFRED 0
CROOKES, WILLIAM 10
Questa possibilità può consentire diverse applicazioni utili, come per esempio nella tabella
RIVISTA:
AUTORE INSTR(AUTORE,',')
------------------------- -----------------
BONHOEFFER, DIETRICH 11
CHESTERTON, G.K. 11
RUTH, GEORGE HERMAN 5
WHITEHEAD, ALFRED 10
CROOKES, WILLIAM 8
In questo caso, con INSTR è stata impostata la ricerca di una virgola nelle stringhe dei nomi
di autori, quindi è stata visualizzata la posizione in cui è stata trovata la virgola nella stringa.
OTTENERE E MODIFICARE INFORMAZIONI DI TESTO 139
Si supponga di voler formattare nuovamente i nomi degli autori in modo diverso dall’ap-
proccio formale “cognome /virgola/nome” e di volerli presentare nella forma più comunemente
utilizzata, come mostrato di seguito:
BONHOEFFER, DIETRICH
DIETRICH BONHOEFFER
Per ottenere questo risultato con INSTR e SUBSTR, occorre trovare la posizione della virgo-
la, quindi utilizzare questa posizione per indicare a SUBSTR il punto in cui ritagliare. Seguendo
la procedura passo per passo, innanzi tutto è necessario trovare la virgola, come nel listato prece-
dente.
È necessario utilizzare due volte la funzione SUBSTR, una per ritagliare il cognome dell’au-
tore e collocarlo nella posizione prima della virgola, l’altra per ritagliare il nome dell’autore da
due posizioni dopo la virgola e posizionarlo verso la fine della stringa.
Ecco la prima operazione con SUBSTR, in cui la posizione 1 viene ritagliata e collocata alla
posizione immediatamente precedente la virgola:
AUTORE SUBSTR(AUTORE,1,INSTR(AUT
------------------------- -------------------------
BONHOEFFER, DIETRICH BONHOEFFER
CHESTERTON, G.K. CHESTERTON
RUTH, GEORGE HERMAN RUTH
WHITEHEAD, ALFRED WHITEHEAD
CROOKES, WILLIAM CROOKES
Successivamente si procede con la seconda, in cui l’elemento collocato nella seconda posi-
zione dopo la virgola viene spostato alla fine della stringa:
AUTORE SUBSTR(AUTORE,INSTR(AUTO
------------------------- -------------------------
BONHOEFFER, DIETRICH DIETRICH
CHESTERTON, G.K. G.K.
RUTH, GEORGE HERMAN GEORGE HERMAN
WHITEHEAD, ALFRED ALFRED
CROOKES, WILLIAM WILLIAM
Si osservi la combinazione di queste due operazioni, ottenuta inserendo uno spazio tra di
esse con la funzione di concatenazione, e il rapido cambio del nome della colonna in “PerNome”:
from RIVISTA;
Un’istruzione SQL di questo tipo può apparire oscura, tuttavia è stata creata utilizzando una
logica semplice e può essere scomposta nella stessa maniera. Si può provare con Bonhoeffer. La
prima parte della procedura è la seguente:
SUBSTR(Autore,INSTR(Autore,',')+2)
BONHOEFFER, DIETRICH
||' '||
SUBSTR(Autore,1,INSTR(Autore,',')-1)
In questo modo, si indica a SQL di ritagliare la porzione del nome dell’autore iniziando
dalla posizione 1 e terminando una posizione prima della virgola, ovvero dove si trova il cogno-
me dell’autore:
OTTENERE E MODIFICARE INFORMAZIONI DI TESTO 141
BONHOEFFER, DIETRICH
AS PerNome
È stato possibile effettuare questa trasposizione soltanto perché, per ogni record Autore
nella tabella RIVISTA, sono state seguite le stesse convenzioni di formattazione. In ciascun
record, il cognome era sempre la prima parola della stringa ed era immediatamente seguito da
una virgola. In questo modo, è stato possibile utilizzare la funzione INSTR per cercare la virgola.
Una volta nota la posizione della virgola, è stato possibile determinare quale parte della stringa
era il cognome e il resto è stato considerato come nome.
Non è sempre così. Infatti, è difficile imporre dei formati standard ai nomi. I cognomi pos-
sono avere dei prefissi (come “von” di “von Hagel”) o suffissi (come “Jr.”, “Sr.” e “III”). Se si
utilizza l’istruzione SQL dell’esempio precedente, il nome “Richards, Jr., Bob” sarebbe stato
trasformato in “Jr., Bob Richards”. A causa della mancanza di un formato standard per i nomi, in
molte applicazioni il nome e il cognome vengono memorizzati separatamente. Titoli (come “Dott.”)
sono solitamente memorizzati in un’altra colonna. Un’altra opzione quando si inseriscono i dati
di questo tipo consiste nell’applicare un unico formato e utilizzare le funzioni SUBSTR e INSTR
per manipolare i dati se necessario.
ASCII e CHR
Le funzioni ASCII e CHR sono utilizzate raramente durante le query ad hoc. CHR converte i
valori numerici nei loro equivalenti stringa di caratteri ASCII:
select CHR(70)||CHR(83)||CHR(79)||CHR(85)||CHR(71)
as ChrValues
from DUAL;
CHRVA
-----
FSOUG
Oracle ha convertito CHR(70) in una F, CHR(83) in una S e così via basandosi sul set di
caratteri del database.
La funzione ASCII esegue l’operazione inversa; se però a questa funzione si passa una strin-
ga, essa opererà solamente sul primo carattere della stessa:
ASCII('FSOUG')
--------------
70
142 CAPITOLO 7
Per visualizzare ogni valore ASCII, occorre valutare ciascuna lettera con esecuzioni separa-
te della funzione ASCII.
select Citta
from CLIMA
where LENGTH(Citta) 7;
CITTA
-----------
LIMA
PARIGI
ATENE
SYDNEY
SPARTA
Le stesse funzioni possono essere utilizzate anche in una clausola order by, come mostrato
qui sotto:
select Citta
from CLIMA
order by LENGTH(Citta);
CITTA
-----------
LIMA
PARIGI
ATENE
SYDNEY
SPARTA
CHICAGO
MANCHESTER
Quelli illustrati sono esempi semplici; si potrebbero impostare clausole molto più comples-
se. Per esempio, si potrebbero cercare tutti gli autori i cui nomi contengono più di una O, utiliz-
zando INSTR nella clausola where:
AUTORE
-------------------------
BONHOEFFER, DIETRICH
CROOKES, WILLIAM
Questa istruzione cerca una seconda occorrenza della lettera O nei nomi degli autori. “> 0”
è una tecnica logica: si ricordi che le funzioni producono generalmente due tipi diversi di risul-
tati, uno con il quale vengono creati nuovi oggetti e l’altro con il quale vengono fornite informa-
zioni relative a oggetti già esistenti.
OTTENERE E MODIFICARE INFORMAZIONI DI TESTO 143
Con la funzione INSTR vengono fornite informazioni su una stringa, in particolare la posi-
zione del gruppo di caratteri ricercato. In questo caso, viene richiesto di localizzare la seconda O
nella stringa Autore. Il risultato è un numero maggiore di zero per quei nomi con almeno due O,
e zero per quei nomi con una o meno O (se INSTR non trova nulla il risultato è zero). Quindi, la
semplice verifica della presenza di un risultato maggiore di zero conferma che la ricerca con
INSTR della seconda O ha avuto successo.
La clausola where in cui compare la funzione INSTR produce lo stesso risultato di questa
istruzione:
Si ricordi che il segno di percentuale (%) è un carattere jolly, ovvero sta al posto di qualsiasi
elemento, quindi la clausola LIKE indica a SQL di cercare due O precedute, separate o seguite da
qualsiasi carattere. Si tratta di un esempio probabilmente più semplice da comprendere del pre-
cedente con INSTR.
Spesso in Oracle esistono più modi per ottenere il medesimo risultato. Alcune procedure
sono più semplici da comprendere, alcune funzionano più velocemente, alcune sono più
appropriate in determinate situazioni e alcune sono semplicemente una scelta di stile personale.
SOUNDEX
Esiste una funzione di stringa che viene utilizzata quasi esclusivamente in una clausola where:
SOUNDEX. Con questa insolita funzione vengono trovate parole che sono simili ad altre, indi-
pendentemente dal modo in cui sono scritte. Si tratta di una caratteristica particolarmente utile
quando non si è certi della grafia di una parola o di un nome, ma è adatta solo per i termini della
lingua inglese. La sintassi per la funzione SOUNDEX è la seguente:
SOUNDEX(stringa)
AUTORE
-------------------------
BONHOEFFER, DIETRICH
Con la funzione SOUNDEX viene confrontato il suono delle voci inserite nella colonna
selezionata con il suono della parola indicata tra apici e viene ricercata una corrispondenza. Si
fanno delle ipotesi sulle modalità di pronuncia delle lettere e delle combinazioni di lettere e le
due parole confrontate devono iniziare con la stessa lettera. Non sempre SOUNDEX trova la
parola ricercata, o la parola scritta male, ma talvolta può risultare d’aiuto.
Non è necessario che una delle due impostazioni di SOUNDEX nella clausola where sia un
nome. SOUNDEX può essere utilizzata anche per confrontare i dati di due colonne, al fine di
144 CAPITOLO 7
trovare quelli simili. Una finalità utile di questa funzione è quella di ripulire le mailing list. Molti
elenchi contengono voci doppie con leggere differenze di grafia o di formato dei nomi dei clien-
ti. Utilizzando la funzione SOUNDEX per elencare tutti i nomi simili, molti dei duplicati posso-
no essere scoperti ed eliminati. Si può provare con la tabella INDIRIZZO:
Per trovare le voci doppie, occorre indurre Oracle a confrontare ogni cognome nella tabella
con tutti gli altri presenti nella stessa tabella.
Si crei un alias della tabella INDIRIZZO e si la chiami prima a e poi b. Ora, è come se ci
fossero due tabelle, a e b, con la colonna comune Cognome.
Nella clausola where, viene eliminata qualunque riga in cui il cognome nella tabella a è
identico della tabella b. Questo serve a impedire che venga trovata la corrispondenza di un co-
gnome con se stesso.
Vengono quindi selezionati i cognomi che appaiono simili:
Si possono anche impostare ricerche di termini singoli all’interno di una voce di testo. Per
esempi di queste e altre ricerche di testo complesse, si rimanda al Capitolo 25.
ratteri formati da parti di informazioni più lunghe rispetto ai caratteri usuali, in Oracle è possibi-
le rappresentare stringhe in giapponese o con caratteri analoghi. Si consultino le voci NLSSORT,
NLS_INITCAP, NLS_LOWER e NLS_UPPER nel Capitolo 48. Oltre alla funzione SUBSTR,
Oracle supporta anche SUBSTRB (che usa i byte al posto dei caratteri), SUBSTRC (che usa i
caratteri Unicode completi), SUBSTR2 (che usa i codepoint UCS2) e infine SUBSTR4 (che
invece usa i codepoint UCS4).
7.7 Conclusioni
I dati possono essere di vari tipi, in primo luogo DATE, NUMBER e caratteri. I dati carattere
sono fondamentalmente stringhe di lettere, numeri e altri simboli e vengono spesso definiti stringhe
di caratteri, o semplicemente stringhe. Queste stringhe possono essere modificate o descritte
utilizzando funzioni di stringa. In Oracle sono disponibili due tipi di dati carattere: stringhe a
lunghezza variabile (tipo di dati VARCHAR2) e stringhe a lunghezza prefissata (tipo di dati
CHAR). I valori nelle colonne CHAR vengono riempiti con spazi in modo da occupare la lun-
ghezza completa della colonna, se il testo inserito risulta più corto della lunghezza di colonna
definita.
Funzioni come RPAD, LPAD, LTRIM, RTRIM, TRIM, LOWER, UPPER, INITCAP e SUBSTR
modificano effettivamente il contenuto di una stringa prima della visualizzazione.
Funzioni come LENGTH, INSTR e SOUNDEX descrivono le caratteristiche di una stringa,
come la lunghezza, la posizione di un certo carattere al suo interno o la somiglianza con altre
stringhe.
Tutte queste funzioni possono essere utilizzate da sole o in combinazione per selezionare e
presentare le informazioni presenti in un database Oracle. Si tratta di procedimenti chiari, costituiti
da fasi logiche semplici che possono essere combinate per ottenere risultati molto sofisticati.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 8
Ricerca
di espressioni regolari
A
partire da Oracle Database 10g, le funzioni SUBSTR, INSTR,
LIKE e REPLACE sono state potenziate ed estese in modo da supportare le ricerche di espressio-
ni regolari. Le espressioni regolari supportano una vasta gamma di controlli e verifiche standar-
dizzati, come la corrispondenza di valori per un certo numero di volte, le ricerche di caratteri di
punteggiatura o le ricerche di cifre. È possibile utilizzare queste nuove funzioni per effettuare
ricerche avanzate su stringhe; Queste nuove funzioni prendono il nome di REGEXP_SUBSTR,
REGEXP_INSTR, REGEXP_LIKE e REGEXP_REPLACE.
Gli utenti che abbiano già usato in precedenza il comando grep di UNIX per effettuare
ricerche di espressioni regolari nei file di testo potrebbero già avere una certa familiarità con i
concetti e le tecniche di ricerca che entrano in campo.
Ora è necessario comunicare a Oracle di continuare fino a quando non trova un altro carat-
tere '-' nella stringa. A tal fine si utilizza l’operatore '[^', un’espressione con parentesi quadra che
indica che i valori accettabili corrispondono a qualunque carattere tranne le espressioni rappre-
sentate nell’elenco. Il comando a questo punto appare in questo modo:
REGE
----
-456
148 CAPITOLO 8
Questo comando indica a Oracle di cercare '-' seguito da uno o più caratteri diversi da '-',
seguiti da '-'. Si osservi che se si aggiunge un '-' in più alla fine dell’espressione regolare, si
ottiene il trattino '-' come parte della stringa restituita:
REGEX
-----
-456-
La maggior parte degli utenti (e degli sviluppatori) non troverà comodo digitare stringhe
come la seguente:
'-[^-]+'
select SUBSTR('123-456-7890',
INSTR('123-456-7890', '-',1,1),
INSTR('123-456-7890', '-',1,2)-
INSTR('123-456-7890', '-',1,1))
from DUAL;
In confronto, la funzione REGEXP_SUBSTR è molto più concisa. Come si vedrà negli esempi
proposti più avanti nel capitolo, le ricerche di espressioni regolari consentono di codificare mo-
delli di ricerca complessi in una singola chiamata a funzione.
La Tabella 8.1 mostra gli operatori con le espressioni regolari e le loro descrizioni. La com-
prensione degli operatori coinvolti è fondamentale per un uso efficace delle capacità di ricerca
offerte dalle espressioni regolari.
Proviamo ad applicare alcuni di questi operatori e di classi di caratteri iniziando con una
semplice ricerca. Innanzi tutto, selezioniamo tutte le stringhe nella stringa di esempio che con-
tengono il carattere due punti:
select REGEXP_SUBSTR
('MIO REGISTRO: Debiti, Crediti e Fatture 1940',
':' ) "REGEXP_SUBSTR"
from DUAL;
R
-
:
Sostituiamo ora questa ricerca con una ricerca di un carattere di punteggiatura utilizzando la
classe di caratteri [:punct:]:
select REGEXP_SUBSTR
('MIO REGISTRO: Debiti, Crediti e Fatture 1940',
RICERCA DI ESPRESSIONI REGOLARI 149
'[:punct:]' ) "REGEXP_SUBSTR"
from DUAL;
R
-
:
A partire da questo punto della stringa la ricerca prosegue sino a incontrare la virgola suc-
cessiva:
select REGEXP_SUBSTR
('MIO REGISTRO: Debiti, Crediti e Fatture 1940',
'[:punct:][^,]+,' ) "REGEXP_SUBSTR"
from DUAL;
REGEXP_SU
---------
: Debiti,
È possibile utilizzare la classe di caratteri [:digit:] per trovare i numeri nella stringa:
select REGEXP_SUBSTR
('MIO REGISTRO: Debiti, Crediti e Fatture 1940',
'[[:digit:]]+' ) "REGEXP_SUBSTR"
from DUAL;
REGE
----
1940
Come mostrato in questo esempio, è possibile utilizzare le classi di caratteri per consolidare
le ricerche di più valori. Quando si lavora con le stringhe di ricerca, in particolare se non si ha
una precedente esperienza di uso delle espressioni regolari, è consigliabile iniziare con la versio-
ne più semplice possibile e procedere aumentando gradualmente la complessità.
8.2 REGEXP_SUBSTR
La funzione REGEXP_SUBSTR, come mostrato negli esempi precedenti, utilizza le espressioni
regolari per specificare i punti iniziale e finale della stringa restituita. La sintassi di
REGEXP_SUBSTR è mostrata nel listato seguente. REGEXP_SUBSTR restituisce la stringa
come dati VARCHAR2 o CLOB nel medesimo set di caratteri utilizzato da stringa_di_origine.
REGEXP_SUBSTR(stringa_di_origine, modello
[, posizione
[, occorrenza
[, parametro_di_corrispondenza ]
]
]
)
Gli esempi presentati finora nel capitolo si sono concentrati sulla variabile modello, ossia
l’espressione regolare, che può contenere al massimo 512 byte. Come illustrato nella sintassi, è
150 CAPITOLO 8
[]d Espressione tra parentesi quadre per specificare un elenco di corrispondenze che devono concordare
con una qualunque delle espressioni rappresentate nell’elenco. Un’espressione con un elenco di non
corrispondenze inizia con un accento circonflesso (^) e specifica un elenco che corrisponde a qualun-
que carattere tranne le espressioni rappresentate nell’elenco.
\n e L’espressione di riferimento all’indietro (n è una cifra compresa tra 1 e 9) corrisponde alla nesima
sottoespressione racchiusa tra parentesi e precedente \n.
[..] f Specifica un elemento di collazione e può essere un elemento multicarattere (per esempio, [.ch.] in
spagnolo).
[: :] g Specifica le classi di caratteri (per esempio, [:alpha:]). Corrisponde a qualunque carattere della classe di
caratteri.
[==] h Specifica le classi di equivalenza. Per esempio, [=a=] corrisponde a tutti i caratteri che hanno la lettera
base 'a'.
e. L’espressione di riferimento all’indietro '\n' corrisponde alla stessa stringa di caratteri con la quale ha trovato corrispondenza
l’nesima sottoespressione. Il carattere n dev’essere una cifra compresa tra 1 e 9, a designare l’nesima sottoespressione, numerata da
sinistra a destra. L’espressione non è valida se la stringa di origine contiene meno di n sottoespressioni prima di \n. Per esempio,
l’espressione regolare ^(.*)\1$ corrisponde a una riga costituita da due apparizioni adiacenti della medesima stringa. Oracle supporta
l’espressione di riferimento all’indietro nel modello dell’espressione regolare e nella stringa di sostituzione della funzione
REGEXP_REPLACE.
f. Un elemento di collazione è un’unità di collazione e nella maggior parte dei casi è uguale a un carattere, anche se in alcune lingue
può essere costituito da due o più caratteri. Storicamente la sintassi delle espressioni regolari non accetta degli intervalli contenenti
elementi di collazione multicarattere, come l’intervallo da ‘a’ a ‘ch’. Lo standard POSIX introduce il delimitatore degli elementi di
collazione ‘[..]’, che consente di delimitare gli elementi di collazione multicarattere come ‘[a-[.ch.]]’. Gli elementi di collazione accet-
tati da Oracle sono determinati dall’impostazione del parametro di inizializzazione NLS_SORT. L’elemento di collazione è valido solo
all’interno dell’espressione tra parentesi quadre.
g. Nelle espressioni regolari inglesi le espressioni di intervallo spesso indicano una classe di caratteri. Per esempio, ‘[a-z]’ indica
qualunque carattere minuscolo. Questa convenzione non è utile negli ambienti multilingua in cui il primo e l’ultimo carattere di una data
classe di caratteri potrebbero non essere gli stessi in tutte le lingue. Lo standard POSIX introduce la sintassi della classe di caratteri
portabile ‘[::]’.
In aggiunta agli operatori, Oracle supporta le classi di caratteri seguenti basate sulle definizioni delle classi di caratteri contenute nei
dati di classificazione NLS:
Sintassi della classe di caratteri Significato
[:alnum:] Tutti i caratteri alfanumerici.
[:alpha:] Tutti i caratteri alfabetici.
[:blank:] Tutti i caratteri di spaziatura.
[:cntrl:] Tutti i caratteri di controllo (non stampabili).
[:digit:] Tutte le cifre numeriche.
[:graph:] Tutti i caratteri [:punct:], [:upper:], [:lower:] e [:digit:].
[:lower:] Tutti i caratteri alfabetici minuscoli.
[:print:] Tutti i caratteri stampabili.
[:punct:] Tutti i caratteri di punteggiatura.
[:space:] Tutti i caratteri di spaziatura (non stampabili).
[:upper:] Tutti i caratteri alfabetici maiuscoli.
[:xdigit:] Tutti i caratteri esadecimali validi.
Questa sintassi per le classi di caratteri consente di fare un uso migliore delle definizioni di caratteri NLS per scrivere espressioni
regolari flessibili. Queste classi di caratteri sono valide solo all’interno dell’espressione tra parentesi quadre.
h. Oracle supporta le classi di equivalenza attraverso la sintassi POSIX ‘[==]’. Una lettera di base e tutte le sue versioni accentate
costituiscono una classe di equivalenza. Per esempio, la classe di equivalenza ‘[=a=]’ corrisponde ad ä e â. Le classi di equivalenza
sono valide solo all’interno dell’espressione tra parentesi quadre.
È importante segnalare questa restrizione a proposito delle classi di equivalenza: Le versioni composte e scomposte della stessa
classe di equivalenza non corrispondono. Per esempio, ‘ä’ non corrisponde ad ‘a’ seguita dalla dieresi.
anche possibile specificare dei parametri relativi alle condizioni posizione, occorrenza e
parametro_di_corrispondenza.
La variabile posizione indica a REGEXP_SUBSTR dove iniziare la ricerca nella
stringa_di_origine. Il valore predefinito di posizione è 1 (il primo carattere). La variabile occor-
renza è un intero che indica quale occorrenza di modello in stringa_di_origine Oracle deve
cercare. Il valore predefinito di occorrenza è 1. Le variabili posizione e occorrenza non sono
disponibili nella funzione SUBSTR standard: esse consentono di combinare le capacità di SUBSTR
con INSTR permettendo nel contempo di effettuare ricerche di espressioni regolari, che rappre-
sentano delle notevoli estensioni rispetto alla funzionalità di SUBSTR.
152 CAPITOLO 8
select REGEXP_SUBSTR
('MIO REGISTRO: Debiti, Crediti e Fatture 1940',
'mio' ,1,1, 'i') "REGEXP_SUBSTR"
from DUAL;
REG
---
MIO
Si modifichi ora l’istruzione in modo da avere una ricerca con distinzione tra maiuscolo e
minuscolo:
select REGEXP_SUBSTR
('MIO REGISTRO: Debiti, Crediti e Fatture 1940',
'mio' ,1,1, 'c') "REGEXP_SUBSTR"
from DUAL;
REG
---
Non viene restituito alcunché a causa della non corrispondenza tra maiuscole e minuscole. Per
default le ricerche prevedono questa distinzione.
È possibile utilizzare i parametri modello e occorrenza allo stesso modo in cui li si impiega
in INSTR. Nell’esempio seguente viene restituita la seconda cifra:
RICERCA DI ESPRESSIONI REGOLARI 153
select REGEXP_SUBSTR
('MIO REGISTRO: Debiti, Crediti e Fatture 1940',
'[[:digit:]]' ,1,2) "REGEXP_SUBSTR"
from DUAL;
R
-
9
La scrittura della stessa query con SUBSTR e INSTR (e supponendo che le due cifre possano
non essere consecutive) sarebbe molto più complessa.
REGEXP_INSTR
La funzione REGEXP_INSTR utilizza le espressioni regolari per restituire il punto iniziale e
finale del modello di ricerca. La sintassi di REGEXP_INSTR è mostrata nel listato seguente.
REGEXP_INSTR restituisce un intero che indica la posizione dell’inizio o della fine del modello
di ricerca, o uno 0 se non trova alcuna corrispondenza.
select REGEXP_INSTR
('MIO REGISTRO: Debiti, Crediti e Fatture 1940',
'[[:digit:]]') "REGEXP_INSTR"
from DUAL;
REGEXP_INSTR
------------
42
154 CAPITOLO 8
select REGEXP_INSTR
('MIO REGISTRO: Debiti, Crediti e Fatture 1940',
'[[:digit:]]',1,1,1) "REGEXP_INSTR"
from DUAL;
REGEXP_INSTR
------------
43
Anche per le ricerche che non hanno modelli complessi, è possibile decidere di usare
REGEXP_INSTR al posto di INSTR per semplificare i processi matematici e logici coinvolti
nelle query che combinano le capacità di INSTR e SUBSTR. Occorre accertarsi di considerare
attentamente le impostazioni per la distinzione tra maiuscolo e minuscolo specificate tramite il
parametro parametro_di_corrispondenza.
REGEXP_LIKE
Oltre alle funzioni per le espressioni regolari mostrate nei listati precedenti, è possibile utilizzare
la funzione REGEXP_LIKE, che permette l’uso delle espressioni regolari nelle clausole where.
Per esempio, quale numero di telefono inizia con '415'?
select Cognome
from INDIRIZZO
where REGEXP_LIKE (Telefono,'415+');
COGNOME
-----------------------------
ADAMS
ZACK
YARROW
WERSCHKY
BRANT
EDGAR
REGEXP_LIKE(stringa_di_origine, modello
[parametro_di_corrispondenza ]
)
select Cognome
from INDIRIZZO
where REGEXP_LIKE (Telefono, '[[:digit:]]');
RICERCA DI ESPRESSIONI REGOLARI 155
Se una funzione TO_NUMBER fallisce perché viene trovato un segno di punteggiatura nel
valore, è possibile visualizzare le righe che hanno causato il fallimento:
select Cognome
from INDIRIZZO
where REGEXP_LIKE (Telefono, '[[:punct:]]');
REPLACE e REGEXP_REPLACE
La funzione REPLACE sostituisce un valore in una stringa con un altro. Per esempio, è possibile
sostituire ciascuna occorrenza di una lettera con un numero corrispondente. Il formato di REPLACE
è il seguente:
EGOREG
REPLACE('GEORGE', 'GE', NULL) = OR
Se la lunghezza della stringa ricercata è diversa da zero, si può sapere quante volte una
stringa è stata trovata nella stringa da cercare. Innanzi tutto, si calcola la lunghezza della stringa
originale:
LENGTH('GEORGE')
Poi si calcola la lunghezza della stringa dopo aver rimosso i valori della stringa ricercata:
Poi si divide la differenza per la lunghezza della stringa ricercata per trovare quante occor-
renze della stringa ricercata sono state sostituite:
select LENGTH('GEORGE')
- LENGTH(REPLACE('GEORGE', 'GE', NULL))
/
LENGTH('GE') AS Contatore
from DUAL;
CONTATORE
---------
2
Con l’eccezione di stringa_di_sostituzione, tutte queste variabili sono state descritte nei
paragrafi precedenti del capitolo. La variabile stringa_di_sostituzione indica a Oracle cosa uti-
lizzare per sostituire la parte della stringa_d_origine corrispondente a modello. La variabile
occorrenza è un intero non negativo che specifica l’occorrenza dell’operazione: Se è 0, tutte le
occorrenze della corrispondenza vengono sostituite; se si specifica un intero positivo, Oracle
sostituisce l’nesima occorrenza.
Si consideri la colonna Telefono della tabella INDIRIZZO. Innanzi tutto si cercheranno i
numeri corrispondenti al formato ###-###-####, ossia un gruppo di tre cifre seguite da un altro
gruppo di tre cifre e da un gruppo di quattro cifre, tutti separati da caratteri ‘-’. È possibile
trovare le righe che soddisfano questo criterio cercando questi gruppi di cifre in una chiamata
alla funzione REGEXP_SUBSTR:
REGEXP_SUBST
------------
213-555-0223
415-555-7530
214-555-8383
312-555-1166
707-555-8900
312-555-1414
415-555-6842
415-555-2178
415-555-7387
415-555-7512
415-555-6252
617-555-0125
603-555-2242
202-555-1414
718-555-1638
214-555-8383
503-555-7491
Ora si utilizza REGEXP_REPLACE per racchiudere tra parentesi le prime tre cifre lasciando
fuori il primo trattino trovato. A tal fine si fa riferimento al primo gruppo di dati con \1, al
secondo con \2 e al terzo con \3.
from INDIRIZZO;
REGEXP_REPLACE
------------------------------------------
(213) 555-0223
(415) 555-7530
(214) 555-8383
(312) 555-1166
(707) 555-8900
(312) 555-1414
(415) 555-6842
(415) 555-2178
(415) 555-7387
(415) 555-7512
(415) 555-6252
(617) 555-0125
(603) 555-2242
(202) 555-1414
(718) 555-1638
(214) 555-8383
(503) 555-7491
L’output mostra il risultato della chiamata alla funzione REGEXP_REPLACE; i prefissi sono
racchiusi tra parentesi e il primo trattino è stato eliminato.
Per illustrare il funzionamento della variabile occorrenza, la funzione REGEXP_REPLACE
seguente sostituisce con un punto il secondo ‘5’ trovato in un numero di telefono:
REGEXP_REPLACE
------------------------------------------
213-5.5-0223
415-.55-7530
214-5.5-8383
312-5.5-1166
707-5.5-8900
312-5.5-1414
415-.55-6842
415-.55-2178
415-.55-7387
415-.55-7512
415-.55-6252
617-5.5-0125
603-5.5-2242
202-5.5-1414
718-5.5-1638
214-5.5-8383
503-.55-7491
È possibile modificare ulteriormente questa query in modo da escludere le prime tre cifre
come possibili corrispondenze (impostazione del punto di partenza a 4) e sostituire invece la
quarta occorrenza:
158 CAPITOLO 8
REGEXP_REPLACE
------------------------------------------
213-555-0223
415-555-7.30
214-555-8383
312-555-1166
707-555-8900
312-555-1414
415-555-6842
415-555-2178
415-555-7387
415-555-7.12
415-555-62.2
617-555-012.
603-555-2242
202-555-1414
718-555-1638
214-555-8383
503-555-7491
REGEXP_REPLACE
------------------------------------------
415-555-7.30
415-555-7.12
415-555-62.2
617-555-012.
È possibile utilizzare la capacità di ricerca di valori alternativi per combinare più criteri di
ricerca in una singola query. L’esempio seguente sostituisce un 5 o un 2 e le occorrenze di ‘5’ e
‘2’ contribuiscono entrambe al conteggio di occorrenza:
REGEXP_REPLACE
------------------------------------------
213-555-0.23
415-555-7.30
415-555-684.
415-555-.178
415-555-7.12
415-555-6.52
617-555-01.5
603-555-.242
Q
ualsiasi cosa si faccia, in particolar modo in ambito
economico, viene misurata, spiegata e spesso guidata dai numeri. Oracle non può rimediare a
questa ossessione per i numeri e all’illusione di controllo che spesso l’accompagna, però agevola
l’analisi accurata e completa delle informazioni in un database. Una buona analisi dei numeri
spesso consente di rivelare tendenze e fatti che inizialmente non risultano evidenti.
La Tabella 9.1 mostra queste funzioni divise per classe. Alcune di esse rientrano in più di
una classe, mentre altre possono essere classificate sia come funzioni di stringa sia come funzioni
numeriche, oppure vengono utilizzate per convertire i dati da una tipologia all’altra. Il Capitolo
11 è dedicato a questo tipo di funzioni.
9.2 Notazione
Le funzioni sono riportate con questo tipo di notazione:
FUNZIONE( v a l o r e [, opzione ] )
La funzione stessa viene indicata con caratteri maiuscoli, mentre i valori e le opzioni sono in
carattere corsivo minuscolo. Tutte le volte che il termine valore è indicato in questo modo, può
rappresentare un numero vero e proprio, il nome di una colonna numerica in una tabella, il
risultato di un calcolo oppure una variabile. Dato che in Oracle non è consentito utilizzare i
numeri come nomi di colonna, un numero vero e proprio non dev’essere racchiuso tra apici (che
invece segnalano una stringa vera e propria in una funzione di stringa). Anche i nomi di colonna
non devono essere racchiusi tra apici.
In tutte le funzioni compare soltanto una coppia di parentesi. Il valore su cui opera questa
funzione, così come le informazioni aggiuntive che è possibile passare alla funzione, devono
essere racchiusi tra parentesi.
Alcune funzioni hanno delle opzioni, elementi che non sono indispensabili per il loro
funzionamento, ma che possono offrire un maggiore controllo se utilizzate. Le opzioni sono
ATAN2(valore1, valore2) ATAN2 restituisce l’arcotangente di due valori. I valori di input sono infiniti, gli output sono
espressi in radianti.
BITAND(valore1, valore2) Operazione di calcolo AND sui bit di valore1 e valore2, che devono entrambi risolversi in nu-
meri non negativi. Restituisce un intero.
(segue)
GIOCARE CON I NUMERI 163
FUNZIONI DI AGGREGAZIONE
FUNZIONE DEFINIZIONE
AVG(valore) Media di valore.
(segue)
164 CAPITOLO 9
GROUPING(espressione) Utilizzata in combinazione con le funzioni ROLLUP e CUBE per individuare i valori NULL.
GROUPING_ID Restituisce un numero corrispondente al vettore del bit GROUPING associato con una riga.
FUNZIONI DI ELENCO
FUNZIONE DEFINIZIONE
COALESCE(valore1, valore2, ...) Restituisce il primo valore non NULL nell’elenco delle espressioni.
sempre visualizzate tra parentesi quadre [ ]. Le parti indispensabili di una funzione sono sempre
inserite prima delle parti facoltative.
GIOCARE CON I NUMERI 165
Questa tabella è utile perché presenta valori con caratteristiche diverse, che sono indicate
dai nomi scelti per le righe. La riga NUMERO INT non contiene decimali. La riga DECIMALE
INF contiene decimali minori di 0.5, la riga DECIMALE MED contiene decimali uguali a 0.5 e
la riga DECIMALE SUP contiene decimali maggiori di 0.5. Questa gamma è particolarmente
importante quando si utilizzano le funzioni ROUND e TRUNC e per comprendere come queste
influiscono sul valore di un numero.
A destra della colonna Nome sono presenti altre tre colonne: Sopra, che contiene soltanto i
numeri sopra lo zero (numeri positivi); Sotto, che contiene soltanto i numeri sotto lo zero, e
Vuoto, che contiene valori NULL.
NOTA In Oracle, una colonna numerica può anche non contenere alcun valore al
suo interno: quando contiene valori NULL, non significa che vi sono valori pari a zero, bensì
semplicemente che è vuota. Questo fatto ha conseguenze importanti nell’esecuzione dei calcoli,
come illustrato più avanti.
Non tutte le righe di questa tabella MATEMATICA sono necessarie per dimostrare il
funzionamento della maggior parte delle funzioni matematiche; negli esempi a seguire viene
utilizzata soprattutto l’ultima riga, DECIMALE SUP. Inoltre, è stato utilizzato il comando column
di SQL*Plus per mostrare esplicitamente la precisione dei calcoli, in modo che siano ben visibili
i risultati delle funzioni che influiscono sulla precisione di un numero. Per analizzare i comandi
SQL e SQL*Plus che hanno prodotto il risultato che segue, consultare lo script che accompagna
i comandi create table per le tabelle di esempio.
NULL
Nell’esempio seguente, le stesse quattro operazioni aritmetiche vengono eseguite nuovamente,
questa volta utilizzando le colonne Sopra e Vuoto al posto di Sopra e Sotto. Si osservi che
qualsiasi operazione aritmetica che coinvolga un valore NULL ha come risultato un valore NULL.
Le colonne calcolate (colonne i cui valori sono il risultato di un calcolo) Piu, Meno, Per e Diviso
sono tutte vuote.
Risulta evidente che un valore NULL non può essere utilizzato in un calcolo. NULL non
coincide con zero: può essere considerato come un valore sconosciuto. Per esempio, si supponga
di avere una tabella con i nomi dei propri amici e la loro età, ma che la colonna Eta per PAT
SMITH sia vuota, perché la sua età è sconosciuta. Qual è la differenza tra l’età dell’amica e la
propria? Non è ovviamente la propria età meno zero. Un valore noto meno un valore sconosciuto
dà come risultato un valore sconosciuto, ovvero NULL. Non è quindi possibile inserire una
risposta, perché non esiste. Dato che il calcolo è impossibile, la risposta è NULL.
Questa è anche la ragione per cui non è possibile utilizzare NULL con un segno di uguale in
una clausola where (Capitolo 5). Non ha senso dire che, se x è sconosciuto e y è sconosciuto, x
e y sono uguali. Se le età del Sig. Rossi e del Sig. Bianchi sono sconosciute, non significa che i
due signori abbiano la stessa età.
Esistono anche casi in cui NULL significa “irrilevante”, come può essere un numero di
appartamento in una casa. In alcuni casi, il numero di appartamento potrebbe essere NULL
perché è sconosciuto (anche se in realtà esiste), mentre in altri casi risulta NULL semplicemente
perché non esiste. I valori NULL verranno esaminati in maniera più dettagliata più avanti in
questo capitolo nel paragrafo “NULL nelle funzioni di gruppo”.
volume delle merci da consegnare, sarebbe assolutamente impossibile per lui valutare il numero
degli aerei cargo necessari? Naturalmente no. Sa per esperienza quant’è il peso e il volume
medio dei pacchi, quindi considera questi valori ipotetici per i clienti che non hanno fornito le
informazioni necessarie. Ecco le informazioni fornite dai clienti:
CLIENTE PESO
------------- ------
JOHNSON TOOL 59
DAGG SOFTWARE 27
TULLY ANDOVER
CLIENTE NVL(PESO,43)
------------- --------------
JOHNSON TOOL 59
DAGG SOFTWARE 27
TULLY ANDOVER 43
In questo caso, si sa che il peso medio dei pacchi equivale a 43 chili, quindi viene utilizzata
la funzione NVL per inserire il valore 43 ogni volta che il pacco di un cliente ha un peso
sconosciuto, e quindi dove il valore nella colonna è NULL. Nell’esempio, TULLY ANDOVER
non ha fornito il peso del pacco, ma è comunque possibile calcolare il peso totale dei pacchi e
ottenere una valutazione attendibile. La sintassi per la funzione NVL è la seguente:
In NVL2, espr1 non può mai essere restituita, mentre saranno restituite espr2 o espr3. Se
espr1 non è NULL, NVL2 restituisce espr2, mentre se espr1 è NULL, NVL2 restituisce espr3.
L’argomento espr1 può essere di un tipo di dato qualunque; gli argomenti espr2 ed espr3 possono
essere di qualunque tipo di dato tranne LONG. A partire da Oracle Database 10g, è possibile
utilizzare la funzione NANVL per i tipi di dati BINARY_FLOAT e BINARY_DOUBLE. NANVL
accetta due variabili e restituisce la seconda se la prima non è un numero.
168 CAPITOLO 9
ABS(valore)
ABS(146) = 146
ABS(-30) = 30
CEIL
La funzione CEIL (abbreviazione di “ceiling”, “soffitto”) produce semplicemente l’intero (o
numero intero) più piccolo che è maggiore o uguale a un valore specificato. Occorre fare molta
attenzione all’effetto di questa funzione su numeri negativi.
Nei listati seguenti vengono illustrati la sintassi della funzione CEIL e alcuni esempi:
CEIL(valore)
CEIL(2) = 2
CEIL(1.3) = 2
CEIL(-2) = -2
CEIL(-2.3) = -2
FLOOR
La funzione FLOOR (lett. “pavimento”) è ovviamente l’opposto della funzione CEIL. Nei listati
seguenti vengono illustrati la sintassi della funzione FLOOR e alcuni esempi:
FLOOR(valore)
FLOOR(2) = 2
FLOOR(1.3) = 1
FLOOR(-2) = -2
FLOOR(-2.3) = -3
MOD
La funzione MOD (“modulo”) è una piccola e antica funzione utilizzata soprattutto
nell’elaborazione dei dati per scopi strani, come “controllare le cifre”, operazione che aiuta a
garantire la trasmissione accurata di una stringa di numeri. La funzione MOD divide un valore
per un divisore e fornisce il resto. Per esempio, MOD(23,6) = 5 significa dividere 23 per 6. La
risposta è 3 con resto di 5, quindi il risultato dell’operazione modulo è 5.
La sintassi della funzione MOD è la seguente:
Sia valore sia divisore possono essere un qualunque numero reale. Il valore di MOD è zero
se divisore è zero o negativo. Si osservino gli esempi seguenti:
MOD(100,10) = 0
MOD(22,23) = 22
MOD(10,3) = 1
MOD(-30.23,7) = -2.23
MOD(4.1,.3) = .2
Il secondo esempio mostra il comportamento di MOD qualora il divisore sia più grande del
dividendo (il numero che viene diviso). Il risultato è il dividendo stesso. Si osservi anche questo
caso importante, in cui valore è un numero intero:
MOD(valore,1) = 0
REMAINDER(-30.23,7) = -2.23
POWER
La funzione POWER offre semplicemente la possibilità di elevare un valore a un dato esponente
positivo, come mostrato di seguito:
SQRT(valore)
SQRT(64) = 8
SQRT(66.666) = 8,16492498
SQRT(4) = 2
EXP, LN e LOG
Le funzioni EXP, LN e LOG vengono utilizzate raramente nei calcoli commerciali, ma sono
molto comuni in campo scientifico e tecnico. EXP è e (2.71828183…) elevato alla potenza
170 CAPITOLO 9
EXP(valore)
EXP(3) = 20,0855369
EXP(5) = 148.413159
LN(valore)
LN(3) = 1,09861229
LN(20,0855369) = 3
LOG(valore)
LOG(EXP(1),3) = 1,09861229
LOG(10,100) = 2
ROUND e TRUNC
ROUND e TRUNC sono due funzioni a valore singolo correlate. Con la funzione TRUNC vengono
troncate o eliminate le cifre decimali di un numero; con la funzione ROUND un numero viene
arrotondato a meno di un dato numero di cifre decimali. La sintassi delle funzioni ROUND e
TRUNC è la seguente:
Nel listato seguente vengono applicate alcune proprietà degne di nota. Innanzi tutto si osservi
questo semplice esempio di selezione dalla tabella MATEMATICA con il comando select.
Vengono richieste due cifre decimali (contando dal punto decimale verso destra).
Soltanto l’ultima riga viene troncata, perché è l’unica con tre cifre dopo il punto decimale.
Sia i numeri positivi sia quelli negativi dell’ultima riga sono stati arrotondati o troncati: 66.666
è stato arrotondato a un numero superiore, 66.67, mentre il valore –77.777 è stato arrotondato a
un numero inferiore, –77.78 (ancor più negativo). Quando l’arrotondamento viene impostato a
zero cifre, si ottiene questo risultato:
GIOCARE CON I NUMERI 171
Si osservi che il valore decimale .5 è stato arrotondato per eccesso quando 55.5 è diventato
56. In questo modo, viene applicata la più comune convenzione di arrotondamento americana
(altre convenzioni arrotondano per eccesso solo se la parte decimale di un numero è maggiore di
.5). Si possono paragonare questi risultati con quelli ottenuti con le funzioni CEIL e FLOOR. Le
differenze sono significative:
Infine si osservi che sia ROUND sia TRUNC possono operare con cifre decimali negative, a
sinistra del punto decimale:
L’arrotondamento di un numero negativo può essere molto utile nella produzione di report
di tipo economico, in cui i valori della popolazione o di somme di denaro devono essere arrotondati
a milioni, miliardi o migliaia di miliardi.
SIGN
La funzione SIGN è il rovescio della medaglia della funzione ABS. ABS indica la grandezza di
un valore ma non il suo segno, SIGN indica il segno di un valore ma non la sua grandezza.
172 CAPITOLO 9
La funzione SIGN viene spesso utilizzata insieme con la funzione DECODE. Questa funzione
viene descritta nel Capitolo 16.
SIN, SINH, COS, COSH, TAN, TANH, ACOS, ATAN, ATAN2 e ASIN
Le funzioni trigonometriche seno, coseno, e tangente sono funzioni scientifiche e tecniche non
molto utilizzate in operazioni commerciali. Le funzioni SIN, COS e TAN consentono di ottenere
i valori delle funzioni trigonometriche standard per un angolo espresso in radianti (gradi
moltiplicati per pi greco diviso per 180). Con le funzioni SINH, COSH e TANH vengono fornite
le funzioni iperboliche per un dato angolo.
SIN(valore)
SIN(30*3,141592655/180) = .5
COSH(valore)
COSH(0) = 1
Si prenda come esempio la funzione AVG. Si supponga di avere un elenco di 100 amici con
le rispettive età. Se si scegliessero 20 nomi a caso e si calcolasse la media delle loro età, quanto
varierebbe il risultato rispetto a quello ottenuto prendendo un diverso elenco casuale di altre 20
persone e calcolandone la media, oppure rispetto alla media di tutti e 100? In effetti, le medie di
questi tre gruppi sarebbero molto vicine. Il senso è che la funzione AVG in qualche modo non
viene influenzata dalla mancanza di dati, anche se i dati mancanti rappresentano una percentuale
elevata rispetto al numero totale dei record disponibili.
NOTA La funzione AGV non è immune alla mancanza di dati, e possono verificarsi
casi in cui il calcolo così effettuato risulta significativamente diverso dal valore corretto (come
quando i dati mancanti non sono distribuiti in maniera casuale), tuttavia si tratta di casi meno
comuni.
Si può provare a paragonare la relativa ininfluenza della mancanza di dati per la funzione
AVG con quello che accade, per esempio, con la funzione SUM. Quanto è vicina al risultato
corretto la somma delle età di 20 amici rispetto alla somma di tutte e 100 le età? Non è affatto
vicina. Quindi, avendo una tabella di amici in cui soltanto 20 su 100 hanno fornito la loro età e
80 su 100 non hanno fornito alcun dato (NULL), quale sarebbe la statistica più affidabile sull’intero
gruppo e meno influenzabile dall’assenza di dati, l’età media dei 20 nominativi calcolata con la
funzione AVG, o la somma delle loro età calcolata con la funzione SUM? Si tratta di una questione
completamente diversa rispetto alla possibilità di valutare la somma di tutti e 100 sulla base di 20
(in effetti, è esattamente la media dei 20 calcolata con AVG, moltiplicata per 100). Il punto è che,
se non si conosce il numero delle righe con dati NULL, è possibile utilizzare il comando seguente
per ottenere un risultato abbastanza attendibile:
La stessa verifica sull’attendibilità dei risultati consente di definire in che modo le altre
funzioni di gruppo rispondono alla presenza di dati NULL. Le funzioni STDDEV e VARIANCE
consentono di calcolare la tendenza centrale; anch’esse sono relativamente insensibili alla
mancanza di dati (questo argomento verrà trattato nel paragrafo “STDDEV e VARIANCE,” più
avanti nel capitolo.)
Le funzioni MAX e MIN consentono di misurare i valori estremi dei dati disponibili. Le
funzioni MAX e MIN possono fluttuare ampiamente, mentre AVG riamane relativamente costante:
se si aggiunge una persona di 100 anni a un gruppo di 99 persone di 50 anni, l’età media aumenta
soltanto a 50.5, ma l’età massima è raddoppiata. Con l’aggiunta di un neonato, l’età media
ritorna a 50 anni, ma l’età minima scende a 0. È evidente che i valori NULL mancanti o sconosciuti
possono influire significativamente sulle funzioni MAX, MIN e SUM, quindi occorre prestare
particolare attenzione quando si usano queste funzioni, soprattutto se una percentuale significativa
di dati è NULL.
È possibile creare funzioni in cui venga considerata anche la distribuzione dei dati e la
quantità di valori NULL confrontata con la quantità di valori reali e ottenere ipotesi attendibili
con MAX, MIN e SUM? La risposta è affermativa, ma tali funzioni sarebbero proiezioni statistiche,
in cui le conclusioni su un particolare insieme di dati devono essere rese esplicite. Non si tratta
di un compito adeguato per una funzione di gruppo di carattere generale. Alcuni statistici
potrebbero sostenere che queste funzioni dovrebbero avere un risultato NULL se è presente un
valore NULL, poiché un risultato di altro tipo potrebbe essere fuorviante. In Oracle viene
comunque prodotto un risultato, ma spetta all’utente decidere se esso è attendibile oppure no.
174 CAPITOLO 9
La funzione COUNT rappresenta un caso speciale. Infatti, può essere utilizzata con valori
NULL fornendo sempre come risultato un numero, mai un valore NULL. La sintassi e l’utilizzo
di questa funzione verranno illustrati tra breve, ma per fare un semplice confronto tra COUNT e
le altre funzioni di gruppo, è sufficiente segnalare che con questa funzione vengono contate tutte
le righe non NULL di una colonna, oppure vengono contate tutte le righe. In altre parole, se
viene richiesto di contare le età di 100 amici, il risultato visualizzato da COUNT è 20 (poiché
soltanto 20 su 100 hanno fornito la loro età). Se invece viene richiesto di contare le righe nella
tabella di amici senza specificare una colonna, il risultato visualizzato è 100. Un esempio di
queste differenze viene illustrato nel paragrafo “DISTINCT nelle funzioni di gruppo “ più avanti
in questo capitolo.
describe COMFORT
SUM(MEZZO)
----------
Con sole quattro righe da considerare nella tabella, è possibile convertire velocemente (o
ignorare) il fastidioso segno meno (–). La variabilità nella temperatura è in realtà la misura della
portata del cambiamento, ovvero l’indicazione di quanto la temperatura è cambiata. Non viene
compreso il segno del valore, quindi –6 è sbagliato. Se non viene corretto, e viene considerato in
un altro calcolo, come il cambiamento medio in un anno, la risposta sarà del tutto errata, come
mostrato di seguito:
176 CAPITOLO 9
select AVG(Mezzogiorno-Mezzanotte)
from COMFORT
where Citta = 'KEENE';
AVG(MEZZOGIORNO-MEZZANOTTE)
---------------------------
17.675
select AVG(ABS(Mezzogiorno-Mezzanotte))
from COMFORT
where Citta = 'KEENE';
AVG(ABS(MEZZOGIORNO-MEZZANOTTE)
-------------------------------
20.675
Combinando le funzioni in questo modo si segue la stessa tecnica illustrata nel Capitolo 7,
nel paragrafo sulle funzioni di stringa. Una funzione completa come:
ABS(Mezzogiorno-Mezzanotte)
viene semplicemente inserita in un’altra funzione come suo valore, come in:
AVG(valore)
AVG(ABS(Mezzogiorno-Mezzanotte))
In questo esempio, sono illustrate funzioni a valore singolo e di gruppo all’opera. Si noti che
è possibile inserire funzioni a valore singolo all’interno di funzioni di gruppo. Con le funzioni a
valore singolo viene calcolato un risultato per ciascuna riga, mentre con le funzioni di gruppo il
risultato viene considerato come valore effettivo della riga. Le funzioni a valore singolo possono
essere combinate (annidate una all’interno dell’altra) praticamente senza limite. Le funzioni di
gruppo possono contenere le funzioni a valore singolo al posto dei propri valori. In effetti, sono
in grado di contenere più funzioni a valore singolo al posto dei loro valori.
Come si procede per combinare funzioni di gruppo? Innanzi tutto, non ha alcun senso annidarle
in questo modo:
ERROR at line 1:
ORA-00978: nested group function without GROUP BY
AVG(Mezzogiorno)
non ha nessun senso annidare le funzioni di gruppo. L’eccezione a questa regola si ha nell’utilizzo
di group by all’interno dell’istruzione select; infatti il motivo per cui è stato prodotto il messaggio
di errore è proprio l’assenza di questo comando. Questo argomento verrà discusso nel Capitolo 12.
Può avere senso sommare, sottrarre, moltiplicare o dividere i risultati di due o più funzioni
di gruppo. Per esempio, l’istruzione:
MAX(MEZZOGIORNO)-MIN(MEZZOGIORNO)
---------------------------------
11.4
Questa query offre un buon esempio di come sia possibile ricavare informazioni dai dati
disponibili: le temperature medie nelle due città sono pressoché identiche, ma l’enorme sbalzo
di temperatura a Keene, paragonato ai valori di San Francisco, è un dato molto significativo sulla
variabilità annuale della temperatura nelle due città e sullo sforzo relativo che occorre per vestirsi
adeguatamente (o per riscaldare e raffreddare un’abitazione) in una città piuttosto che nell’altra.
La clausola group by verrà spiegata in maniera dettagliata nel Capitolo 12. In breve, in questo
esempio aveva il compito di vincolare le funzioni di gruppo a operare non sulla tabella completa,
bensì sui sottogruppi delle temperature per città.
STDDEV e VARIANCE
La deviazione standard e la varianza hanno in comune il significato statistico e utilizzano la
stessa sintassi delle altre funzioni di gruppo:
Per la sintassi delle funzioni statistiche elencate nella Tabella 9.1 si rimanda al Capitolo 48.
178 CAPITOLO 9
Ecco un esempio:
In questa query sono visualizzati alcuni risultati degni di nota. Innanzi tutto, con l’opzione
DISTINCT la funzione COUNT conta soltanto i nomi di città unici. Se si richiedesse di contare le
temperature di mezzanotte con questa opzione impostata, il risultato sarebbe 7, poiché due delle
otto temperature sono uguali. Quando la funzione COUNT viene utilizzata per Citta ma senza il
vincolo impostato con DISTINCT, il risultato è 8.
In questo esempio viene dimostrato che la funzione COUNT può essere applicata anche a
una colonna di caratteri. Non viene effettuato un calcolo sui valori presenti nella colonna, come
nel caso delle funzioni SUM o AVG; viene semplicemente contato il numero delle righe con un
valore nella colonna specificata.
La funzione COUNT presenta anche un’altra proprietà singolare: valore può essere un
asterisco, ovvero con COUNT è possibile ottenere il numero delle righe di una tabella, a prescindere
dal fatto che vi siano colonne specifiche con valori NULL. Le righe vengono contate anche se
tutti i campi hanno valore NULL.
Nelle altre funzioni di gruppo non è possibile utilizzare l’asterisco come nella funzione
COUNT, né è possibile utilizzare una colonna di caratteri come valore (cosa possibile con le
funzioni MAX e MIN). Viceversa, in tutte le funzioni di gruppo è possibile utilizzare l’opzione
DISTINCT, che vincola ad agire soltanto su valori unici. Con una tabella contenente valori come
questi:
NOME ETA
--------------- ----
GEORGE 42
ROBERT 52
NANCY 42
VICTORIA 42
FRANK 42
MEDIA TOTALE
----- ------
47 94
GIOCARE CON I NUMERI 179
che, se si desiderasse conoscere l’età media dei propri amici, non sarebbe la risposta corretta.
L’uso dell’opzione DISTINCT in funzioni diverse da COUNT è estremamente raro, tranne forse
in alcuni calcoli statistici. Per MAX e MIN si ottiene lo stesso risultato con o senza l’opzione
DISTINCT.
L’opzione alternativa a DISTINCT è ALL, che rappresenta l’impostazione predefinita. Con
l’opzione ALL si indica a SQL di verificare tutte le righe, anche se un valore viene riprodotto in
righe diverse. Non è necessario digitare l’opzione ALL; se non si specifica DISTINCT, viene
automaticamente utilizzata ALL.
Ora si confronti il risultato di questa query con il risultato seguente. Si osservino in particolare
i valori dei mesi di giugno e settembre per San Francisco, nonché quelli di dicembre per Keene:
Sulla riga di settembre per San Francisco non viene riportato nessun valore, poiché con le
funzioni GREATEST e LEAST non è stato possibile confrontare correttamente una temperatura
di mezzanotte effettiva con una temperatura di mezzogiorno sconosciuta. Negli altri due casi, la
temperatura di mezzanotte era effettivamente maggiore rispetto alla temperatura di mezzogiorno.
180 CAPITOLO 9
Sia GREATEST sia LEAST possono essere utilizzate con molti valori, che possono essere
colonne, numeri veri e propri, calcoli o combinazioni di altre colonne. Le funzioni GREATEST
e LEAST possono essere utilizzate anche con colonne di caratteri. Per esempio, è possibile
utilizzarle per selezionare i nomi che risultano ultimi (GREATEST) o primi (LEAST) in ordine
alfabetico:
GREATEST('Bob','George','Andrew','Isaiah') = Isaiah
LEAST('Bob','George','Andrew','Isaiah') = Andrew
È possibile utilizzare la funzione COALESCE per valutare più valori come valori non NULL.
A partire da una stringa di valori, COALESCE restituirà il primo valore non NULL incontrato; se
tutti i valori sono NULL, verrà visualizzato un risultato NULL.
Nella tabella COMFORT, per una delle misurazioni di San Francisco c’è un valore NULL
nella colonna Mezzogiorno. La query seguente restituisce:
COALESCE(MEZZOGIORNO,MEZZANOTTE)
--------------------------------
16.9
16.9
16.4
11.4
Nei primi due record dell’output, il valore visualizzato è il valore di Mezzogiorno. Nel terzo
record, il valore di Mezzogiorno è NULL quindi al suo posto viene restituito quello di Mezzanotte.
Le funzioni DECODE e CASE di Oracle offrono una funzionalità simile, come descritto nel
Capitolo 16.
Questo messaggio di errore è poco chiaro. Significa che Oracle ha rilevato un errore nella
logica della domanda. Se si richiedono le colonne, significa che si desidera che vengano
visualizzate le singole righe; l’utilizzo di MAX, una funzione di gruppo, significa che si desidera
visualizzare un risultato di gruppo per tutte le righe. Si tratta di due richieste di diverso tipo: con
la prima viene richiesto un insieme di righe, con la seconda una riga calcolata, quindi si innesca
un conflitto. Ecco come impostare la query:
Viene prodotta soltanto una riga. Quindi, si potrebbe pensare che la combinazione di una
richiesta per le colonne Citta e DataCampione insieme con la funzione MAX per i valori di
Mezzogiorno non sia contraddittoria come illustrato poc’anzi. Ma cosa sarebbe successo se fosse
stata richiesta la temperatura minima?
Due righe! Piu di una riga soddisfa la richiesta impostata con MIN, quindi si innesca un
conflitto cercando di combinare una normale richiesta di colonna con una funzione di gruppo.
È anche possibile utilizzare due subquery, ciascuna con una funzione di gruppo (oppure due
subquery, una con una funzione di gruppo e l’altra senza). Si supponga di voler conoscere la
temperatura massima e minima a mezzogiorno durante l’anno:
2/2/4
-----
.25
2/(2/4)
-------
4
La causa di tutto questo si chiama precedenza. La precedenza definisce l’ordine con cui
vengono eseguiti i calcoli matematici, non solo in Oracle, ma più in generale in matematica. Le
regole sono semplici: le operazioni racchiuse tra parentesi hanno la precedenza assoluta, poi
vengono considerate le moltiplicazioni e le divisioni, quindi le addizioni e le sottrazioni. Quando
si calcola un’equazione, qualsiasi calcolo impostato tra parentesi viene eseguito per primo.
Seguono le moltiplicazioni e le divisioni. Infine, vengono effettuate le addizioni e le sottrazioni.
Quando devono essere eseguite operazioni con lo stesso grado di precedenza, si segue l’ordine
da sinistra a destra. Ecco alcuni esempi:
ARGOMENTO S PAGINA
--------------- - ------
Meteo C 2
Vita moderna B 1
Bridge B 2
3 rows selected.
ARGOMENTO S PAGINA
--------------- - ------
Notizie A 1
Sport D 1
Economia E 1
Vita moderna B 1
Bridge B 2
5 rows selected.
GIOCARE CON I NUMERI 183
ARGOMENTO S PAGINA
--------------- - ------
Vita moderna B 1
Bridge B 2
2 rows selected.
9.8 Conclusioni
Le funzioni per valore singolo operano sui valori riga per riga. Con le funzioni di elenco vengono
confrontate le colonne e ne viene selezionata soltanto una, sempre riga per riga. Le funzioni per
valore singolo modificano quasi sempre il valore della colonna cui sono applicate. Ciò non
significa, naturalmente, che viene modificato il database dal quale viene tratto il valore, ma
soltanto che viene effettuato un calcolo con tale valore e il risultato è diverso dal valore originale.
Le funzioni di elenco non modificano i valori in questo modo, piuttosto selezionano (o
visualizzano) il valore maggiore o minore, rispettivamente con le funzioni GREATEST e LEAST,
di una serie di valori contenuti in una riga. Sia le funzioni per valore singolo sia quelle di elenco
non producono un risultato se incontrano un valore NULL.
Entrambe queste funzioni possono essere utilizzate in tutti i casi in cui può essere utilizzata
un’espressione, come nelle clausole select e where.
Con le funzioni di gruppo vengono visualizzate delle informazioni su un intero gruppo di
numeri, tutte le righe di un insieme. Le funzioni di questo tipo indicano la media di quei valori,
il massimo, il loro numero, o la deviazione standard e così via. Nelle funzioni di gruppo i valori
NULL vengono ignorati, e questa caratteristica dev’essere tenuta ben presente quando si impostano
delle query su gruppi di valori; diversamente, il rischio di risultati errati è elevato.
Con le funzioni di gruppo è anche possibile visualizzare informazioni sui sottogruppi che
fanno parte di una tabella, oppure creare una vista di summary delle informazioni da una o più
tabelle. Nel Capitolo 12 vengono forniti ulteriori dettagli su queste caratteristiche aggiuntive.
Infine, il grado di precedenza matematica e logica influisce sull’ordine con il quale vengono
valutate le query, e ciò può avere un effetto disastroso sui risultati delle query. È necessario
prendere l’abitudine di utilizzare le parentesi per rendere esplicito e facile da comprendere l’ordine
desiderato.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 10
Le date
U
no dei pregi di Oracle è la capacità di memorizzare e calcola-
re le date, nonché il numero di secondi, minuti, ore, giorni, mesi e anni che intercorrono tra le
date. Oltre alle funzioni di data basilari, Oracle supporta anche una vasta gamma di funzioni per
la conversione dei fusi orari. Oracle ha anche la straordinaria capacità di formattare le date
praticamente in tutti modi immaginabili, dal semplice “01.05.04” a “1 maggio nell’anno 778 dal
regno di Luigi IX”. Probabilmente molte di queste funzioni di formattazione e calcolo delle date
sono utilizzate di rado, ma quelle fondamentali si rivelano sicuramente importanti.
NOTA In molti esempi di questo capitolo si utilizzano date espresse nel formato
americano, per mostrare l’applicazione dei codici di formato di Oracle previsti per tale lingua.
I risultati effettivi ottenuti nel proprio sistema dipendono dall’impostazione del National Language
Support, il supporto per la localizzazione di Oracle in lingue diverse dall’inglese.
SYSDATE
---------
23-MAR-04
NOTA DUAL è una piccola ma utile tabella Oracle creata per verificare le funzio-
ni o per eseguire rapidi calcoli. Questa tabella verrà descritta più avanti nel capitolo, nel riqua-
dro “La tabella DUAL per brevi test e calcoli”.
Una seconda funzione, CURRENT_DATE, segnala la data di sistema con il fuso orario della
sessione (nella sessione locale è possibile impostare un fuso orario che può essere diverso da
quello del database):
CURRENT_D
---------
23-MAR-04
Un’altra funzione, SYSTIMESTAMP, segnala la data di sistema nel formato del tipo di dati
TIMESTAMP:
SYSTIMESTAMP
---------------------------------------------
23-MAR-04 04.49.31.718000 PM -05:00
Per ulteriori dettagli sul tipo di dati TIMESTAMP, le funzioni e i formati utilizzati per il
fuso orario, fare riferimento al paragrafo “Uso dei tipi di dati TIMESTAMP” più avanti nel
capitolo. I prossimi paragrafi si concentrano sull’utilizzo del tipo di dati DATE, in quanto si
tratta del tipo di dati che soddisfa la maggior parte dei requisiti di elaborazione.
DUAL è una piccolissima tabella fornita da Oracle con una sola riga e una sola colonna:
describe DUAL
Dal momento che molte funzioni Oracle funzionano sia su colonne che su letterali, con DUAL è
possibile vederne il funzionamento utilizzando soltanto letterali. In questi esempi, l’istruzione select
non si preoccupa di quali colonne sono nella tabella e una singola riga è sufficiente per illustrare
un’operazione. Per esempio, si supponga di voler calcolare velocemente POWER(4,3), ovvero 4
al cubo.
POWER(4,3)
----------
64
La colonna reale in DUAL è irrilevante. Questo significa che è possibile fare esperimenti con la
formattazione e l’aritmetica delle date utilizzando la tabella DUAL e le funzioni di data per capire
come operano. Poi, queste funzioni possono essere applicate alle date effettive nelle tabelle reali.
Quali feste non sono celebrate nella data effettiva dell’anniversario nel 2004? Si può rispon-
dere facilmente a questo quesito sottraendo la DataCelebrata dalla Dataeff. Se la risposta non è
zero, le due date sono diverse:
Aggiunta di mesi
Se il 22 febbraio è il “Fast Day” nel New Hampshire, forse sei mesi dopo si potrebbe celebrare
il “Giorno di festa” (traduzione di “Feast Day”). In tal caso, qual è la data? È sufficiente utilizzare
la funzione ADD_MONTHS, per sommare un conteggio di sei mesi, come mostrato di seguito:
Giorno di festa
---------------
22-AUG-04
Sottrazione di mesi
Se la prenotazione del posto per il picnic dev’essere effettuata almeno sei mesi prima del Columbus
Day, qual è l’ultimo giorno utile per effettuarla? Occorre considerare la DataCelebrata per il
Columbus Day e utilizzare ADD_MONTHS per aggiungere un numero negativo di sei mesi (che
equivale a sottrarre i mesi). In questo modo, si ottiene la data che precede di sei mesi il Columbus
Day. Poi occorre sottrarre un giorno.
Ultimo giorno
-------------
10.APR.04
GREATEST e LEAST
Per ciascuna delle feste spostate al lunedì, viene prima la data reale o quella di celebrazione? La
funzione LEAST seleziona la data che viene prima in un elenco di date, colonne o letterali;
GREATEST invece seleziona la data più recente. Queste funzioni sono esattamente le stesse
utilizzate con i numeri e le stringhe di caratteri:
Funzioni di data
In questo caso, LEAST funziona abbastanza bene, perché opera sulle colonne DATE di una
tabella. E i letterali?
LEAST('20
---------
20-DEC-04
Questo risultato è errato, un po’ come se al posto di LEAST si fosse detto GREATEST. Il 20
dicembre 2004 non cade prima del 20 gennaio 2004. Perché si è arrivati a questo risultato?
Perché la funzione LEAST ha considerato questi letterali come stringhe.
Non sapeva di doverli considerare come date. Occorre quindi utilizzare la funzione TO_DATE
per convertire questi letterali in un formato interno DATE che Oracle possa utilizzare per le
funzioni orientate alle date:
LEAST(TO_
---------
20-JAN-04
NEXT_DAY
NEXT_DAY calcola la data del prossimo giorno della settimana (ossia, domenica, lunedì, marte-
dì, mercoledì, giovedì, venerdì o sabato) successivo alla data specificata. Per esempio, si sup-
LE DATE 191
A differenza della maggior parte delle funzioni e degli operatori logici di Oracle, GREATEST e
LEAST non considerano come date le stringhe di caratteri eventualmente corrispondenti a
tale formato. Le date sono trattate come stringhe:
FESTA DATACELEBRATA
--------------------- -------------
LABOR DAY 02-SEP-02
Per fare in modo che LEAST e GREATEST funzionino correttamente, alle stringhe letterali deve
essere applicata la funzione TO_DATE:
ponga che il giorno di paga sia sempre il primo venerdì dopo il 15 del mese. La tabella
GIORNOPAGA contiene solo le date del periodo di paga, ovvero il 15 del mese, con una riga per
ogni mese dell’anno:
DATACICLO
---------
15-JAN-04
15-FEB-04
15-MAR-04
15-APR-04
15-MAY-04
15-JUN-04
15-JUL-04
15-AUG-04
15-SEP-04
15-OCT-04
15-NOV-04
15-DEC-04
Giorno Paga
---------
16-JAN-04
20-FEB-04
19-MAR-04
16-APR-04
21-MAY-04
18-JUN-04
16-JUL-04
20-AUG-04
17-SEP-04
22-OCT-04
19-NOV-04
17-DEC-04
Questo risultato è quasi corretto, tranne per il mese di ottobre, perché NEXT_DAY è la data
del venerdì successivo alla data del periodo di paga. Dato che il 15 ottobre 2004 è un venerdì,
questa query fornisce erroneamente il venerdì successivo. La versione corretta è questa:
NEXT_DAY è veramente una funzione del tipo “maggiore di”. Richiede la data maggiore di
quella indicata che cade in un giorno specifico della settimana. Per tenere conto anche delle date
che cadono già di venerdì, occorre sottrarre 1 dalla data del periodo di paga. In questo modo,
ogni data del periodo di paga compare un giorno prima di NEXT_DAY. Quindi, i giorni di paga
sono sempre i venerdì giusti.
LAST_DAY
Questa funzione restituisce la data dell’ultimo giorno del mese. Si supponga che le commissioni
e i premi vengano pagati sempre l’ultimo giorno del mese. Quali sono queste date nel 2004?
Fine mese
---------
31-JAN-04
29-FEB-04
31-MAR-04
30-APR-04
31-MAY-04
30-JUN-04
31-JUL-04
31-AUG-04
30-SEP-04
31-OCT-04
30-NOV-04
31-DEC-04
LE DATE 193
Per calcolare l’età di ogni persona, occorre calcolare i mesi trascorsi tra la data odierna e le
date di nascita, quindi dividere per 12, per ottenere gli anni: la divisione visualizzerà l’età con un
componente decimale. Dato che la maggior parte delle persone sopra i sette anni non indica la
propria età utilizzando porzioni di anni, si applica la funzione FLOOR al calcolo.
OGGI REVISIONE
--------- ---------
23-MAR-04 01-OCT-04
ADD_MONTHS considera SysDate e vi somma sei mesi. LAST_DAY considera questo risul-
tato e calcola l’ultimo giorno di quel mese. Poi occorre sommare 1 alla data per ottenere il primo
giorno del mese successivo. Quanti giorni mancano a quella revisione? È sufficiente sottrarre da
194 CAPITOLO 10
questa data (revisione) la data odierna. Si osservi l’uso delle parentesi per assicurare l’ordine
corretto di calcolo:
ATTESA
-------
192
SYSDATE
---------
23-MAR-04
All’inizio del capitolo si è osservato che Oracle può sottrarre una data dall’altra, per esem-
pio domani meno oggi, e produrre una risposta che non è un numero intero. È opportuno esami-
nare questa situazione:
TO_DATE('24-MAR-04')-SYSDATE
----------------------------
.516
La ragione del numero frazionario di giorni tra oggi e domani è che nelle informazioni di
data Oracle mantiene le ore, i minuti e i secondi e SysDate è sempre attuale, aggiornata al secon-
do. Ovviamente, a domani manca meno di un giorno intero.
Per semplificare alcune delle difficoltà che si possono incontrare nell’utilizzo di frazioni di
giorni, Oracle fa alcune ipotesi riguardo le date.
■ A una data inserita come letterale, per esempio ‘24-MAR-04’, viene assegnata come ora
predefinita 12 A.M. (mezzanotte), l’inizio della giornata.
■ Una data inserita attraverso SQL*Plus, a meno che l’ora non sia assegnata specificamente, è
impostata a 12 A.M. (mezzanotte) l’inizio della giornata.
■ SysDate include sempre sia la data che l’ora, a meno che non venga esplicitamente arroton-
data. L’uso della funzione ROUND imposta qualsiasi data alle 12 A.M. di quel giorno, se l’ora è
prima di mezzogiorno, e a 12 A.M. del giorno successivo se è dopo mezzogiorno. La funzione
TRUNC opera in modo simile, solo che imposta l’ora a 12 A.M. fino a un secondo prima della
mezzanotte.
Per ottenere il numero arrotondato di giorni tra oggi e domani, si può utilizzare quanto
segue:
TO_DATE('25-MAR-04')-ROUND(SYSDATE)
-----------------------------------
1
LE DATE 195
TO_CHAR(data[,'formato'[,'NLSparametri']])
TO_DATE(stringa[,'formato'[,'NLSparametri']])
data dev’essere una colonna definita in Oracle come tipo DATE: non può essere una stringa,
neppure se è nel formato data predefinito (GG-MMM-AA). L’unico modo di utilizzare una stringa
al posto di data nella funzione TO_CHAR è quello di includerla in una funzione TO_DATE.
stringa è una stringa letterale, un numero vero e proprio o una colonna di un database che
contiene una stringa o un numero. In tutti i casi, tranne uno, il formato di stringa deve corrispon-
dere a quello descritto da formato. Solo se una stringa è nel formato predefinito, formato può
essere tralasciato. Il valore predefinito è DD-MON-YY, ma può essere cambiato con:
Per illustrare un esempio del funzionamento delle opzioni viene utilizzata TO_CHAR. La
prima cosa da fare è definire un formato di colonna per i risultati della funzione TO_CHAR;
infatti, senza di esso, TO_CHAR produce una colonna in SQL*Plus della grandezza di circa 100
caratteri. Rinominando la colonna (per rendere più leggibile la sua intestazione) e impostando il
formato a 30 caratteri si ottiene una visualizzazione pratica:
from COMPLEANNO
where Nome = 'VICTORIA';
DATANASCITA FORMATTATO
----------- ------------------------------
20-MAY-49 05/20/49
DataNascita mostra il formato di data predefinito in Oracle: DD-MON-YY (giorno del mese,
trattino, tre lettere di abbreviazione per il mese, trattino, ultime due cifre dell’anno). La funzione
TO_CHAR nell’istruzione select è abbastanza chiara. MM, DD e YY nell’istruzione TO_CHAR
sono simboli chiave per Oracle da seguire nella formattazione della data. Le barre (/) sono sol-
tanto segni di interpunzione, e Oracle ne accetta molti altri.
DATANASCITA FORMATTATO
----------- ------------------------------
20-MAY-49 4905>20
Oltre alla punteggiatura standard, Oracle consente anche di inserire del testo nel formato. Si
può ottenere questo risultato racchiudendo il testo desiderato tra virgolette doppie:
DATANASCITA FORMATTATO
----------- ------------------------------
12-MAY-46 May , 12TH in, um, 1946
23-AUG-37 August , 23RD in, um, 1937
02-FEB-47 February , 02ND in, um, 1947
20-MAY-49 May , 20TH in, um, 1949
11-NOV-42 November , 11TH in, um, 1942
È interessante osservare alcune conseguenze del formato. La parola intera “Month” comuni-
ca a Oracle di utilizzare nella visualizzazione il nome intero del mese. Dato che è stata specifica-
ta con la prima lettera maiuscola e le altre minuscole, ogni mese nel risultato viene formattato
allo stesso modo. Le opzioni per il mese sono le seguenti:
Formato Risultato
Month August
Month August
Mon Aug
Mon Aug
Il giorno del mese viene ottenuto con DD in formato. Un suffisso th aggiunto a DD comuni-
ca a Oracle di utilizzare i suffissi ordinali inglesi, come “TH”, “RD” e “ND” insieme al numero.
In questo caso, anche i suffissi possono essere in maiuscolo o minuscolo, ma questo dipende da
DD e non da th:
Formato Risultato
DDth o DDTH 11TH
Ddth o DdTH 11Th
Ddth o ddTH 11th
LE DATE 197
I seguenti formati di date vengono utilizzati sia con TO_CHAR che con TO_DATE.
I formati di data seguenti funzionano solo con TO_CHAR. Non funzionano con TO_DATE.
*ISO è l’International Standards Organization, che ha un set di standard per le date diverso dai
formati degli Stati Uniti.
Questo stesso approccio vale per tutti i numeri in formato, compreso il secolo, l’anno, il
trimestre, il mese, la settimana, il giorno del mese (DD), il giorno giuliano, le ore, i minuti e i
secondi.
LE DATE 199
Le parole tra virgolette vengono semplicemente inserite dove si trovano. Gli spazi tra qual-
siasi di queste richieste di formato sono riprodotti anche nel risultato (si osservino i tre spazi
nell’esempio precedente prima della parola “in”). YyyY è stato inserito semplicemente per di-
mostrare che non c’è distinzione tra maiuscole e minuscole, a meno che non venga utilizzato un
suffisso come Th. Per semplicità, si consideri questa richiesta di formattazione:
DATANASCITA FORMATTATO
----------- ------------------------------
12-MAY-46 May , 12th, 1946
23-AUG-37 August , 23rd, 1937
02-FEB-47 February , 02nd, 1947
20-MAY-49 May , 20th, 1949
11-NOV-42 November , 11th, 1942
Si tratta di un formato abbastanza normale. I giorni sono tutti allineati, per cui è facile
confrontare le righe. Questo è l’allineamento predefinito, e Oracle lo realizza aggiungendo alla
destra dei nomi dei mesi degli spazi fino a raggiungere la larghezza di nove. Ci sono casi dove è
più importante che una data sia formattata normalmente, per esempio all’inizio di una lettera.
Nell’esempio, gli spazi tra mese e virgola sembrerebbero strani. Per eliminarli, si utilizza fm
come prefisso per le parole month o day:
Formato Risultato
Month, ddth August, 20th
fmMonth, ddth August, 20th
Day, ddth Monday, 20th
fmDay, ddth Monday, 20th
Si consideri l’ esempio seguente:
Combinando tutti questi controlli di formato e aggiungendo le ore e i minuti, si può produrre
un certificato di nascita:
Dopo aver visto questo risultato, si supponga di voler visualizzare la data in lettere. A tal
fine occorre utilizzare il controllo sp:
Ma erano le 3.27 del mattino o del pomeriggio? Questa informazione potrebbe essere ag-
giunta tra virgolette, ma in questo modo il risultato riporterebbe sempre “del mattino” o “del
pomeriggio”, indipendentemente dall’ora effettiva del giorno (dal momento che le virgolette
racchiudono un letterale). Al contrario, Oracle consente di aggiungere “del mattino” o “del po-
meriggio” dopo l’ora, ma non tra virgolette. Quindi, Oracle la interpreta come una richiesta di
visualizzazione di questi codici. Nell’esempio seguente si può notare come questo controllo di
formattazione sia stato inserito in select come P.M., ma il risultato mostra A.M., perché la nasci-
ta si è verificata al mattino:
Un elenco di tutte le possibili opzioni di data è riportato nel riquadro “Formati delle date”,
più avanti nel capitolo. Come si fa a creare un formato di data per l’anno 778 dal regno di Luigi
IX? Occorre utilizzare l’aritmetica delle date per alterare l’anno da A.D. a A.L. (il regno di Luigi
IX è iniziato nel 1226, perciò si deve sottrarre 1226 dall’anno corrente) e infine formattare
semplicemente il risultato utilizzando TO_CHAR.
LE DATE 201
ORA
--------
05.11.48
Questo esempio è corretto, dal momento che utilizza MI per mostrare i minuti. Tuttavia, gli
utenti selezionano spesso MM, forse perché stanno impiegando altre due coppie di lettere dop-
pie, HH e SS. Se si seleziona MM, viene restituito il mese, non i minuti:
OraErrato
---------
05.03.48
In questo caso, l’ora non è corretta, perché al posto dei minuti è stato selezionato il mese.
Anche se Oracle è flessibile e supporta molti formati differenti per le date, non può evitare che
gli utenti commettano questo errore.
NEW_TIME(data,'questo','quello')
data è la data (e l’ora) nel fuso orario questo; questo dev’essere sostituito da un’abbreviazio-
ne di tre lettere per il fuso orario corrente, mentre quello dev’essere sostituito da un’abbreviazio-
ne di tre lettere per il fuso orario di cui si vuole conoscere la data e l’ora. Le opzioni per i fusi
orari sono fornite nel paragrafo “Funzioni di data”, riportato in precedenza in questo capitolo.
Per confrontare la data della nascita di Victoria tra l’ora standard dell’Est e quella delle Hawaii,
senza mostrare l’ora, occorre utilizzare l’istruzione seguente:
DATANASCITA NEW_TIME(
----------- ---------
20-MAY-49 19-MAY-49
Come è possibile che Victoria sia nata in due giorni diversi? Dato che ogni data in Oracle
contiene anche l’ora, è sufficiente utilizzare TO_CHAR e NEW_TIME per scoprire le differenze
di data e di ora tra i due fusi orari. Quanto segue risponde alla domanda:
202 CAPITOLO 10
NATA NATA
------------------------------ ------------------------------
May 20th, 1949 alle 3.27 AM May 19th, 1949 alle 10.27 PM
Calcoli di TO_DATE
TO_DATE segue le stesse convenzioni di formattazione di TO_CHAR, con alcune restrizioni. Lo
scopo di questa funzione è convertire una stringa letterale, come MAY 20, 1949, in un formato di
data di Oracle. In questo modo, la data potrà essere impiegata nei calcoli con le date.
Ecco la sintassi di TO_DATE:
TO_DATE(stringa[,'formato'])
TO_DATE('
---------
22-MAR-04
Occorre osservare, però, che il formato 22-MAR-04 è già quello predefinito in cui Oracle
visualizza e accetta le date. Quando una stringa letterale ha una data in questo formato, formato
in TO_DATE può essere tralasciato, ottenendo esattamente lo stesso risultato:
TO_DATE('
---------
22-MAR-04
Quando il formato (formato) corrisponde alla stringa letterale (stringa), questa viene con-
vertita in data e visualizzata nel formato di data predefinito:
TO_DATE('
---------
22-MAR-04
Si supponga che sia necessario conoscere il giorno della settimana del 22 marzo. La funzio-
ne TO_CHAR non funziona, anche con la stringa letterale nel formato appropriato, perché richie-
de una data (si veda la sintassi all’inizio del paragrafo “Formattazione di TO_DATE e
TO_CHAR”):
ERROR at line 1:
ORA-01722: invalid number
TO_CHAR(T
---------
Monday
TO_DATE può accettare anche dei numeri, senza gli apici, invece di stringhe, purché siano
formattati in modo coerente. Ecco un esempio:
TO_DATE(1
---------
05-NOV-46
I segni di interpunzione in formato vengono ignorati, ma il numero deve seguire l’ordine dei
controlli di formato. Il numero stesso non deve contenere segni di interpunzione.
Quanto può essere complesso il controllo di formato in TO_DATE? Si supponga di aver
semplicemente invertito l’istruzione select con TO_CHAR mostrata in precedenza, mettendo il
risultato in una parte stringa di TO_DATE e mantenendo lo stesso formato di TO_CHAR.
Si è verificato un errore. Come si è visto, può essere utilizzato solo un numero limitato di
controlli di formato. Ecco quindi le restrizioni sul formato che controlla TO_DATE:
204 CAPITOLO 10
Le date possono essere impiegate anche con altri operatori logici di Oracle, fermi restando
alcuni avvertimenti e restrizioni. L’operatore BETWEEN applica l’aritmetica delle date se la
colonna che lo precede è una data, anche se le date di confronto sono stringhe letterali:
FESTA DATACELEBRATA
------------------------- -------------
NEW YEARS DAY 01-JAN-04
MARTIN LUTHER KING, JR. 19-JAN-04
LINCOLNS BIRTHDAY 16-FEB-04
WASHINGTONS BIRTHDAY 16-FEB-04
FAST DAY, NEW HAMPSHIRE 22-FEB-04
FESTA DATACELEBRATA
------------------------- -------------
NEW YEAR DAY 01-JAN-04
FAST DAY, NEW HAMPSHIRE 22-FEB-04
LE DATE 205
Se non si è sicuri che il 2000 sia il secolo predefinito, si può utilizzare la funzione TO_DATE
per specificare i valori del secolo per le date nell’operatore IN:
FESTA DATACELEBRATA
------------------------- -------------
NEW YEAR DAY 01-JAN-04
FAST DAY, NEW HAMPSHIRE 22-FEB-04
LEAST e GREATEST non funzionano, perché presuppongono che le stringhe letterali siano
stringhe, non date. Per una spiegazione esauriente di LEAST e GREATEST, fare riferimento al
riquadro “Un avvertimento su GREATEST e LEAST” più indietro nel capitolo.
Nell’esempio precedente non è specificato alcun valore per il secolo nella colonna Datanascita
e nessuna età. Se si utilizza la funzione TO_CHAR nella colonna Datanascita, si può vedere la
data di nascita completa inserita da Oracle, impostata per default al secolo corrente:
NATA
-----------
21-NOV-2039
Per le date che possono essere impostate correttamente per default al secolo corrente, l’uso
del valore predefinito non rappresenta un problema. Il valore della Datanascita di Alicia è il 21-
NOV-2039, una data errata di ben 100 anni! Ogni volta che si inseriscono i valori delle date,
sarebbe opportuno specificare il valore completo dell’anno con quattro cifre.
206 CAPITOLO 10
EXTRACT
( { { YEAR
| MONTH
| DAY
| HOUR
| MINUTE
| SECOND
}
| { TIMEZONE_HOUR
| TIMEZONE_MINUTE
}
| { TIMEZONE_REGION
| TIMEZONE_ABBR
}
}
FROM { dataora_valore_espressione | intervallo_valore_espressione }
)
Per esempio, se si desiderasse estrarre il mese in cui è nata Victoria, si potrebbe eseguire la
query seguente:
select Datanascita,
EXTRACT(Mese from COMPLEANNO) Mese
from COMPLEANNO
where Nome = 'VICTORIA';
DATANASCITA MESE
----------- ---------
20-MAY-49 5
Per operazioni di estrazioni più complesse, si dovrà utilizzare TO_CHAR, tuttavia EXTRACT
è in grado di supportare molte query comuni relative a valori di date.
create table X1
(tscol TIMESTAMP(5));
TSCOL
---------------------------------
23-MAR-04 05.27.32.71800 PM
L’output mostra il secondo in cui è stata inserita la riga, addirittura fino a cinque posizioni
dopo il valore decimale. La funzione SYSTIMESTAMP restituisce i dati sotto forma di
TIMESTAMP (precisione_alla_frazione_di_secondo) con il tipo di dati WITH TIME ZONE.
La stessa identica riga, inserita in una colonna definita con il tipo di dati TIMESTAMP(5) WITH
TIME ZONE, restituisce i dati nel formato seguente:
create table X2
(tscol TIMESTAMP(5) WITH TIME ZONE);
TSCOL
----------------------------------
23-MAR-04 05.29.11.64000 PM –05:00
In questo output, il fuso orario viene visualizzato come una differenza di Coordinated
Universal Time (UTC).
Attualmente, il database è impostato a un fuso orario che è cinque ore avanti rispetto al
valore di UTC.
Oracle supporta anche un tipo di dati TIMESTAMP (precisione_alla_frazione_di_secondo)
WITH LOCAL TIME ZONE, simile a TIMESTAMP WITH TIME ZONE. L’unica differenza è
che i dati vengono normalizzati con il fuso orario del database quando sono memorizzati nel
database, quindi durante le operazioni di recupero gli utenti visualizzano i dati nel fuso orario di
sessione.
Oltre ai tipi di dati TIMESTAMP, Oracle supporta anche due tipi di dati di intervallo:
INTERVAL YEAR (precisione_all’anno) TO MONTH e INTERVAL DAY (precisione_al_gior-
no) TO SECOND (precisione_alla_frazione_di_secondo). INTERVAL YEAR TO MONTH
memorizza un lasso di tempo espresso in anni e mesi, dove la precisione è il numero di cifre
contenute nel campo YEAR (compreso tra 0 a 9; il valore predefinito è di 2 cifre). Il tipo di dati
INTERVAL DAY TO SECOND memorizza un lasso di tempo espresso in giorni, ore, minuti e
secondi; la precisione per i valori del giorno e dei secondi accetta numeri compresi tra 0 e 9. I tipi
di dati INTERVAL vengono utilizzati principalmente nelle analisi statistiche e nelle procedure
di data mining.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 11
Funzioni di conversione
e trasformazione
I
n questo capitolo vengono esaminate le funzioni che converto-
no un tipo di dati in un altro. Finora sono stati trattati esaurientemente quattro tipi di dati princi-
pali e le loro funzioni associate:
■ CHAR (stringhe di caratteri a lunghezza fissa) e VARCHAR2 (stringhe di caratteri a lun-
ghezza variabile) includono qualsiasi lettera dell’alfabeto, qualsiasi numero o qualsiasi simbolo
sulla tastiera. I letterali carattere devono essere racchiusi tra apici:
‘Salute a tutti!’.
-246.320
■ DATE è un tipo speciale che include informazioni sulla data, l’ora e il fuso orario. Ha un
formato predefinito, DD-MON-YY, ma può essere visualizzato in molti modi utilizzando la
funzione TO_CHAR, come si è mostrato nel Capitolo 10. I letterali DATE devono essere racchiu-
si fra apici:
‘26-AUG-81’.
Ognuno di questi tipi di dati ha un gruppo di funzioni progettate appositamente per la loro
manipolazione, come si è visto nei Capitoli 7, 8, 9 e 10. Le funzioni di stringa sono utilizzate con
colonne o letterali di caratteri, mentre le funzioni aritmetiche con colonne o letterali NUMBER,
infine le funzioni di data con colonne o letterali DATE. La maggior parte delle funzioni di grup-
po e miste opera con qualsiasi tipo di dati. Alcune di queste funzioni modificano l’oggetto su cui
agiscono (CHAR, VARCHAR2, NUMBER o DATE), mentre altre riportano informazioni sul-
l’oggetto.
In un certo senso, molte delle funzioni esaminate finora sono funzioni di trasformazione,
ossia modificano gli oggetti. Tuttavia, quelle trattate in questo capitolo cambiano gli oggetti in
modo inusuale: li trasformano da un tipo di dati a un altro o effettuano una profonda trasforma-
zione dei dati. La Tabella 11.1 descrive queste funzioni.
210 CAPITOLO 11
CAST Effettua una conversione CAST di un tipo incorporato o collection in un altro; è utilizzata comunemente
con tabelle annidate e array variabili.
CHARTOROWID Modifica una stringa di caratteri in modo che funzioni come un identificatore di riga interno di Oracle o
RowID.
COMPOSE Traduce una stringa in qualunque tipo di dato in una stringa UNICODE nella sua forma completamente
normalizzata utilizzando il medesimo set di caratteri della stringa di input.
CONVERT Converte una stringa di caratteri dal set di caratteri di una lingua in un altro.
DECODE Decodifica una stringa di caratteri CHAR o VARCHAR2 o un numero (NUMBER) in una serie di vari
numeri, in base a un valore. Si tratta di una funzione di tipo if, then, else molto potente. A essa è dedicato
il Capitolo 17.
DECOMPOSE Traduce una stringa in qualunque tipo di dato in una stringa UNICODE dopo la sua scomposizione canonica
utilizzando il medesimo set di caratteri della stringa di input.
RAWTOHEX Modifica una stringa di numeri binari in una stringa di caratteri di numeri esadecimali.
ROWIDTOCHAR Modifica un identificatore di riga interno di Oracle, o RowID, in una stringa di caratteri.
TO_CLOB Converte i valori NCLOB in una colonna LOB o in altre stringhe di caratteri in valori CLOB.
TO_DATE Converte un elemento di tipo NUMBER, CHAR o VARCHAR2 in un elemento di tipo DATE (un tipo di dato
di Oracle).
TO_DSINTERVAL Converte una stringa di tipo di dati CHAR, VARCHAR2, NCHAR o NVARCHAR2 in un tipo INTERVAL DAY
TO SECOND.
TO_LOB Converte un valore LONG in un LOB come parte di un’istruzione insert as select.
TO_MULTI_BYTE Converte i caratteri a singolo byte di una stringa di caratteri in caratteri di più byte.
TO_NCHAR Converte una stringa di caratteri, i numeri o le date dal set di caratteri del database in quello della lingua
nazionale.
TO_NCLOB Converte i valori CLOB in una colonna LOB o in altre stringhe di caratteri in valori NCLOB.
(segue)
FUNZIONI DI CONVERSIONE E TRASFORMAZIONE 211
TO_YMINTERVAL Converte una stringa di tipo di dati CHAR, VARCHAR2, NCHAR o NVARCHAR2 in un tipo INTERVAL
YEAR TO MONTH .
UNISTR Converte una stringa in Unicode nel set di caratteri Unicode del database.
select SUBTR(TO_CHAR(948033515),1,5)||'-'||
SUBTR(TO_CHAR(948033515),6) AS Cap
from DUAL;
CAP
---------------------------------------------
94803-3515
In questo caso, la funzione TO_CHAR trasforma il numero puro 948033515 (si noti che non
è racchiuso tra apici, come se si trattasse di una stringa CHAR o VARCHAR2) in una stringa di
caratteri. Successivamente, SUBSTR taglia le posizioni dalla 1 alla 5 di questa stringa, produ-
cendo 94803. All’estremità destra della stringa viene concatenato un trattino, quindi un’ altra
funzione TO_CHAR crea un’altra stringa, che un’altra SUBSTR taglia dalla posizione 6 fino alla
fine. La seconda stringa, 3515, viene concatenata dopo il trattino. L’intera stringa ricostruita
viene etichettata come “CAP”, e Oracle la visualizza: 94803-3515. La funzione TO_CHAR con-
sente di utilizzare le funzioni di manipolazione delle stringhe su numeri (e date) come se fossero
effettivamente stringhe. Comodo? Certamente. Tuttavia, si consideri quanto segue:
212 CAPITOLO 11
select SUBTR(948033515,1,5)||'-'||
SUBTR(948033515,6) AS Cap
from DUAL;
CAP
---------------------------------------------
94803-3515
describe INDIRIZZO
Ora viene selezionato solo il codice di avviamento postale per tutte le Mary nella tabella:
select SUBSTR(Cap,1,5)||'-'||
SUBSTR(Cap,6) AS Cap
from INDIRIZZO
where Nome = ‘MARY';
CAP
-----------------------------------------
94941-4302
60126-2460
SUBSTR funziona proprio come con le stringhe, anche se il codice di avviamento postale è
una colonna di tipo NUMBER della tabella INDIRIZZO. Funzionano anche le altre funzioni di
stringa?
CAP RTRIM(CAP,20)
---------- ----------------------------------------
949414302 9494143
601262460 60126246
RTRIM(stringa [,'set'])
Il set di caratteri da rimuovere dalla stringa è racchiuso fra apici, ma in questo esempio non ci
sono apici:
RTRIM(Cap,20)
INITCAP(LOWER(SYSDATE))
-----------------------
22-Mar-04
Si noti che la funzione INITCAP rende maiuscola la prima lettera di “mar” anche se si trova
in mezzo alla stringa “22-mar-04”. Questa è una caratteristica di INITCAP che non è limitata alle
date, anche se viene illustrata qui per la prima volta. Si osservi l’esempio seguente:
214 CAPITOLO 11
select INITCAP(‘ecco-un_bel.test,di:punteggiatura;per+initcap')
from DUAL;
INITCAP(‘ECCO-UN_BEL.TEST,DI:PUNTEGGIATURA;PE
---------------------------------------------
Ecco-Un_Bel.Test,Di:Punteggiatura;Per+Initcap
INITCAP rende maiuscola la prima lettera di ogni parola. Infatti, stabilisce l’inizio di una
parola basandosi sul fatto che sia preceduta da qualsiasi carattere diverso da una lettera. Si pos-
sono anche tagliare e incollare le date, proprio come se fossero stringhe, utilizzando funzioni di
stringa:
SUB
---
MAR
In questo caso, un valore DATE viene riempito a sinistra con dei 9 in modo da ottenere una
lunghezza totale di 20:
LPAD(SYSDATE,20,'9')
--------------------
9999999999922-MAR-04
LPAD, o qualunque altra funzione di stringa, può essere impiegata anche su NUMBER,
letterali (come in questo esempio) o colonne:
LPAD(9,20,0)
--------------------
00000000000000000009
Questi esempi mostrano che le funzioni di stringa trattano i valori NUMBER e DATE come
se fossero stringhe di caratteri. Il risultato della funzione (quello che viene visualizzato) è esso
stesso una stringa di caratteri. Nel prossimo esempio, una stringa (si notino gli apici) viene
trattata come un NUMBER dalla funzione numerica FLOOR:
FLOOR(‘-323.78')
----------------
-324
Nell’esempio seguente, due stringhe di caratteri letterali sono convertite in DATE per la
funzione di data MONTHS_BETWEEN. Essa funziona solo perché le stringhe letterali sono espres-
se nel formato di data predefinito, DD-MON-YY:
FUNZIONI DI CONVERSIONE E TRASFORMAZIONE 215
MONTHS_BETWEEN('16-MAY-02','01-NOV-02')
---------------------------------------
-5.516129
Una delle linee guida afferma che un DATE non viene convertito in un NUMBER. Ma di
seguito viene proposto un esempio di addizione e sottrazione con una data. Viene violata la
direttiva?
La risposta è no, perché l’addizione e la sottrazione sono operazioni di aritmetica delle date,
non di aritmetica normale. L’aritmetica delle date (trattata nel Capitolo 10) funziona solo con
l’addizione e la sottrazione e solo con valori DATE. La maggior parte delle funzioni converte
automaticamente una stringa di caratteri espressa nel formato di data predefinito in un DATE.
Un’eccezione è questo tentativo di sommare una data con un letterale:
L’aritmetica delle date, anche con tipi di dati DATE reali, funziona solo con l’addizione e la
sottrazione. Qualsiasi altra funzione aritmetica applicata a una data fallisce. Le date non vengo-
no convertite in numeri, come illustra questo tentativo di dividere per 2 una data:
Per utilizzare un NUMBER in una funzione di data, occorre applicare la funzione TO_DATE.
punto interrompersi, producendo un messaggio di errore e causando una perdita di tempo per
cercare di trovare il problema. Inoltre, un’altra persona che leggesse l’istruzione select potrebbe
rimanere confusa da funzioni che sembrano inappropriate per operare su caratteri o numeri.
L’uso di TO_NUMBER evidenzia il fatto che un valore numerico è sempre previsto anche se la
colonna utilizza il tipo di dati VARCHAR2.
Una semplice regola pratica potrebbe essere quella di utilizzare funzioni in cui il rischio è
ridotto, come funzioni di manipolazioni di stringhe su numeri, invece di funzioni aritmetiche su
stringhe. A vantaggio proprio e degli altri utenti, è opportuno porre sempre una nota accanto
all’istruzione select per segnalare l’utilizzo della conversione automatica di tipo.
NOTA La funzione CAST viene utilizzata con le tabelle annidate e con gli array
variabili; fare riferimento al Capitolo 34 per maggiori dettagli. La funzione DECODE verrà
trattata nel Capitolo 16.
BIN_TO_NUM(1,1,0,1)
-------------------
13
BIN_TO_NUM(1,1,1,0)
-------------------
14
TRANSLATE
TRANSLATE è una semplice funzione che effettua una sostituzione ordinata carattere per carat-
tere in una stringa. Ecco la sintassi di TRANSLATE:
TRANSLATE(stringa,if,then)
TRANSLATE esamina ogni carattere in stringa, quindi controlla if per vedere se il carattere
è presente nella stringa. Se lo trova, annota la posizione del carattere in if e poi esamina la stessa
posizione in then. TRANSLATE sostituisce il carattere in stringa con quello in then. Normalmen-
te, la funzione viene scritta su un’unica linea, come mostrato di seguito:
select TRANSLATE(7671234,234567890,'BCDEFGHIJ')
from DUAL;
TRANSLA
-------
GFG1BCD
Tuttavia può essere più facile da capire se viene suddivisa in due linee (per SQL*Plus non fa
differenza, naturalmente):
select TRANSLATE(7671234,234567890,
‘BCDEFGHIJ')
from DUAL;
TRANSLA
-------
GFG1BCD
select TRANSLATE(‘HAL','ABCDEFGHIJKLMNOPQRSTUVWXYZ',
‘BCDEFGHIJKLMNOPQRSTUVWXYZA') AS Chi
from DUAL;
218 CAPITOLO 11
CHI
---
IBM
Si rimanda all’analisi della funzione REGEXP_REPLACE nel Capitolo 8 per maggiori det-
tagli sulla manipolazione di stringhe possibile con le espressioni regolari in Oracle Database
10g.
DECODE
Se TRANSLATE è una sostituzione carattere per carattere, DECODE può essere considerata una
sostituzione valore per valore. Per ogni valore in un campo, DECODE cerca una corrispondenza
in una serie di test if-then. DECODE è una funzione incredibilmente potente, con un’ampia
gamma di aree in cui può essere utile. Il Capitolo 16 è interamente dedicato alla trattazione
dell’utilizzo avanzato di DECODE e CASE.
Ecco la sintassi di questa funzione:
DECODE( valore ,if1 , then1 ,if2 ,then2 ,if3 ,then3 ,... . . , else )
Qui sono illustrate soltanto tre combinazioni if-then, ma in realtà non vi è alcun limite per
esse. Per vedere come opera questa funzione, viene ripresa la tabella GIORNALE introdotta nei
primi capitoli:
ARGOMENTO S PAGINA
--------------- - ----------
Notizie A 1
Sport D 1
Editoriali A 12
Economia E 1
Meteo C 2
Televisione B 7
Nascite F 7
Annunci F 8
Vita moderna B 1
Fumetti C 4
Film B 4
Bridge B 2
Necrologi F 6
Salute F 6
ARGOMENTO S DECODE(PAGINA,'1','PRIMAPAGINA',”PAGINA”||PAGINA)
--------------- - ----------------------------------------
Notizie A Prima pagina
Sport D Prima pagina
Editoriali A Pagina 12
Economia E Prima pagina
Meteo C Pagina 2
Televisione B Pagina 7
Nascite F Pagina 7
Annunci F Pagina 8
Vita moderna B Prima pagina
Fumetti C Pagina 4
Film B Pagina 4
Bridge B Pagina 2
Necrologi F Pagina 6
Salute F Pagina 6
Esistono alcune restrizioni per i tipi di dati che possono essere presenti nell’elenco di clau-
sole if e then; se ne occuperà il Capitolo 16.
11.4 Conclusioni
La maggior parte delle funzioni in Oracle, anche se è designata per un particolare tipo di dati,
come CHAR, VARCHAR2, NUMBER o DATE, in realtà funziona anche con gli altri tipi di dati.
Ciò è possibile tramite una conversione automatica di tipo. A parte alcune logiche eccezioni e
con la speranza di compatibilità future, questo è possibile finché i dati da convertire appaiono
“simili” a quelli in cui devono essere convertiti.
Le funzioni di carattere convertono qualsiasi NUMBER o DATE. Le funzioni numeriche
convertono un CHAR o un VARCHAR2, se contiene le cifre da 0 a 9, un punto decimale o un
segno meno (–) a sinistra. Tuttavia, le funzioni numeriche non convertono i valori DATE. Le
funzioni per date convertono le stringhe di caratteri se sono nel formato DD-MON-YY, ma non
convertono i numeri.
Esistono infine due funzioni, TRANSLATE e DECODE, che cambiano radicalmente i dati su
cui agiscono. TRANSLATE effettua una sostituzione di caratteri in base a qualsiasi configurazio-
ne specificata, mentre DECODE esegue una sostituzione di valori per qualsiasi configurazione
specificata.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 12
Raggruppamenti
F
inora si è visto come SQL permetta di selezionare (select)
righe di informazioni dalle tabelle del database, come le clausole where possano limitare il
numero di righe restituite in modo da ottenere solo quelle che soddisfano alcune regole e come
le righe restituite possano essere disposte in ordine crescente o decrescente utilizzando order by.
Inoltre, si è visto anche come le funzioni per dati NUMBER, DATE e caratteri possano conver-
tire i valori nelle colonne e come le funzioni di gruppo possano fornire informazioni sull’intera
serie di righe.
Oltre alle funzioni di gruppo analizzate, esistono anche due clausole di gruppo: having e
group by. Queste sono parallele alle clausole where e order by, con la differenza che operano su
gruppi e non su singole righe. Queste clausole possono effettuare analisi molto profonde nei dati.
NOMECATEGORIA COUNT(*)
-------------------- ----------
NARRAADULTI 6
SAGGIAADULTI 10
CONSADULTI 6
NARRRAGAZZI 5
SAGGIRAGAZZI 1
ILLUSRAGAZZI 3
Questo avviene perché le funzioni di gruppo, come SUM e COUNT, sono progettate per
fornire informazioni su un gruppo di righe, non sulle singole righe di una tabella. L’errore viene
evitato utilizzando NomeCategoria nella clausola group by, che induce la funzione COUNT a
contare tutte le righe raggruppate per ogni NomeCategoria.
La clausola having funziona in modo molto simile a where, ma la sua logica è riferita soltan-
to ai risultati di funzioni di gruppo, invece che a colonne o espressioni per singole righe, le quali
possono ancora essere selezionate dalla clausola where. Di seguito, le righe dell’esempio prece-
dente vengono ulteriormente ridotte a quelle in cui ci sono più di cinque libri in una categoria:
NOMECATEGORIA COUNT(*)
-------------------- ----------
NARRADULTI 6
SAGGIADULTI 10
CONSADULTI 6
Per stabilire una valutazione media per categoria, è possibile utilizzare la funzione AVG,
come mostrato nel listato seguente:
Valutazione è una colonna di caratteri di tipo VARCHAR2, ma contiene dei valori numerici,
quindi Oracle può applicare su di essa delle funzioni numeriche (si consulti il Capitolo 11). Qual
è la valutazione media totale?
AVG(VALUTAZIONE)
----------------
3.32258065
In questo caso non c’è nessuna clausola group by, perché l’intero insieme di righe nella
tabella BIBLIOTECA viene trattato come gruppo. Ora si può utilizzare questo risultato come
RAGGRUPPAMENTI 223
parte di una query più ampia: quali categorie hanno valutazioni medie superiori alla valutazione
media di tutti i blocchi?
Analizzando di nuovo i listati precedenti, questo risultato è corretto, perché solo due dei
gruppi hanno valori di valutazione medi superiori alla media totale.
Anche se i risultati sono ordinati in base alla colonna NomeCategoria, lo scopo di group by
non è produrre una sequenza desiderata, bensì raccogliere righe “simili”. L’ordine in cui compa-
iono è un effetto collaterale della modalità di funzionamento di group by; group by non è stata
progettata per alterare il criterio di ordinamento.
Aggiunta di order by
La soluzione per creare un ordine alternativo di visualizzazione è l’aggiunta di una clausola
order by dopo la clausola having. Per esempio, si potrebbe aggiungere l’istruzione seguente:
NOMECATEGORIA COUNT(*)
-------------------- ----------
ILLUSRAGAZZI 3
SAGGIRAGAZZI 1
NARRRAGAZZI 5
CONSADULTI 6
SAGGIADULTI 10
NARRADULTI 6
Ecco il risultato:
NOMECATEGORIA COUNT(*)
-------------------- ----------
SAGGIADULTI 10
NARRADULTI 6
224 CAPITOLO 12
CONSADULTI 6
NARRRAGAZZI 5
ILLUSRAGAZZI 3
SAGGIRAGAZZI 1
Anche se è possibile usare l’alias della colonna come parte della clausola order by, non lo si
potrà utilizzare come parte della clausola having. L’assegnazione a COUNT(*) di un alias come
“Contatore” e il tentativo di usare having Contatore > 1 come clausola in questa query porteran-
no a un errore “invalid column name”:
Ordine di esecuzione
La query precedente contiene una certa quantità di clausole. Di seguito sono riportate le regole
utilizzate da Oracle per eseguire ciascuna di esse e l’ordine in cui viene effettuata l’esecuzione:
1. Vengono scelte le righe in base alla clausola where.
2. Queste righe vengono raggruppate in base alla clausola group by.
3. Per ogni gruppo vengono calcolati i risultati delle funzioni di gruppo.
4. Vengono scelti ed eliminati i gruppi in base alla clausola having.
5. I gruppi vengono ordinati in base ai risultati delle funzioni di gruppo nella clausola order by.
La clausola order by deve utilizzare una funzione di gruppo oppure una colonna specificata nella
clausola group by.
L’ordine di esecuzione è importante in quanto ha un impatto diretto sulle prestazioni delle
query. In generale, più record possono essere eliminati attraverso le clausole where, più rapida è
l’esecuzione delle query. Questo guadagno di prestazioni è dovuto alla riduzione del numero di
righe che devono essere elaborate durante l’operazione group by.
Se una query utilizza una clausola having per eliminare gruppi, è consigliabile controllare se
questa condizione può essere riscritta come una clausola where. In molti casi questa riscrittura
non è possibile. In genere è realizzabile solo quando la clausola having è impiegata per eliminare
gruppi basati sulle colonne di raggruppamento.
Per esempio, si supponga di avere questa query:
group by NomeCategoria
COUNT(*)
Nella versione modificata vengono raggruppate meno righe, portando così a miglioramenti nelle
prestazioni. Via via che il numero di righe nelle tabelle aumenta, il miglioramento delle presta-
zioni può aumentare drasticamente dall’eliminazione della prima riga.
Questo potrebbe sembrare un esempio di messa a punto banale perché la tabella contiene
poche righe. Tuttavia anche una query così piccola può avere un impatto significativo in un’ap-
plicazione destinata a un ambiente di produzione. Ci sono molti esempi di applicazioni di produ-
zione con prestazioni che risentono in misura notevole degli elevati volumi di esecuzioni prodot-
ti da query apparentemente piccole. Quando queste piccole query vengono eseguite migliaia o
milioni di volte al giorno, diventano responsabili del maggiore consumo di risorse nel database.
Quando si pianificano i percorsi di accesso SQL per un’applicazione, occorre mettere a punto
anche le query più piccole.
226 CAPITOLO 12
È possibile creare una vista basata su questa query, per poi interrogare la vista con una query:
desc CATEGORIA_CONTEGGIO
NOMECATEGORIA CONTATORE
-------------------- ---------
NARRADULTI 6
SAGGIADULTI 10
CONSADULTI 6
NARRRAGAZZI 5
SAGGIRAGAZZI 1
ILLUSRAGAZZI 3
“Contatore” viene definito come un alias di colonna, un altro nome da utilizzare quando si fa
riferimento a una colonna. Nella descrizione della vista e nella query non c’è alcuna prova della
RAGGRUPPAMENTI 227
I nternamente, Oracle opera con tutti i nomi delle colonne e delle tabelle in maiuscolo. Questo è
il modo in cui i nomi sono salvati nel dizionario di dati e in cui ci si attende che siano riportati.
Quando vengono digitati gli alias per creare una vista, non dovrebbero mai essere racchiusi tra
apici. Con i doppi apici si induce Oracle a salvarli internamente con caratteri sia maiuscoli che
minuscoli. In questo caso, Oracle non sarà mai in grado di trovare queste colonne quando si
esegue un’istruzione select, a meno di non racchiudere tra apici i nomi delle colonne durante tutte
le query.
Pertanto, quando si creano alias per una vista, non si devono mai utilizzare i doppi apici.
funzione di raggruppamento eseguita, solo il nome della colonna Contatore. È come se la vista
CATEGORIA_CONTEGGIO fosse una reale tabella con le righe delle somme mensili. Perché?
Oracle prende automaticamente una singola parola, senza apici, e la utilizza per rinominare
la colonna che segue. Durante questa operazione, Oracle trasforma la parola (l’alias) in maiusco-
lo, a prescindere da come era stata digitata. Si può eseguire una verifica confrontando i nomi
delle colonne nei comandi create view e describe. Quando si crea una vista, gli apici non devono
mai essere inseriti intorno agli alias delle colonne. Gli alias devono rimanere sempre nelle istruzio-
ni create view senza apici. In questo modo, vengono memorizzati in maiuscolo, cosa necessaria
perché Oracle possa trovarli. Per un avvertimento relativo all’uso degli alias, si rimanda al riqua-
dro “Alias nella creazione di viste”.
Ora si hanno i conteggi di Categoria raccolti in una vista. Si potrebbe creare anche un totale
per l’intera libreria, utilizzando CONTEGGIOLIBRI sia come nome per la vista sia come alias
della colonna per COUNT(*):
View created.
select CONTEGGIOLIBRI
from CONTEGGIOLIBRI;
CONTEGGIOLIBRI
--------------
31
Via via che nuove righe vengono aggiunte ed eseguite sulla tabella BIBLIOTECA, le viste
CONTEGGIOLIBRI e CATEGORIA_CONTEGGIO rifletteranno le modifiche dei conteggi.
informazioni che prima non erano evidenti. Per esempio, qual è la percentuale dei libri in ogni
categoria?
In questa query, due viste sono elencate nella clausola from, ma non sono unite in una clau-
sola where. Perché? In questo caso particolare, non è necessaria alcuna clausola where perché
una delle viste, CONTEGGIOLIBRI, restituisce soltanto una riga (come mostrato nel listato
precedente). L’unica riga in CONTEGGIOLIBRI viene unita a ciascuna riga di CATEGORIA_
CONTEGGIO, ottenendo così una riga di output per ogni riga contenuta in CATEGORIA_
CONTEGGIO. Sarebbe stato possibile ottenere gli stessi risultati unendo direttamente la tabella
BIBLIOTECA alla vista CONTEGGIOLIBRI, ma come si può vedere, la query è più complicata
e difficile da comprendere, e con l’aumento del numero dei gruppi la query diventa sempre più
complessa:
(COUNT(*)/MAX(ConteggioLibri))*100 as Percento
Dato che questo risultato fa parte di una funzione di raggruppamento, ciascuno dei valori deve
essere raggruppato. Pertanto, un tentativo iniziale come questo fallirebbe in quanto ConteggioLibri
non è raggruppata:
(COUNT(*)/ConteggioLibri)*100 as Percento
Considerata la presenza di una sola riga nella vista CONTEGGIOLIBRI, è possibile eseguire
una funzione MAX su di essa in modo che venga restituita quest’unica riga, raggruppata a se
stessa.
Per creare query in grado di confrontare un raggruppamento di righe con un altro, almeno
uno dei raggruppamenti dev’essere una vista oppure una “vista in linea” creata nella clausola
from della query. Al di là di queste restrizioni tecniche, però, le query eseguite con le viste sono
più semplici e facili da capire. Se si confrontano gli ultimi due esempi, la differenza per quel che
riguarda la chiarezza è evidente. Infatti, le viste nascondono la complessità.
Per applicare il metodo della vista in linea, si inserisca il testo della vista nella clausola from
assegnando alle colonne degli alias:
RAGGRUPPAMENTI 229
In questo esempio, la vista CONTEGGIOLIBRI è stata rimossa dalla clausola from e sosti-
tuita dalla sua query base. In questa query, l’alias di ConteggioLibri viene assegnato al risultato
della funzione COUNT(*) eseguita sulla tabella BIBLIOTECA. Nella query principale, questo
alias di ConteggioLibri viene poi utilizzato come parte integrante di un calcolo. Con questo
metodo di codifica non è necessario creare la vista CONTEGGIOLIBRI. È opportuno fare molta
attenzione quando all’interno della stessa query si utilizzano più livelli di raggruppamento: la
creazione di viste in genere aiuta a semplificare la creazione e la gestione del codice.
Con i dati ordinati nella vista, lo sviluppo dell’applicazione potrebbe risultare più semplice.
Per esempio, se il codice passa attraverso un gruppo di record, la possibilità di ordinare prima
questi record potrebbe semplificare l’elaborazione e il controllo degli errori. Durante lo svilup-
po dell’applicazione, si ha la certezza che i dati vengono sempre restituiti in modo ordinato. La
query seguente seleziona i valori di Titolo, utilizzando la pseudocolonna NumeroRiga per limi-
tare l’output a nove record:
TITOLO
--------------------------------------
ANNE OF GREEN GABLES
BOX SOCIALS
CHARLOTTE’S WEB
COMPLETE POEMS OF JOHN KEATS
EITHER/OR
EMMA WHO SAVED MY LIFE
GOOD DOG, CARL
GOSPEL
HARRY POTTER AND THE GOBLET OF FIRE
In questo esempio, la clausola having ha selezionato solo le categorie con una valutazione
media maggiore di 4 (group by ha raccolto tutte le righe in gruppi per NomeCategoria). Tutti gli
altri gruppi sono stati eliminati. Per il gruppo che ha soddisfatto questo criterio è invece stata
calcolata la percentuale del conteggio totale.
La clausola having è molto efficiente per stabilire quali righe di una tabella contengono
valori duplicati in colonne specifiche. Per esempio, se si sta cercando di stabilire un nuovo
indice unico su una colonna (o su una serie di colonne) di una tabella e la creazione dell’indice
fallisce per problemi di unicità dei dati, è facile determinare quali righe hanno causato il problema.
Innanzi tutto occorre selezionare le colonne che dovrebbero essere uniche, seguite da una
colonna COUNT(*). Occorre poi raggruppare in base alle colonne che dovrebbero essere uniche
e utilizzare la clausola having per restituire solo i gruppi dove COUNT(*)>1. Quindi, soltanto i
record restituiti hanno valori duplicati. La query seguente mostra questo tipo di verifica effettua-
ta per la colonna NomeAutore della tabella AUTORE:
no rows selected
Quali libri hanno più di un autore? Si selezionino i titoli da BIBLIOTECA_AUTORE per i quali
il gruppo (raggruppato per Titolo) ha più di un membro:
TITOLO COUNT(*)
---------------------------------------- ----------
COMPLETE POEMS OF JOHN KEATS 2
JOURNALS OF LEWIS AND CLARK 4
KIERKEGAARD ANTHOLOGY 2
RUNAWAY BUNNY 2
RAGGRUPPAMENTI 231
Chi sono questi dieci autori? Si potrebbe creare una vista basata su questa query, oppure
concepirla come vista in linea:
TITOLO NOMEAUTORE
---------------------------------------- --------------------
COMPLETE POEMS OF JOHN KEATS JOHN BARNARD
COMPLETE POEMS OF JOHN KEATS JOHN KEATS
JOURNALS OF LEWIS AND CLARK BERNARD DE VOTO
JOURNALS OF LEWIS AND CLARK MERIWETHER LEWIS
JOURNALS OF LEWIS AND CLARK STEPHEN AMBROSE
JOURNALS OF LEWIS AND CLARK WILLIAM CLARK
KIERKEGAARD ANTHOLOGY ROBERT BRETALL
KIERKEGAARD ANTHOLOGY SOREN KIERKEGAARD
RUNAWAY BUNNY CLEMENT HURD
RUNAWAY BUNNY MARGARET WISE BROWN
Questa query potrebbe apparire complicata (e l’uso di una vista la renderebbe più leggibile),
tuttavia si basa su concetti analizzati in questo capitolo: una vista in linea esegue una funzione
group by e utilizza una clausola having per restituire solamente i titoli con più autori. Questi
titoli serviranno poi come base di una query sulla tabella BIBLIOTECA_AUTORE. In una query
singola, la tabella BIBLIOTECA_AUTORE viene sottoposta a query per i dati raggruppati e per
i dati delle singole righe.
I titoli e gli autori verranno ordinati in base al numero degli autori (partendo dal numero
maggiore), quindi per Titolo e per NomeAutore:
232 CAPITOLO 12
TITOLO NOMEAUTORE
---------------------------------------- ----------------------
JOURNALS OF LEWIS AND CLARK BERNARD DE VOTO
JOURNALS OF LEWIS AND CLARK MERIWETHER LEWIS
JOURNALS OF LEWIS AND CLARK STEPHEN AMBROSE
JOURNALS OF LEWIS AND CLARK WILLIAM CLARK
COMPLETE POEMS OF JOHN KEATS JOHN BARNARD
COMPLETE POEMS OF JOHN KEATS JOHN KEATS
KIERKEGAARD ANTHOLOGY ROBERT BRETALL
KIERKEGAARD ANTHOLOGY SOREN KIERKEGAARD
RUNAWAY BUNNY CLEMENT HURD
RUNAWAY BUNNY MARGARET WISE BROWN
Unione di colonne
Come si è spiegato nei Capitoli 4 e 5, per unire due tabelle, è necessario che queste abbiano una
relazione definita da una colonna comune. Ciò vale anche se si desidera unire delle viste tra loro,
oppure tabelle e viste. L’unica eccezione si ha quando una delle tabelle o delle viste ha una sola
riga, come la tabella CONTEGGIOLIBRI. In questo caso, SQL unisce la singola riga a ogni riga
dell’altra tabella o vista e non è necessario fare alcun riferimento, nella clausola where della
query, alle colonne di unione.
Qualunque tentativo di unire due tabelle che hanno ognuna più di una riga senza specificare
le colonne di unione nella clausola where produce un prodotto cartesiano, in genere un risultato
gigantesco dove ogni riga di una tabella è unita con ogni riga dell’altra. Una piccola tabella di 80
righe unita in questo modo con un’altra piccola tabella di 100 righe produrrebbe 8000 righe,
poche delle quali significative.
Q
uesto capitolo e quello successivo introducono concetti più
difficili rispetto a quelli esaminati in precedenza. Anche se molte di queste tecniche sono rara-
mente utilizzate nelle normali operazioni di esecuzione di query o di produzione di report, esi-
stono sicuramente occasioni in cui è necessario impiegarle. Se sembrano troppo impegnative, è
comunque utile andare avanti. Il vantaggio è che quando questi metodi saranno necessari, si sarà
in grado di utilizzarli.
CATPADRE SOTTOCATEGORIA
-------- --------------------
ADULTI NARRATIVA
ADULTI SAGGI
ADULTI CONSULTAZIONE
RAGAZZI NARRATIVA
RAGAZZI ILLUSTRATI
Tre tabelle vengono unite tramite join allo stesso modo di due. Le colonne comuni sono
impostate uguali fra loro nella clausola where, come mostrato nel listato precedente. Per unire
tre tabelle tramite join, occorre collegare due di esse a una terza. In questo esempio, la tabella
CATEGORIA viene unita tramite join alla tabella BIBLIOTECA, e il risultato di questo join
viene a sua volta unito alla tabella BIBLIOTECA_PRESTITO. La clausola distinct indica a
Oracle di restituire solamente combinazioni distinte di CategoriaPadre e Sottocategoria.
234 CAPITOLO 13
NOTA Non tutte le tabelle vengono unite tramite join. In effetti, il numero di col-
legamenti tra le tabelle è in genere inferiore di uno rispetto al numero delle tabelle da unire
tramite join.
Una volta unite le tabelle, come mostrato nelle prime due linee della clausola where, è
possibile stabilire il numero di verifiche per categoria padre e per sottocategoria.
Subquery correlate
Esiste un altro modo per eseguire join tra più tabelle? Si ricordi che una clausola where può
contenere un’istruzione select di una subquery. Le istruzioni select di subquery possono essere
annidate, ovvero una clausola where in una subquery può anche contenere una clausola where
con una subquery, che a sua volta può contenere una clausola where con una subquery, fino a
molti livelli, più di quanti saranno mai necessari. Il listato seguente mostra tre istruzioni select,
ciascuna connessa all’altra attraverso una clausola where:
CATPADRE SOTTOCATEGORIA
-------- --------------------
ADULTI NARRATIVA
ADULTI SAGGI
ADULTI CONSULTAZIONE
RAGAZZI NARRATIVA
RAGAZZI ILLUSTRATI
Questa query seleziona qualsiasi categoria contenga libri che sono stati presi in prestito.
Ottiene questo risultato richiedendo semplicemente un libro il cui titolo si trovi nella tabella
BIBLIOTECA e il cui record di controllo sia invece nella tabella BIBLIOTECA_PRESTITO. In
una subquery, Oracle presuppone che le colonne provengano dalla prima istruzione select, ovve-
ro quella che contiene la subquery nella sua clausola where. Questa prende il nome di subquery
annidata, perché per ogni NomeCategoria nella query principale (esterna), NomeCategoria po-
trebbe essere correlata nella seconda clausola where.
In altre parole, una subquery può fare riferimento a una colonna di una tabella utilizzata
nella propria query principale (la query che ha la subquery nella clausola where). Si consideri la
query riportata di seguito:
TITOLO
--------------------------------------------------
WONDERFUL LIFE
THE MISMEASURE OF MAN
QUANDO UNA QUERY DIPENDE DA UN’ALTRA 235
Quando viene eseguita come subquery, viene correlata alla query padre, quindi è possibile
fare riferimento alle colonne della prima istruzione select nella subquery. In questo e nei prossi-
mi capitoli verranno proposti altri esempi di subquery correlate.
A prima vista, questa query potrebbe sembrare un po’ complessa; in realtà, se si analizza il
codice in dettaglio diventa semplice da seguire. Si parta dalla query più interna: si ottiene un
elenco dei titoli che Fred Fuller ha già letto. Per questi titoli, si fa riferimento alla tabella BI-
BLIOTECA per avere un elenco dei valori di NomeCategoria distinti ai quali sono assegnati
questi libri. Si ritorni ora alla tabella BIBLIOTECA per ricavare tutti i titoli in queste categorie.
Per questi titoli, si fa riferimento alla tabella BIBLIOTECA_AUTORE per creare un elenco
degli autori. Ecco i risultati:
NOMEAUTORE
--------------------
BERNARD DE VOTO
BERYL MARKHAM
DANIEL BOORSTIN
DAVID MCCULLOUGH
DIETRICH BONHOEFFER
G. B. TALBOT
JOHN ALLEN PAULOS
MERIWETHER LEWIS
STEPHEN AMBROSE
STEPHEN JAY GOULD
WILLIAM CLARK
236 CAPITOLO 13
Fred chiede dei consigli su autori nuovi, quindi si devono escludere quelli che ha già letto.
Per visualizzare il nome degli autori che Fred ha già letto, è sufficiente eseguire la query sulle
tabelle BIBLIOTECA_PRESTITO e BIBLIOTECA_AUTORE:
NOMEAUTORE
------------------------
DAVID MCCULLOUGH
Ora si dovrà escludere il nome di questo autore dall’elenco che si sta per fornire. Aggiun-
gendo un’altra clausola and alla query si può ottenere questo risultato:
NOMEAUTORE
--------------------
BERNARD DE VOTO
BERYL MARKHAM
DANIEL BOORSTIN
DIETRICH BONHOEFFER
G. B. TALBOT
JOHN ALLEN PAULOS
MERIWETHER LEWIS
STEPHEN AMBROSE
STEPHEN JAY GOULD
WILLIAM CLARK
Questa clausola and fa parte della query principale anche se segue la subquery. Inoltre, si noti
che per alcune tabelle la query viene effettuata in più punti all’interno dello script; ciascuna di
queste query viene considerata come un accesso separato della tabella.
NOMEAUTORE COUNT(*)
------------------------------ ----------
DAVID MCCULLOUGH 2
DIETRICH BONHOEFFER 2
E. B. WHITE 2
SOREN KIERKEGAARD 2
STEPHEN JAY GOULD 2
W. P. KINSELLA 2
WILTON BARNHARDT 2
Tuttavia, il tentativo di trovare sia il NomeAutore sia il Titolo non riesce, perché l’istruzione
group by , resa necessaria da COUNT(*), è impostata sulla chiave primaria della tabella
BIBLIOTECA_AUTORE (NomeAutore, Titolo). Dato che per definizione ogni chiave primaria
identifica in modo univoco soltanto una riga, il numero dei titoli per questa riga non può mai
essere maggiore di uno, perciò il test della clausola having risulta sempre falso, e la query non
trova alcuna riga:
no rows selected.
EXISTS fornisce una soluzione. La subquery seguente chiede se, per ogni NomeAutore
selezionato nella query esterna, esiste un NomeAutore nella tabella BIBLIOTECA_AUTORE
con un numero di Titoli maggiore di uno. Se per un dato nome la risposta è positiva, il test di
EXISTS è vero e la query esterna seleziona un NomeAutore e un Titolo. I nomi degli autori sono
correlati dallo pseudonimo “BA” dato alla prima tabella BIBLIOTECA_AUTORE.
NOMEAUTORE TITOLO
------------------------ ------------------------------
DAVID MCCULLOUGH JOHN ADAMS
DAVID MCCULLOUGH TRUMAN
DIETRICH BONHOEFFER LETTERS AND PAPERS FROM PRISON
DIETRICH BONHOEFFER THE COST OF DISCIPLESHIP
E. B. WHITE CHARLOTTE'S WEB
238 CAPITOLO 13
Le due query sono correlate: si osservi che la subquery fa riferimento alla colonna
BA.NomeAutore anche se questa colonna si trova nella query esterna, e non nella subquery.
All’interno della subquery, l’alias BA2 non è necessario, tuttavia aiuta a semplificare il codice
da mantenere.
Questa stessa query poteva essere costruita utilizzando IN e un test sul nome della colonna.
In questo caso, non è necessaria una subquery correlata:
TITOLO
----------------------------------------
ANNE OF GREEN GABLES
EITHER/OR
GOOD DOG, CARL
HARRY POTTER AND THE GOBLET OF FIRE
QUANDO UNA QUERY DIPENDE DA UN’ALTRA 239
INNUMERACY
JOHN ADAMS
MIDNIGHT MAGIC
MY LEDGER
POLAR EXPRESS
THE DISCOVERERS
THE MISMEASURE OF MAN
THE SHIPPING NEWS
TO KILL A MOCKINGBIRD
TRUMAN
WEST WITH THE NIGHT
WONDERFUL LIFE
Questo report è corretto, tuttavia non mostra i conteggi 0, ossia i libri che non sono stati presi in
prestito. Se è necessario visualizzare l’inventario di tutti i libri insieme alla lista di controllo, si
dovrà unire tramite join la tabella BIBLIOTECA_PRESTITO alla tabella BIBLIOTECA:
Questa query restituirà esattamente gli stessi record, perché le uniche righe di BIBLIOTE-
CA che possono soddisfare i criteri di join sono quelle che sono state controllate. Per elencare i
libri rimanenti, si dovrà ricorrere a un outer join, che indichi a Oracle di restituire una riga anche
se il join non produce una corrispondenza. Prima di Oracle9i, la sintassi per un outer join usava
il segno più (+) sul lato del join che restituiva altre righe. In questo caso, si tratta di
BIBLIOTECA_PRESTITO. La query seguente mostra il numero massimo di giorni in cui ogni
libro è stato preso in prestito:
RUNAWAY BUNNY
SHOELESS JOE
THE COST OF DISCIPLESHIP
THE DISCOVERERS 48
THE GOOD BOOK
THE MISMEASURE OF MAN 31
THE SHIPPING NEWS 59
TO KILL A MOCKINGBIRD 14
TRUMAN 19
TRUMPET OF THE SWAN
UNDER THE EYE OF THE CLOCK
WEST WITH THE NIGHT 48
WONDERFUL LIFE 31
Tutti i titoli contenuti in BIBLIOTECA vengono restituiti, anche quelli che non soddisfano
i criteri di join. Se invece si visualizzano i valori di BIBLIOTECA_PRESTITO.Titolo, si noterà
che si tratta di valori NULL. Si provi a considerare il segno (+), che deve trovarsi subito dopo la
colonna di join della tabella più breve, come un’indicazione “aggiungere un’altra riga (NULL) di
BC.Titolo ogni volta che non esiste una corrispondenza con B.Titolo.”
In questo caso, la tabella BIBLIOTECA_PRESTITO sta ricevendo delle righe restituite du-
rante il join anche se non sono state trovate delle corrispondenze. Questa query può essere riscritta
nel modo seguente:
Si osservi l’uso della clausola on come parte integrante della sintassi dell’outer join. Si
osservi che:
È possibile sostituire la clausola on con una clausola using insieme al nome della colonna
comune alle tabelle: non si deve qualificare il nome della colonna con un nome di tabella o con
un alias di tabella.
QUANDO UNA QUERY DIPENDE DA UN’ALTRA 241
Si osservi che non è consentito specificare un alias di tabella per le colonne elencate nella
clausola using, così come nelle clausole group by e select.
Come accadeva con la vecchia sintassi, il lato utilizzato come tabella di controllo per l’outer
join fa differenza; l’esecuzione di un’outer join a sinistra non restituirà tutti i titoli.
16 rows selected.
Una terza opzione, full outer join, restituisce tutte le righe da entrambe le tabelle. Le righe
che non soddisfano la condizione on restituiscono valori NULL. In questo esempio non ci sono
righe che soddisfino questa condizione, pertanto la query restituisce le medesime 31 righe otte-
nute con right outer join.
Prima di Oracle9i, era possibile generare i risultati di un outer join completo eseguendo due
outer join separati, utilizzando ogni tabella come tabella esterna, e un’operazione union per
combinare i risultati in un’unica query.
242 CAPITOLO 13
select Titolo
from BIBLIOTECA
where Titolo not in
(select Titolo from BIBLIOTECA_PRESTITO)
order by Titolo;
TITOLO
----------------------------------------
BOX SOCIALS
CHARLOTTE'S WEB
COMPLETE POEMS OF JOHN KEATS
EMMA WHO SAVED MY LIFE
GOSPEL
JOURNALS OF LEWIS AND CLARK
KIERKEGAARD ANTHOLOGY
LETTERS AND PAPERS FROM PRISON
PREACHING TO HEAD AND HEART
RUNAWAY BUNNY
SHOELESS JOE
THE COST OF DISCIPLESHIP
THE GOOD BOOK
TRUMPET OF THE SWAN
UNDER THE EYE OF THE CLOCK
Questo è il modo in cui verrebbe generalmente scritta una query di questo tipo, anche se gli
utenti Oracle esperti sanno che così risulterebbe lenta: infatti si potrebbe indurre Oracle a ese-
guire una scansione intera di tabella in poco tempo sulla tabella BIBLIOTECA_PRESTITO.
L’ottimizzatore potrebbe trasformare internamente quel NOT IN in uno degli approcci
funzionalmente identici che seguono. La query seguente utilizza un outer join e produce lo stes-
so risultato. La differenza è che quest’ultima sarà efficiente poiché l’ottimizzatore può sfruttare
gli indici nelle colonne di join:
TITOLO
----------------------------------------
BOX SOCIALS
CHARLOTTE'S WEB
COMPLETE POEMS OF JOHN KEATS
EMMA WHO SAVED MY LIFE
GOSPEL
JOURNALS OF LEWIS AND CLARK
KIERKEGAARD ANTHOLOGY
LETTERS AND PAPERS FROM PRISON
QUANDO UNA QUERY DIPENDE DA UN’ALTRA 243
Perché questa query funziona e dà gli stessi risultati che con NOT IN? L’outer join tra le due
tabelle garantisce che tutte le righe siano disponibili per il test, comprese quelle dei titoli per i
quali non è elencato alcun record di controllo nella tabella BIBLIOTECA_PRESTITO. La linea:
produce solamente quei titoli che non appaiono nella tabella BIBLIOTECA_PRESTITO (quin-
di, Oracle li restituisce come titoli NULL). La logica in questo caso è oscura, ma funziona. Il
modo migliore per utilizzare questa tecnica consiste nel seguire semplicemente il modello.
select B.Titolo
from BIBLIOTECA B
where not exists
(select 'x' from BIBLIOTECA_PRESTITO BC
where BC.Titolo = B.Titolo)
order by B.Titolo;
TITOLO
----------------------------------------
BOX SOCIALS
CHARLOTTE'S WEB
COMPLETE POEMS OF JOHN KEATS
EMMA WHO SAVED MY LIFE
GOSPEL
JOURNALS OF LEWIS AND CLARK
KIERKEGAARD ANTHOLOGY
LETTERS AND PAPERS FROM PRISON
PREACHING TO HEAD AND HEART
RUNAWAY BUNNY
SHOELESS JOE
THE COST OF DISCIPLESHIP
THE GOOD BOOK
TRUMPET OF THE SWAN
UNDER THE EYE OF THE CLOCK
244 CAPITOLO 13
Questa query indica i libri che non sono stati presi in prestito, come mostrato in precedenza
tramite i metodi di NOT IN e di outer join. Ma come funziona questa query?
Per ogni record nella tabella BIBLIOTECA, viene controllata la subquery NOT EXISTS. Se
il join di questo record alla tabella BIBLIOTECA_PRESTITO restituisce una riga, la subquery
ha esito positivo. NOT EXISTS comunica alla query di invertire il codice restituito; perciò, qual-
siasi riga in BIBLIOTECA che può essere unita tramite a join a BIBLIOTECA_PRESTITO non
viene restituita dalla query esterna. Le uniche righe rimaste sono quelle di BIBLIOTECA che
non hanno una riga corrispondente in BIBLIOTECA_PRESTITO.
NOT EXISTS è un modo molto efficiente per effettuare questo tipo di query, soprattutto
quando per il join vengono utilizzate più colonne. Dato che impiega un join, NOT EXISTS è
spesso in grado di sfruttare gli indici disponibili, a differenza di NOT IN. La possibilità di utiliz-
zare indici per questo tipo di query può avere un impatto significativo sulle prestazioni della
query.
select Titolo
from LIBRO_ORDINE natural join BIBLIOTECA;
TITOLO
----------------------------------------
SHOELESS JOE
GOSPEL
select BO.Titolo
from LIBRO_ORDINE BO, BIBLIOTECA
where BO.Titolo = BIBLIOTECA.Titolo
and BO.Editore = BIBLIOTECA.Editore
and BO.NomeCategoria = BIBLIOTECA.NomeCategoria;
Il join è stato eseguito in base alle colonne comuni alle due tabelle.
Il supporto per la sintassi dei join interni è stato introdotto con Oracle9i. I join interni sono
quelli predefiniti, restituiscono le righe comuni alle due tabelle e rappresentano l’alternativa agli
outer join. Si osservi che questi join supportano le clausole on e using, quindi è possibile speci-
ficare i propri criteri di join come mostrato nel listato seguente:
select BO.Titolo
from LIBRO_ORDINE BO inner join BIBLIOTECA B
on BO.Titolo= B.Titolo;
TITOLO
----------------------------------------
GOSPEL
SHOELESS JOE
QUANDO UNA QUERY DIPENDE DA UN’ALTRA 245
TITOLO
----------------------------------------
ANNE OF GREEN GABLES
BOX SOCIALS
CHARLOTTE'S WEB
COMPLETE POEMS OF JOHN KEATS
EITHER/OR
EMMA WHO SAVED MY LIFE
GALILEO'S DAUGHTER
GOOD DOG, CARL
GOSPEL
HARRY POTTER AND THE GOBLET OF FIRE
INNUMERACY
JOHN ADAMS
JOURNALS OF LEWIS AND CLARK
KIERKEGAARD ANTHOLOGY
LETTERS AND PAPERS FROM PRISON
LONGITUDE
ONCE REMOVED
SHOELESS JOE
SOMETHING SO STRONG
19 rows selected.
246 CAPITOLO 13
Dove è finito il record in più? Il problema è che uno dei valori di Titolo nella tabella
LIBRO_ORDINE si trova già nella tabella BIBLIOTECA. Per visualizzare i duplicati, occorre
utilizzare UNION ALL al posto di UNION:
TITOLO
----------------------------------------
ANNE OF GREEN GABLES
BOX SOCIALS
CHARLOTTE'S WEB
COMPLETE POEMS OF JOHN KEATS
EITHER/OR
EMMA WHO SAVED MY LIFE
GALILEO'S DAUGHTER
GOOD DOG, CARL
GOSPEL
GOSPEL
HARRY POTTER AND THE GOBLET OF FIRE
INNUMERACY
JOHN ADAMS
JOURNALS OF LEWIS AND CLARK
KIERKEGAARD ANTHOLOGY
LETTERS AND PAPERS FROM PRISON
LONGITUDE
ONCE REMOVED
SHOELESS JOE
SOMETHING SO STRONG
20 rows selected.
TITOLO
----------------------------------------
GOSPEL
SHOELESS JOE
Successivamente, viene creato l’elenco dei nuovi libri (in LIBRO_ORDINE ma non in BI-
BLIOTECA) tramite l’operatore MINUS:
TITOLO
----------------------------------------
GALILEO'S DAUGHTER
LONGITUDE
ONCE REMOVED
SOMETHING SO STRONG
Si sarebbe potuto utilizzare MINUS anche per mostrare quali libri non erano stati presi in
prestito:
TITOLO
------------------------------
BOX SOCIALS
CHARLOTTE'S WEB
COMPLETE POEMS OF JOHN KEATS
EMMA WHO SAVED MY LIFE
GOSPEL
JOURNALS OF LEWIS AND CLARK
KIERKEGAARD ANTHOLOGY
LETTERS AND PAPERS FROM PRISON
PREACHING TO HEAD AND HEART
RUNAWAY BUNNY
SHOELESS JOE
THE COST OF DISCIPLESHIP
THE GOOD BOOK
TRUMPET OF THE SWAN
UNDER THE EYE OF THE CLOCK
15 rows selected.
Fin qui sono stati trattati gli aspetti fondamentali di UNION, INTERSECT e MINUS. Ora è
opportuno un esame più dettagliato. Nella combinazione di due tabelle, Oracle non si occupa dei
nomi delle colonne ai due lati dell’operatore di combinazione, ovvero richiede che ogni istruzio-
ne select sia valida e abbia colonne valide per le proprie tabelle; tuttavia i nomi delle colonne
nella prima istruzione select non devono necessariamente coincidere con quelli della seconda.
Oracle impone queste condizioni essenziali:
■ Le istruzioni select devono avere lo stesso numero di colonne. Se in due tabelle sottoposte a
query il numero di colonne selezionate è diverso, si potranno selezionare le stringhe al posto
delle colonne per far coincidere gli elenchi delle colonne delle due query.
■ Le colonne corrispondenti nelle istruzioni select devono appartenere allo stesso tipo di dati
(non è necessario che siano della stessa lunghezza).
Quando ordina l’output, Oracle utilizza i nomi delle colonne tratti dalla prima istruzione
select per assegnare i risultati della query. Di conseguenza, solo i nomi delle colonne tratti dalla
prima istruzione select potranno essere impiegati in order by.
248 CAPITOLO 13
Gli operatori di combinazione possono essere utilizzati con due o più tabelle, e in questo
caso la precedenza diventa un vero problema, soprattutto se compaiono INTERSECT e MINUS.
Per imporre l’ordine desiderato occorre utilizzare le parentesi.
Subquery IN
Gli operatori di combinazione possono essere utilizzati nelle subquery, ma occorre prestare molta
attenzione alla precedenze. Una query del tipo:
è scarna e ambigua. Quale operazione verrà eseguita per prima, il join delle due query come
parte integrante di un’unica clausola where, oppure la clausola in cha si basa sulla query di
TABELLA_1 seguita poi da un join di questo risultato con TABELLA_2? Per chiarire la proprie
intenzioni e per far rispettare la precedenza corretta delle operazioni sono necessarie delle pa-
rentesi. Alla clausola in viene sempre data una precedenza maggiore rispetto a union, a meno che
non si inseriscano delle parentesi per alterare il modo in cui viene eseguita la query. Se si deside-
ra che union abbia una precedenza maggiore, occorre utilizzare delle parentesi:
Alcune possibilità
complesse
Q
uesto capitolo prosegue lo studio delle funzioni e delle carat-
teristiche più complesse di Oracle. Di particolare interesse è la creazione di query semplici e di
gruppo che possono essere presentate in viste, l’utilizzo di totali nei calcoli e la creazione di
report che mostrano strutture ad albero. Come quelle del Capitolo 13, queste tecniche non sono
essenziali per la maggior parte delle situazioni in cui serve realizzare un report. Se sembrano
troppo difficili, non c’è da preoccuparsi. Per chi sta iniziando ora a utilizzare Oracle e le sue
funzionalità per le query, è sufficiente sapere che queste tecniche esistono e che possono essere
applicate in caso di necessità.
NOMECATEGORIA CONTATORE
-------------------- ----------
NARRADULTI 6
SAGGIADULTI 10
CONSADULTI 6
NARRRAGAZZI 5
250 CAPITOLO 14
SAGGIRAGAZZI 1
ILLUSRAGAZZI 3
Si provi a ordinare i risultati in base ai valori della colonna Contatore, partendo dal più grande:
NOMECATEGORIA CONTATORE
-------------------- ----------
SAGGIADULTI 10
NARRADULTI 6
CONSADULTI 6
NARRRAGAZZI 5
ILLUSRAGAZZI 3
SAGGIRAGAZZI 1
RANK(3)WITHINGROUP(ORDERBYCONTATOREDESC)
----------------------------------------
5
Un valore pari a 3 per Contatore sarebbe il quinto valore più alto di Contatore. E un valore di
Contatore pari a 8?
RANK(8)WITHINGROUP(ORDERBYCONTATOREDESC)
----------------------------------------
2
L’aggiunta di questi cinque libri alla categoria la sposterebbe al secondo posto. Da un punto
di vista percentile, quale sarebbe la graduatoria per questa categoria?
PERCENT_RANK(8)WITHINGROUP(ORDERBYCONTATOREDESC)
------------------------------------------------
.166666667
ALCUNE POSSIBILITÀ COMPLESSE 251
set headsep !
column Nome format a20
column Titolo format a20 word_wrapped
column GiorniPrestito format 999.99 heading 'Giorni!Prestito'
column GiorniRitardo format 999.99 heading 'Giorni!Ritardo'
Giorni Giorni
NOME TITOLO DATAREST Prestito Ritardo TASSARITARDO
-------------------- -------------------- --------- -------- ------- ----------
DORAH TALBOT MY LEDGER 03-MAR-02 16.00 2.00 .4
******************** ----------
sum .4
clear compute
clear break
select DataRestituzione, Nome,
SUM((DataRestituzione-DataPrestito -14)*0.20) TassaRitardo
from BIBLIOTECA_PRESTITO
where DataRestituzione-DataPrestito > 14
group by DataRestituzione, Nome
order by DataRestituzione, Nome;
Poi è possibile modificare ulteriormente questa tabella in modo da raggruppare questi importi
per mese:
Invece di raggruppare per Mese e per Nome, si potrebbe usare la funzione ROLLUP per
generare i totali parziali e i totali. Nell’esempio seguente, la clausola group by viene modificata
per includere una chiamata alla funzione ROLLUP. Si osservino le righe in più create alla fine del
risultato e dopo ogni mese:
Per ogni mese, Oracle ha calcolato la tassa di ritardo totale indicandola con un valore NULL
per il nome. L’output mostra nel mese di febbraio due importi separati pari a 3,40 e un totale
mensile di 6,80. Per il trimestre, il totale degli importi dovuti a ritardi è di 37.00. Anche con i
comandi SQL*Plus (fare riferimento al Capitolo 6) sarebbe stato possibile calcolare questi risul-
tati, tuttavia questo metodo consente di ottenere queste somme con un solo comando SQL a
prescindere dallo strumento utilizzato per eseguire la query del database.
Si provi ad abbellire il report. Con la funzione GROUPING è possibile stabilire se una riga
è un totale o un totale parziale (creato da ROLLUP) oppure se corrisponde a un valore NULL nel
database. Nella clausola select, la colonna Nome verrà selezionata in questo modo:
select DECODE(GROUPING(TO_CHAR(DataRestituzione,'MESE')),1,
'Tutti i mesi',TO_CHAR(DataRestituzione,'MESE')),
DECODE(GROUPING(Nome),1, 'Tutti i nomi',Nome),
SUM((DataRestituzione-DataPrestito -14)*0.20) TassaRitardo
from BIBLIOTECA_PRESTITO
where DataRestituzione-DataPrestito > 14
group by ROLLUP(TO_CHAR(DataRestituzione, 'MESE'), Nome);
Con la funzione CUBE è possibile ottenere i totali parziali per tutte le combinazioni dei
valori nella clausola group by. La query seguente utilizza la funzione CUBE per generare queste
informazioni:
select DECODE(GROUPING(TO_CHAR(DataRestituzione,'MESE')),1,
'Tutti i mesi',TO_CHAR(DataRestituzione,'MESE')),
DECODE(GROUPING(Nome),1, 'Tutti i nomi',Nome),
SUM((DataRestituzione-DataPrestito -14)*0.20) TassaRitardo
from BIBLIOTECA_PRESTITO
where DataRestituzione-DataPrestito > 14
group by CUBE(TO_CHAR(DataRestituzione, 'MESE'), Nome);
La clausola connect by fornisce uno strumento per riportare tutti i membri della famiglia in
questi alberi. Consente di escludere rami o singoli membri di un albero genealogico e di muover-
si attraverso l’albero verso l’alto o verso il basso, riportando i membri della famiglia incontrati
lungo il percorso.
Il primo antenato nell’albero tecnicamente viene chiamato nodo principale. Nel linguaggio
corrente corrisponderebbe al tronco. Dal tronco si estendono i rami, che hanno altri rami, che
hanno ancora altri rami. Le forcelle in corrispondenza delle quali uno o più rami si distaccano da
un ramo più largo prendono il nome di nodi e l’estremità di un ramo viene chiamata foglia o
nodo foglia. La Figura 14.1 mostra una rappresentazione di un albero.
Di seguito è riportata una tabella di mucche e tori nati tra il gennaio del 1900 e l’ottobre del
1908. Ciascun discendente, appena nato, viene inserito come una riga nella tabella, insieme con
il sesso, i genitori (la mucca e il toro) e la data di nascita. Se si confrontano mucche e figli in
questa tabella con la Figura 14.1, si scopre che corrispondono. Per esempio, EVE non ha alcuna
mucca o toro genitore, perché è nata in un’altra fattoria, mentre ADAM e BANDIT sono tori
introdotti per la riproduzione, senza genitori nella tabella.
Foglie (chiamate
anche nodi foglia)
Nodi o forcelle
(Suzy è un nodo
anche se non Nodo radice
sembrerebbe o tronco
una forcella)
Poi viene scritta una query per illustrare visivamente le relazioni familiari. A tal fine si
utilizza LPAD e una colonna speciale, Level, che si ottiene con connect by. Level è un numero, da
1 per EVE a 5 per DELLA, che in realtà indica la generazione. Se EVE è la prima generazione di
bovini, allora DELLA è la quinta generazione. Ogni volta che si usa la clausola connect by, la
colonna Level può essere utilizzata nell’istruzione select per mostrare la generazione di ogni
riga. Level è una pseudocolonna, come SysDate e User. Non fa realmente parte della tabella, ma
è disponibile in determinate circostanze. Il prossimo listato presenta un esempio che utilizza
Level.
I risultati di questa query sono visibili nella tabella seguente, ma perché l’istruzione select
ha prodotto queste informazioni? Come funziona?
Si noti che questa è in pratica la Figura 14.1 percorsa in senso orario. EVE non è al centro,
ma è il nodo principale (tronco) di questo albero. I suoi figli sono BETSY, POCO, GRETA,
MANDY e CINDY. I figli di BETSY sono NOVI, GINNY e TEDDI. I figli di GINNY sono
SUZY e RUTH. E il figlio di SUZY è DELLA. Anche MANDY ha due figli, che si chiamano
DUKE e PAULA.
Questo albero inizia con EVE come primo “discendente”. Se l’istruzione SQL avesse conte-
nuto start with MANDY, sarebbero stati selezionati solo MANDY, DUKE e PAULA. L’istruzio-
ne start with definisce l’inizio della parte di albero da visualizzare e include solo i rami che si
allungano dall’individuo da essa specificato. start with significa proprio “inizia con”.
LPAD nell’istruzione select ha probabilmente una costruzione un po’ confusa. Il formato di
LPAD, riportato dal Capitolo 7, è il seguente:
LPAD(stringa,lunghezza [,'set'])
In altre parole, si indica di prendere la stringa specificata e di riempirla a sinistra con il set di
caratteri specificato fino a raggiungere la lunghezza indicata. Se non viene specificato alcun set
di caratteri, il riempimento avviene con degli spazi vuoti.
Occorre confrontare questa sintassi con LPAD nell’istruzione select mostrata in precedenza:
LPAD(' ',6*(Level-1))
In questo caso, la stringa è costituita da un singolo carattere (uno spazio, indicato dallo
spazio racchiuso tra apici). Inoltre 6*(Level-1) è la lunghezza, e poiché set non è definito, vengo-
no utilizzati degli spazi. In altre parole, viene comunicato a SQL di prendere questa stringa di
uno spazio e di riempirla a sinistra con il numero di spazi determinato da 6*(Level-1), un calcolo
eseguito dapprima sottraendo 1 da Level e moltiplicando questo risultato per 6. Per EVE, Level
è 1, quindi 6*(1-1), oppure 0 spazi. Per BETSY, Level (la sua generazione) è 2, quindi un LPAD
pari a 6. Pertanto, per ogni generazione dopo la prima, vengono concatenati sei spazi in più alla
sinistra della colonna Figlio. L’effetto è evidente nel risultato appena mostrato. Il nome di ogni
Figlio viene rientrato riempiendo a sinistra con un numero di spazi equivalente al suo Level o
alla sua generazione.
Perché si effettuano un riempimento e una concatenazione, invece di utilizzare LPAD diret-
tamente su Figlio? Per due motivi. Primo, un’istruzione LPAD diretta su Figlio avrebbe giustifi-
cato a destra i nomi dei figli. I nomi di ogni livello avrebbero avuto le ultime lettere allineate
verticalmente. Secondo, se Level-1 è uguale a 0, come per EVE, il risultato di LPAD per EVE
sarebbe stato di 0 caratteri, il che avrebbe provocato la sparizione di EVE:
Pertanto, per ottenere la giusta spaziatura per ogni livello, per assicurarsi che EVE sia pre-
sente e per avere i nomi allineati verticalmente a sinistra, si dovrebbe utilizzare LPAD con la
funzione di concatenazione e non direttamente sulla colonna Figlio.
Ma come funziona connect by? Si esamini di nuovo la Figura 14.1. A partire da NOVI e
risalendo l’elenco all’indietro, quali mucche sono le discendenti che vengono prima di NOVI?
La prima è BETSY e quella appena prima di BETSY è EVE. Anche se non è immediatamente
comprensibile, la clausola:
comunica a SQL di trovare la riga successiva in cui il valore della colonna Mucca è uguale al
valore della colonna Figlio nella riga precedente. Si esamini la tabella e si vedrà che è vero.
La clausola where rimuove soltanto la mucca o le mucche in essa citate. Se BETSY muore,
viene rimossa dal diagramma, ma i suoi figli rimangono. In effetti, si noti che BETSY è ancora
sotto la colonna Mucca come madre dei suoi figli, NOVI, GINNY e TEDDI:
260 CAPITOLO 14
L’ordine in cui l’albero genealogico viene visualizzato quando si usa connect by è livello
per livello, da sinistra a destra, come mostrato nella Figura 14, iniziando con il livello più basso,
Level 1. Nell’esempio seguente si vuole alterare questo ordine in modo da raggruppare le muc-
che e i loro figli in base alla data di nascita:
Ora, l’ordine delle righe non mostra più le generazioni, come in un albero, ma l’indentazione
conserva ancora queste informazioni. Però non è possibile stabilire la relazione tra genitori e
discendenti senza osservare le colonne Mucca e Toro. Se non si conosce la data di nascita di
EVE, la visualizzazione dell’albero genealogico chiaramente viene alterata.
Questo risultato mostra le radici di DELLA, ma è un po’ fuorviante rispetto alle visualizzazioni
precedenti. È come se DELLA fosse l’antenata ed EVE l’ultima discendente. Aggiungere un
order by per Datanascita può essere d’aiuto, ma EVE compare ancora all’estrema destra:
Infine, si osservi come questo report appare diverso quando connect by segue la discendenza
del toro. Ecco i discendenti di ADAM:
ADAM e BANDIT erano i tori originari che hanno dato inizio alla mandria. Per creare un
singolo albero che riporti i discendenti sia di ADAM sia di BANDIT, si dovrebbe inventare un
“padre” per questi due tori, che sia la radice dell’albero. Uno dei vantaggi che hanno questi
alberi alternativi rispetto al tipo mostrato in precedenza è che molti gruppi ereditari, dalle fami-
glie ai progetti, ai reparti delle aziende, possono essere rappresentati con precisione in più di un
modo:
Le regole fondamentali
Utilizzare connect by e start with per creare report simili ad alberi non è difficile, ma occorre
seguire alcune regole fondamentali:
■ L’ordine delle clausole quando si usa connect by è il seguente:
1. select
2. from
3. where
4. start with
5. connect by
6. order by
■ prior fa in modo che il report vada dalla radice verso le foglie (se la colonna prior è il genito-
re) o dalle foglie verso la radice (se la colonna prior è il discendente).
■ Una clausola where elimina gli individui dall’albero, ma non i loro discendenti (o gli ante-
nati, se prior è a destra del segno di uguale).
■ Una qualificazione in connect by (in particolare un “non uguale”) elimina un individuo e
tutti i suoi discendenti (o antenati, a seconda di come si traccia l’albero).
■ connect by non può essere utilizzata con un join di tabella nella clausola where.
Probabilmente sono in pochi a ricordare in modo esatto questa particolare serie di comandi.
Tuttavia, con una conoscenza base degli alberi e dell’ereditarietà, per la costruzione di un’istru-
zione select appropriata per un report su un albero dovrebbe essere sufficiente consultare la
sintassi corretta in questo capitolo.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 15
15.1 insert
15.2 rollback, commit e autocommit
15.3 Inserimenti in più tabelle
15.4 delete
15.5 update
15.6 Uso del comando merge
F
inora, tutto ciò che si è appreso su Oracle, SQL e SQL*Plus
riguarda la selezione di dati da tabelle nel database. Questo capitolo mostra in che modo modi-
ficare i dati in una tabella: come inserire nuove righe, come aggiornare i valori delle colonne
nelle righe e come cancellare completamente delle righe. Anche se questi argomenti non sono
stati trattati esplicitamente, quasi tutto il materiale appreso in relazione a SQL, compresi tipi di
dati, calcoli, formattazione di stringhe, clausole where e simili, può essere utilizzato in questa
sede, quindi non rimane molto altro da imparare. Oracle mette a disposizione una funzionalità di
database distribuita e trasparente per inserire, aggiornare e cancellare dati in database remoti
(trattata nel Capitolo 23). Come si vedrà in questo capitolo, Oracle consente di combinare questi
comandi tramite inserimenti in più tabelle e il comando merge (per effettuare le operazioni di
inserimento e aggiornamento in un solo comando).
15.1 insert
Il comando SQL insert consente di inserire una riga di informazioni direttamente in una tabella
(o indirettamente attraverso una vista). La tabella COMFORT registra le temperature a mezzo-
giorno e a mezzanotte nonché le precipitazioni giornaliere, città per città, in quattro date cam-
pione nel corso dell’anno:
describe COMFORT
Per aggiungere una nuova riga a questa tabella, si usi l’istruzione seguente:
insert into COMFORT
values (‘WALPOLE', '21-MAR-03'),
13.8, 6.6, 0);
1 row created.
La parola values deve precedere l’elenco di dati da inserire. Una stringa di caratteri dev’es-
sere racchiusa tra apici, mentre i numeri possono stare da soli. I campi devono essere separati da
virgole e devono avere lo stesso ordine delle colonne nella descrizione della tabella.
Una data dev’essere racchiusa tra apici ed espressa nel formato di data predefinito di Oracle.
Per inserire una data in un formato diverso occorre utilizzare la funzione TO_DATE con una
maschera di formattazione, come mostrato nell’esempio seguente:
insert into COMFORT
values (‘WALPOLE', TO_DATE('06/22/2003','MM/DD/YYYY'),
13.8, 6.6, 0);
1 row created.
Inserimento di un’ora
Se si inseriscono le date senza specificare i valori dell’ora, viene prodotta un’ora predefinita
corrispondente alla mezzanotte, l’inizio del giorno. Se si desidera inserire una data con un’ora
differente, è sufficiente ricorrere alla funzione TO_DATE e includere un’ora:
insert into COMFORT
values (‘WALPOLE', TO_DATE('06/22/2003 1:35',
‘MM/DD/YYYY HH24:MI'), 13.8, 6.6, 0);
1 row created.
Le colonne possono essere inserite anche in ordine diverso rispetto a quello in cui appaiono
nella descrizione, se prima (davanti alla parola values) si elenca l’ordine dei dati. Questo non
modifica l’ordine fondamentale delle colonne nella tabella. Consente semplicemente di elencare
i campi dei dati in un ordine diverso (per informazioni sull’inserimento di dati in tipi di dati
definiti dall’utente, si rimanda alla Parte quinta).
Si può “inserire” anche un valore NULL. In altre parole, la parte sinistra della colonna rimar-
rà vuota per questa riga, come mostrato di seguito:
insert into COMFORT
(DataCampione, Precipitazione, Citta, Mezzogiorno, Mezzanotte)
values ('23-SEP-03', NULL,
‘WALPOLE', 30.2, 22.3);
1 row created.
per DataCampione (22-DEC-03) e per Citta (WALPOLE). Si noti la clausola where nell’istru-
zione select che recupera solo una riga. Se con select fossero state recuperate cinque righe,
sarebbero state inserite cinque nuove righe; se ne fossero state ottenute dieci, ne sarebbero state
inserite dieci e così via.
1 row created.
NOTA Non è possibile utilizzare la sintassi insert into...select from con i tipi di
dati LONG, a meno che non si usi la funzione TO_LOB per inserire i dati LONG in una colonna
LOB.
5 rows selected.
Per “22-JUN-03” vengono mostrati due record perché uno di essi ha un componente dell’ora.
Per visualizzare l’ora, si usi la funzione TO_CHAR:
I record presi dalla tabella LIBRO_ORDINE vengono inseriti nella tabella BIBLIOTECA.
Invece di tentare di riutilizzare lo spazio nella tabella BIBLIOTECA, i nuovi record vengono
posti alla fine della spazio di memorizzazione fisico della tabella.
Dal momento che i nuovi record non tentano di riutilizzare lo spazio disponibile che la
tabella ha già usato, le esigenze di spazio della tabella BIBLIOTECA potrebbero aumentare. In
linea di massima, si dovrebbe utilizzare APPEND solo quando si inseriscono grandi quantità di
dati in tabelle con poco spazio riutilizzabile. Il punto in cui vengono inseriti i record aggiunti
prende il nome di highwatermark della tabella, e l’unico modo di ripristinare un highwatermark
consiste nel troncare la tabella stessa con truncate. Dato che truncate cancella tutti i record e non
può essere annullato, è bene assicurarsi che sia disponibile una copia di backup dei dati della
tabella prima di utilizzare questo comando. Per ulteriori dettagli, si può consultare la voce truncate
nel Capitolo 48.
show autocommit
autocommit OFF
OFF è il valore predefinito e in quasi tutti i casi è la modalità predefinita. Si può anche
specificare un numero per il valore autocommit, in modo da determinare il numero di comandi
dopo i quali Oracle esegue un commit. Se autocommit è OFF, le operazioni di inserimento, ag-
giornamento e cancellazione non vengono rese definitive finché non vengono confermate con
commit:
commit;
commit complete
Finché non viene eseguito commit, gli altri utenti non possono vedere il lavoro che si sta
svolgendo sulle tabelle. Chiunque acceda a queste tabelle continua a ottenere le vecchie infor-
mazioni. Le nuove informazioni sono visibili ogni volta che si effettua una selezione nella tabel-
la. In effetti, si opera su un’area “provvisoria”, con la quale si può interagire finché non si
utilizza commit. È possibile effettuare una grande quantità di operazioni insert, update e delete
e poi annullare il lavoro (riportando le tabelle alla situazione in cui erano all’inizio) con questo
comando:
rollback;
rollback complete
savepoint A;
savepoint B;
L’output mostra i cinque vecchi record più le tre nuove righe che sono state aggiunte. Ora, si
annulli solamente l’ultimo inserimento:
rollback to savepoint B;
Se ora si prova a interrogare la tabella COMFORT con una query, si noterà che l’ultimo
inserimento è stato annullato, mentre gli altri sono ancora presenti:
select * from COMFORT
where Citta = ‘WALPOLE';
Gli ultimi due record non sono stati ancora confermati; per indurre una conferma di questi
record è necessario eseguire un comando commit oppure un altro comando. È ancora possibile
annullare il secondo inserimento (to savepoint A) oppure tutti gli inserimenti (tramite un coman-
do rollback).
commit implicito
Le azioni che fanno in modo che si verifichi un commit, anche senza alcuna istruzione esplicita,
sono quit, exit (l’equivalente di quit), e qualsiasi comando del linguaggio DDL (Data Definition
Language). Utilizzare uno di questi comandi significa eseguire automaticamente un commit.
Rollback automatico
Se è già stata completata una serie di operazioni di inserimento, aggiornamento o cancellazione
che però non è stata ancora confermata esplicitamente o implicitamente e si incorre in serie
difficoltà, come un problema al computer, Oracle annulla automaticamente qualsiasi operazione
non confermata. Se il computer o il database si bloccano, Oracle effettua il rollback la prossima
volta che il database viene richiamato.
MODIFICA DEI DATI: INSERT, UPDATE, MERGE E DELETE 271
COMFORT_TEST avrà più record per ogni record presente in COMFORT: la colonna Misura
avrà dei valori come “Mezzanotte”, “Mezzogiorno” e “Precipitazione” che consentono di me-
morizzare un maggior numero di misurazioni per ciascuna città in ogni data campione.
Ora, si popoli la tabella COMFORT_TEST con dati presi da COMFORT, senza specificare
condizioni:
insert ALL
into COMFORT_TEST (Citta, DataCampione, Misura, Valore)
values (Citta, DataCampione, 'MEZZOGIORNO', Mezzogiorno)
into COMFORT_TEST (Citta, DataCampione, Misura, Valore)
values (Citta, DataCampione, 'MEZZANOTTE', Mezzanotte)
into COMFORT_TEST (Citta, DataCampione, Misura, Valore)
values (Citta, DataCampione, 'PRECIPITAZIONE', Precipitazione)
select Citta, DataCampione, Mezzogiorno, Mezzanotte, Precipitazione
from COMFORT
where Citta = 'KEENE';
12 rows created.
Questa query comunica a Oracle di inserire più righe per ogni riga restituita dalla tabella
COMFORT. La query su COMFORT restituisce quattro righe. La prima clausola into inserisce il
valore di Mezzogiorno, insieme a una stringa di testo, “MEZZOGIORNO”, nella colonna Misu-
ra. La seconda clausola into inserisce il valore Mezzanotte, mentre la terza inserisce il valore
Precipitazione, come mostrato nella query su COMFORT_TEST che segue l’inserimento:
12 rows selected.
Cosa sarebbe accaduto se al posto della parola chiave all fosse stata utilizzata la parola
chiave first? A meno che non si utilizzino delle clausole when, non è possibile usare la parola
chiave first. L’esempio seguente mostra l’uso della clausola when per limitare il numero di
inserimenti eseguiti nel comando di inserimenti multipli. Per questo esempio, viene utilizzata la
parola chiave all:
insert FIRST
when Mezzogiorno > 27 then
into COMFORT_TEST (Citta, DataCampione, Misura, Valore)
values (Citta, DataCampione, "MEZZOGIORNO', Mezzogiorno)
when Mezzanotte > 21 then
into COMFORT_TEST (Citta, DataCampione, Misura, Valore)
values (Citta, DataCampione, 'MEZZANOTTE', Mezzanotte)
when Precipitazione is not null then
into COMFORT_TEST (Citta, DataCampione, Misura, Valore)
values (Citta, DataCampione, 'PRECIPITAZIONE', Precipitazione)
select Citta, DataCampione, Mezzogiorno, Mezzanotte, Precipitazione
from COMFORT
where Citta = 'KEENE';
6 rows created.
Quali sono le sei righe inserite? I due valori di Mezzogiorno che soddisfano questa condi-
zione:
insert FIRST
when Mezzogiorno > 27 then
into COMFORT_TEST (Citta, DataCampione, Misura, Valore)
values (Citta, DataCampione, 'MEZZOGIORNO', Mezzogiorno)
when Mezzanotte > 21 then
into COMFORT_TEST (Citta, DataCampione, Misura, Valore)
values (Citta, DataCampione, 'MEZZANOTTE', Mezzanotte)
when Precipitazione is not null then
into COMFORT_TEST (Citta, DataCampione, Misura, Valore)
values (Citta, DataCampione, 'PRECIPITAZIONE', Precipitazione)
select Citta, DataCampione, Mezzogiorno, Mezzanotte, Precipitazione
from COMFORT
where Citta = 'KEENE';
4 rows created.
Pertanto è stato inserito il suo valore di Mezzogiorno (37.6). Dato che è stata impiegata la
parola chiave first, e che la condizione valutata per prima (Mezzogiorno) era vera, Oracle non ha
controllato le altre condizioni relative a questa riga. Lo stesso processo si è verificato con le
misure di PRECIPITAZIONE: l’altro valore non NULL di Precipitazione si trovava infatti sullo
stesso record di Mezzogiorno, pari a 29.5.
Cosa sarebbe accaduto se nessuna delle condizioni fosse stata soddisfatta? Per visualizzare
questa opzione si crei una terza tabella, COMFORT2, con la medesima struttura di COMFORT:
274 CAPITOLO 15
Ora, verrà eseguito un inserimento per tutte le città (con la clausola first) e verrà introdotta
una clausola else secondo cui qualsiasi riga non soddisfi le condizioni verrà inserita nella tabella
COMFORT2. Per questo esempio, le condizioni when sono state modificate per limitare il nu-
mero di righe che soddisfano le condizioni:
insert FIRST
when Mezzogiorno > 27 then
into COMFORT_TEST (Citta, DataCampione, Misura, Valore)
values (Citta, DataCampione, 'MEZZOGIORNO, Mezzogiorno)
when Mezzanotte > 35 then
into COMFORT_TEST (Citta, DataCampione, Misura, Valore)
values (Citta, DataCampione, 'MEZZANOTTE', Mezzanotte)
when Precipitazione > 100 then
into COMFORT_TEST (Citta, DataCampione, Misura, Valore)
values (Citta, DataCampione, 'PRECIPITAZIONE', Precipitazione)
else
into COMFORT2
select Citta, DataCampione, Mezzogiorno, Mezzanotte, Precipitazione
from COMFORT
where Citta = 'KEENE';
4 rows created.
Il risultato indica quante righe sono state create, ma non in quale tabella sono state inserite.
Il totale indicato riguarda tutti gli inserimenti. In questo caso, due record sono stati inseriti in
COMFORT_TEST e altri due in COMFORT2 a causa della presenza della condizione else:
15.4 delete
La rimozione di una o più righe da una tabella richiede il comando delete, come mostrato negli
esempi dell’ultimo paragrafo. La clausola where è essenziale per eliminare solo le righe desi-
derate. delete senza una clausola where svuota completamente la tabella. Il comando seguente
elimina le voci relative a Walpole dalla tabella COMFORT:
Ovviamente, una clausola where in delete, proprio come in update o select che faccia parte
di insert, può contenere tutta la logica di una qualsiasi istruzione select e può includere subquery,
unioni, intersezioni e così via. Si può sempre annullare un comando insert, update o delete
errato ma, in realtà, prima di modificare il database, conviene sempre provare con select per
assicurarsi di fare la cosa giusta.
Ora che sono state cancellate le righe dove Citta=‘WALPOLE’, si può verificare l’effetto di
delete con una semplice query:
no rows selected
rollback;
Rollback complete
Questo dimostra che il recupero è possibile, purché non si sia verificato un commit. Nel caso
in cui le modifiche siano state confermate, si potrebbero utilizzare delle query flashback (Capi-
tolo 27) per recuperare i dati.
Un altro comando utilizzato per cancellare record, truncate, non si comporta come delete.
Mentre delete consente di confermare o annullare la cancellazione, truncate elimina automatica-
mente tutti i record dalla tabella. L’azione del comando truncate non può essere annullata o
confermata; i record troncati sono irrecuperabili e non è possibile ricorrere a una query flashback
per vedere i dati che sono stati troncati. Per ulteriori dettagli, consultare la voce truncate nel
Capitolo 48.
276 CAPITOLO 15
15.5 update
update richiede di impostare valori specifici per ogni colonna che si desidera modificare e di
specificare su quale riga o su quali righe si intende operare utilizzando una clausola where co-
struita attentamente:
1 row updated.
4 rows selected.
Cosa si può fare se si scopre che il termometro utilizzato a Keene riporta le temperature
costantemente aumentate di un grado? Si possono anche svolgere calcoli, funzioni di stringa e
qualsiasi altra funzione legittima nell’impostazione di un valore per update (proprio come per
insert o per la clausola where in delete). Nell’esempio seguente, tutte le temperature di Keene
sono state ridotte di un grado:
4 rows updated.
4 rows selected.
Anche qui, come in delete, la clausola where è fondamentale. Senza di essa, viene aggiorna-
ta ogni riga della tabella. Con una clausola where costruita in modo non corretto, verranno
aggiornate le righe errate, spesso in modo difficile da scoprire o correggere, soprattutto se l’opera-
zione è stata confermata con un commit. Quando si effettuano degli aggiornamenti, conviene
sempre utilizzare l’impostazione set feedback on ed esaminare il risultato per assicurarsi che il
numero di righe aggiornate sia quello previsto. È poi utile effettuare una query sulle righe dopo
l’aggiornamento per controllare se si sono verificati i cambiamenti previsti.
1 row updated.
4 rows selected.
Quando si utilizza una subquery con un comando update, occorre assicurarsi che essa non
restituisca più di un record per ognuno dei record aggiornati, altrimenti l’aggiornamento falli-
sce. Per maggiori dettagli sulle query correlate, si rimanda al Capitolo 13.
Inoltre, è possibile utilizzare un’istruzione select incorporata per aggiornare più colonne
contemporaneamente. Le colonne devono essere racchiuse fra parentesi e separate da una virgo-
la, come mostrato di seguito:
1 row updated.
278 CAPITOLO 15
Ed ecco il risultato:
4 rows selected.
1 row updated.
Con COMFORT2 utilizzata come origine di dati, è possibile eseguire un’unione con il co-
mando merge sulla tabella COMFORT. Per le righe che corrispondono alle voci ‘21-MAR-03' e
‘22-DEC-03' verranno aggiornati i valori di Mezzogiorno di COMFORT. Le righe che esistono
solamente in COMFORT2 (per esempio, ‘16-MAY-03') verranno inserite in COMFORT. Il lista-
to seguente illustra il comando da usare:
3 rows merged.
L’output indica il numero di righe elaborate dalla tabella sorgente, ma non dice nulla riguar-
do il numero delle righe inserite o aggiornate. È possibile visualizzare le modifiche eseguendo
una query su COMFORT (si notino i record di Mezzogiorno=12.7):
Si analizzi il comando per capire come si è arrivati a questo risultato. Nella prima linea,
viene nominata la tabella di destinazione e le viene assegnato un alias, C1:
Nelle due linee successive, la clausola using fornisce i dati di origine per l’unione, e alla
sorgente viene assegnato l’alias C2:
La condizione per l’unione viene quindi specificata nella clausola on. Se i valori Citta e
DataCampione dei dati di origine corrispondono a quelli nella tabella di destinazione, i dati
verranno aggiornati. La clausola when matched then, seguita da un comando update, indica a
Oracle quali colonne aggiornare nella tabella sorgente:
Se non esiste alcuna corrispondenza, allora si dovrebbe inserire la riga, come specificato
nella clausola when not matched:
È possibile usare il comando merge per semplificare le operazioni in cui vengono inserite e
aggiornate molte righe tratte da un’unica sorgente. Come avviene per tutte le operazioni update,
si dovrà prestare molta attenzione a utilizzare le clausole where appropriate nella clausola using
dei comandi merge.
NOTA Non è possibile aggiornare una colonna cui si fa riferimento nella clausola
condizionale on.
Nel comando merge è possibile specificare una clausola update, una clausola insert o en-
trambe.
Per inserire tutte le righe di origine nella tabella, è possibile utilizzare un predicato di filtro
costante nella condizione della clausola on. Un esempio di predicato di filtro costante è on
(0=1). Oracle riconosce tale predicato ed effettua un inserimento non condizionale di tutte le
righe di origine nella tabella. Se viene fornito un predicato di filtro costante, non viene effettuata
alcuna unione join durante il comando merge.
A partire da Oracle Database 10g è possibile includere una clausola delete nella parte update
del comando merge. Questa clausola (con la propria clausola where) può cancellare nella tabella
di destinazione le righe che vengono aggiornate da merge. La clausola delete…where valuta il
valore aggiornato, non quello originale nella tabella di destinazione. Se una riga della tabella di
destinazione soddisfa la condizione delete…where ma non è inclusa nell’insieme di righe su cui
agisce merge (in base a quanto definito dalla condizione on), non viene cancellata. Ecco un
esempio:
MODIFICA DEI DATI: INSERT, UPDATE, MERGE E DELETE 281
DECODE e CASE:
if, then ed else in SQL
L
a funzione DECODE è senza dubbio una delle più potenti nel
linguaggio SQL di Oracle. Si tratta di una delle varie estensioni aggiunte da Oracle al linguaggio
SQL standard. Questo capitolo analizzerà diversi modi di impiegare DECODE, tra cui la crea-
zione di report a “campi incrociati”. In Oracle sono disponibili anche le funzioni CASE e
COALESCE che servono per eseguire test logici complessi nelle istruzioni SQL.
Questo è un capitolo complesso e l’argomento è difficile. Gran parte degli argomenti illu-
strati non sono necessari per la grande maggioranza dei report e possono essere tralasciati se
vanno al di là delle proprie esigenze. Si tratta tuttavia di materiale importante nel caso in cui
occorra effettuare complesse operazioni di realizzazione di report e di programmazione.
DECODE(valore,if1,then1,if2,then2,if3,then3,... . . ,else)
Qui valore rappresenta qualsiasi colonna di una tabella (a prescindere dal tipo di dati) o qualsiasi
risultato di un calcolo, come una data meno un’altra, una funzione SUBSTR su una colonna di
caratteri, un numero moltiplicato per un altro e così via; valore viene controllato in ogni riga: se
è uguale a if1, il risultato di DECODE è then1, se è uguale a if2, il risultato è then2, e così via per
tutte le coppie if-then che si possono costruire. Se valore non è uguale a nessuno degli if, il
risultato è else. Ciascuno degli if, then ed else può essere una colonna o il risultato di una funzio-
ne o di un calcolo. Tra parentesi è possibile racchiudere fino a 255 elementi.
284 CAPITOLO 16
Si consideri la cronologia dei prestiti per i libri della biblioteca, così come è stata registrata
nella tabella BIBLIOTECA_PRESTITO:
Esaminando questa lista di controllo, si noterà che alcuni libri sono stati presi in prestito per
un periodo di tempo abbastanza lungo. Per evidenziare i lettori che hanno tenuto i libri più a
lungo, si può ordinare questo elenco in base al numero dei giorni in cui una persona ha tenuto il
libro:
Il problema è rappresentato da alcuni lettori in particolare, oppure da alcuni tipi di libri che
per essere letti richiedono più tempo? Sono molte le variabili coinvolte in questa questione e
analizzarle singolarmente potrebbe portare a decisioni sbagliate. Qual è il numero medio di
giorni di prestito per i libri di ogni categoria?
select B.NomeCategoria,
MIN(BC.DataRestituzione-BC.DataPrestito) MinOut,
MAX(BC.DataRestituzione-BC.DataPrestito) MaxOut,
AVG(BC.DataRestituzione-BC.DataPrestito) AvgOut
from BIBLIOTECA_PRESTITO BC, BIBLIOTECA B
where BC.Titolo = B.Titolo
group by B.NomeCategoria;
Questo tentativo è più utile, ma non produce una reale analisi dell’impatto su queste catego-
rie prodotto dalle diverse persone che hanno in prestito i libri. Per ottenere questo risultato, si
potrebbe eseguire un altro raggruppamento, ma sarà più semplice se si crea un report a campi
incrociati. Il listato seguente genera un report che mostra il prestito minimo, massimo e medio
per persona per categoria. Questa query usa la funzione DECODE per eseguire i calcoli. Per le
finalità di questo esempio vengono utilizzati tre utenti della biblioteca.
select B.NomeCategoria,
MAX(DECODE(BC.Nome, 'FRED FULLER',
BC.DataRestituzione-BC.DataPrestito,NULL)) MaxFF,
AVG(DECODE(BC.Nome, 'FRED FULLER',
BC.DataRestituzione-BC.DataPrestito,NULL)) AvgFF,
MAX(DECODE(BC.Nome, 'DORAH TALBOT',
BC.DataRestituzione-BC.DataPrestito,NULL)) MaxDT,
AVG(DECODE(BC.Nome, 'DORAH TALBOT',
BC.DataRestituzione-BC.DataPrestito,NULL)) AvgDT,
MAX(DECODE(BC.Nome, 'GERHARDT KENTGEN',
BC.DataRestituzione-BC.DataPrestito,NULL)) MaxGK,
AVG(DECODE(BC.Nome, 'GERHARDT KENTGEN',
BC.DataRestituzione-BC.DataPrestito,NULL)) AvgGK
286 CAPITOLO 16
Ora l’output mostra le persone che hanno preso i libri in prestito nella parte superiore: il
periodo massimo di prestito per Fred Fuller è la colonna MaxFF, per Dorah Talbot è la colonna
MaxDT e per Gerhardt Kentgen è la colonna MaxGK. L’output rivela che per la categoria
SaggiAdulti il periodo medio di prestito è il più lungo per ciascuna delle persone indicate e che
nel caso di Gerhardt Kentgen è significativamente più lungo rispetto alla sua media nelle altre
categorie di libri letti.
Come è stato prodotto questo report? Nella query, il raggruppamento è stato fatto per
NomeCategoria. La query sulla colonna MaxFF è mostrata di seguito:
select B.NomeCategoria,
MAX(DECODE(BC.Nome, 'FRED FULLER',
BC.DataRestituzione-BC.DataPrestito,NULL)) MaxFF,
DECODE esegue un controllo di tipo if-then sui dati: se (if) il valore della colonna BC.Nome
in una riga è ‘FRED FULLER', allora (then) calcola la differenza tra la DataRestituzione e la
DataPrestito, altrimenti (else) restituisce un valore NULL. Questo elenco di valori viene quindi
valutato, e viene restituito il valore massimo. Un gruppo simile di operazioni restituisce il peri-
odo medio di prestito per Fred Fuller:
NOMECATEGORIA
-----------
NARRADULTI
SAGGIADULTI
CONSADULTI
NARRRAGAZZI
SAGGIRAGAZZI
ILLUSRAGAZZI
DECODE E CASE: IF, THEN ED ELSE IN SQL 287
Per sostituire questi nomi, si potrebbe unire tramite join BIBLIOTECA a CATEGORIA e
selezionare CategoriaPrincipale e CategoriaSecondaria dalla tabella CATEGORIA. Se la lista
delle categorie è statica, si potrebbe evitare il join con la tabella CATEGORIA ed eseguire la
sostituzione con la funzione DECODE, come mostrato nel listato seguente. Si osservi che DECODE
supporta più combinazioni if-then in un’unica chiamata.
select distinct
DECODE(NomeCategoria,'NARRADULTI','Narrativa Adulti',
'SAGGIADULTI','Saggi Adulti',
'CONSADULTI','Consultazione Adulti',
'NARRRAGAZZI','Narrativa Ragazzi',
'SAGGIRAGAZZI','Saggi Ragazzi',
'ILLUSRAGAZZI','Illustrati Ragazzi',
NomeCategoria)
from BIBLIOTECA;
DECODE(NOMECATEGORIA,
--------------------
Narrativa Adulti
Saggi Adulti
Consultazione Adulti
Narrativa Ragazzi
Saggi Ragazzi
Illustrati Ragazzi
In questo caso, i dati sono statici; per i dati volatili, l’impostazione immutabile delle conver-
sioni nel codice dell’applicazione non sarebbe una pratica di programmazione accettabile. La
tecnica proposta in questo esempio è utile per i sistemi di elaborazione delle transazioni in cui si
cerca di ridurre al minimo il numero di chiamate al database. In questo esempio, per modificare
‘SAGGIADULTI’ in ‘Saggi Adulti’ non è necessario accedere al database; la modifica avviene
nella chiamata alla funzione DECODE. Si osservi che se vengono trovate altre categorie, la
condizione else della funzione DECODE restituisce il valore della colonna CategoriaNome ori-
ginale.
Per i libri delle categorie Adulti si deve aumentare il numero dei giorni di ritardo consentiti
a 21. In questo modo, non cambierà il numero dei giorni di prestito, ma soltanto il calcolo nella
colonna GiorniRitardo. Dato che NomeCategoria non è una colonna delle tabella
BIBLIOTECA_PRESTITO, questa modifica richiede anche l’aggiunta della tabella BIBLIO-
TECA alla clausola from.
Nella clausola select, la logica della query per la colonna GiorniRitardo è la seguente:
DECODE E CASE: IF, THEN ED ELSE IN SQL 289
DECODE(SUBSTR(NomeCategoria,1,5), 'ADULTI',
BC.DataRestituzione-BC.DataPrestito -21,
BC.DataRestituzione-BC.DataPrestito -14 ) GiorniRitardo
Nel formato if-then-else di DECODE, questo significa che “Se gli ultimi sei caratteri della
colonna NomeCategoria corrispondono alla stringa “ADULTI”, allora si deve sottrarre 21 dal
numero dei giorni di ritardo; altrimenti, si deve sottrarre 14”. Il calcolo della colona TassaRitardo
utilizza una logica simile. La clausola where usa DECODE per stabilire il valore di limitazione
per le righe restituite: per i libri della categoria ADULTI, il numero concesso è 21; altrimenti, 14:
Ora, si aggiunga un’altra regola: per i libri della categoria Narrativa adulti, la mora di ritardo
sarà esattamente il doppio di quella prevista per gli altri libri per adulti. Dall’ultima query, il
calcolo per TassaRitardo è:
DECODE(SUBSTR(NomeCategoria,-1,6), 'ADULTI',
(BC.DataRestituzione-BC.DataPrestito –21)*0.30,
(BC.DataRestituzione-BC.DataPrestito -14)*0.20 ) TassaRitardo
La nuova regola richiede una verifica di categoria ulteriore nella funzione DECODE già
eseguita. Di seguito viene mostrato il nuovo calcolo per TassaRitardo:
DECODE(SUBSTR(NomeCategoria,-1,6), 'ADULTI',
DECODE(SUBSTR(NomeCategoria,-7,4),'NARR',
(BC. DataRestituzione-BC.DataPrestito –21)*0.60,
(BC. DataRestituzione-BC.DataPrestito –21)*0.30),
(BC. DataRestituzione-BC.DataPrestito -14)*0.20 ) TassaRitardo
È possibile annidare funzioni DECODE in altre funzioni DECODE per supportare la logica
complessa nei processi di elaborazione dei dati. Per esempio, si potrebbe decidere di visualizzare
una colonna se ha un valore non NULL, e una seconda colonna se la prima è NULL. Con DECODE,
ovvero una semplice chiamata di funzione:
se Colonna1 è NULL, viene restituita Colonna2; altrimenti, viene restituito il valore non NULL di
Colonna1. Per eseguire una logica simile, si può usare anche NVL o le funzioni COALESCE e
NULLIF.
COALESCE restituisce il primo valore non NULL che incontra in un elenco di valori. L’esem-
pio di DECODE precedente potrebbe essere riscritto in questo modo:
COALESCE(Colonna1, Colonna2)
NOTA COALESCE può accettare più di due argomenti, mentre ciò non vale per NVL.
DECODE(SUBSTR(NomeCategoria,-1,6), 'ADULTI',
DECODE(SUBSTR(NomeCategoria,-7,4),'NARR',
(BC. DataRestituzione-BC.DataPrestito –21)*0.60,
(BC. DataRestituzione-BC.DataPrestito –21)*0.30),
(BC. DataRestituzione-BC.DataPrestito -14)*0.20 ) TassaRitardo
DECODE E CASE: IF, THEN ED ELSE IN SQL 291
DECODE(SIGN(
DECODE(SUBSTR(NomeCategoria,-1,6), 'ADULTI',
DECODE(SUBSTR(NomeCategoria,-7,4),'NARR',
(BC.DataRestituzione-BC.DataPrestito –21)*0.60,
(BC.DataRestituzione-BC.DataPrestito –21)*0.30),
(BC.DataRestituzione-BC.DataPrestito -14)*0.20 ) –4),
1,
DECODE(SUBSTR(NomeCategoria,-1,6), 'ADULTI',
DECODE(SUBSTR(NomeCategoria,-7,4),'NARR',
(BC.DataRestituzione-BC.DataPrestito –21)*0.60,
(BC.DataRestituzione-BC.DataPrestito –21)*0.30),
(BC.DataRestituzione-BC.DataPrestito -14)*0.20 ),
0) TassaRitardo
Partendo da una base semplice, questa serie di chiamate alle funzioni DECODE consente di
applicare una logica molto complessa nei calcoli di TassaRitardo. La prima funzione DECODE
valuta il segno del risultato della funzione DECODE successiva quando a esso viene sottratto 4.
Se questo numero è positivo, viene restituita la tassa di ritardo calcolata; altrimenti, viene resti-
tuito 0. Il listato seguente mostra questo calcolo e l’output ottenuto:
È possibile eliminare la visualizzazione delle prime quattro righe (con le tasse di ritardo pari
a 0) modificando in modo analogo la clausola where.
select distinct
DECODE(NomeCategoria,'NARRADULTI','Narrativa Adulti',
'SAGGIADULTI','Saggi Adulti',
'CONSADULTI','Consultazione Adulti',
'NARRRAGAZZI','Narrativa Ragazzi',
'SAGGIRAGAZZI','Saggi Ragazzi',
'ILLUSRAGAZZI','Illustrati Ragazzi',
NomeCategoria)
from BIBLIOTECA;
select distinct
CASE NomeCategoria
when 'NARRADULTI' then 'Narrativa Adulti'
when 'SAGGIADULTI' then 'Saggi Adulti'
when 'CONSADULTI' then 'Consultazione Adulti'
when 'NARRRAGAZZI' then 'Narrativa Ragazzi'
when 'SAGGIRAGAZZI' then 'Saggi Ragazzi'
when 'ILLUSRAGAZZI' then 'Illustrati Ragazzi'
else NomeCategoria
end
from BIBLIOTECA;
CASECATEGORYNAMEWHEN
--------------------
Narrativa Adulti
Saggi Adulti
Consultazione Adulti
Narrativa Ragazzi
Saggi Ragazzi
Illustrati Ragazzi
DECODE(SUBSTR(NomeCategoria,-1,6), 'ADULTI',
DECODE E CASE: IF, THEN ED ELSE IN SQL 293
(BC.DataRestituzione-BC.DataPrestito –21)*0.30,
(BC.DataRestituzione-BC.DataPrestito -14)*0.20 ) TassaRitardo
CASE SUBSTR(NomeCategoria,-1,6)
when 'ADULTI' then (BC.DataRestituzione-BC.DataPrestito –21)*0.30
else (BC.DataRestituzione-BC.DataPrestito -14)*0.20
end
La seconda regola (i libri della categoria NARRADULTI hanno tasse di ritardo doppie)
richiede un comando CASE annidato:
CASE SUBSTR(NomeCategoria,-1,6)
when 'ADULTI' then
CASE SUBSTR(NomeCategoria,-7,4)
when 'NARR' then (BC.DataRestituzione-BC.DataPrestito –21)*0.60
else (BC.DataRestituzione-BC.DataPrestito –21)*0.30
end
else (BC.DataRestituzione-BC.DataPrestito -14)*0.20
end
Questo risultato è più complesso, ma seguire la logica è davvero molto semplice, e in genere
è anche più facile da gestire rispetto a quella della clausola DECODE equivalente. Ora si consi-
deri la condizione finale: se la tassa di ritardo calcolata è minore o uguale a •4, si deve ottenere
0. Dato che si utilizza la funzione CASE, non è necessario ricorrere a una€ funzione SIGN: è
sufficiente usare un confronto “<” durante l’elaborazione del comando. L’esempio seguente mostra
come aggiungere questo controllo: viene aggiunta un’altra funzione CASE, e la chiamata alla
funzione CASE interna viene racchiusa tra parentesi. Il risultato viene confrontato con •4:
CASE when
(CASE SUBSTR(NomeCategoria,-1,6)
when 'ADULTI' then
CASE SUBSTR(NomeCategoria,-7,4)
when 'NARR' then (BC.DataRestituzione-BC.DataPrestito –21)*0.60
else (BC.DataRestituzione-BC.DataPrestito –21)*0.30
end
else (BC.DataRestituzione-BC.DataPrestito -14)*0.20
end)
< 4 then 0
La clausola else per questa chiamata alla funzione CASE è la stessa per l’esecuzione della fun-
zione CASE interna: calcola la tassa di ritardo.
else
CASE SUBSTR(NomeCategoria,-1,6)
when 'ADULTI' then
CASE SUBSTR(NomeCategoria,-7,4)
when 'NARR' then (BC.DataRestituzione-BC.DataPrestito –21)*0.60
else (BC.DataRestituzione-BC.DataPrestito –21)*0.30
end
else (BC.DataRestituzione-BC.DataPrestito -14)*0.20
end
end
294 CAPITOLO 16
Creazione e gestione
di tabelle, viste, indici,
cluster e sequenze
F
inora si è posta particolare attenzione all’utilizzo delle tabel-
le. In questo capitolo si imparerà a creare, eliminare e modificare tabelle, a creare viste e ad
utilizzare opzioni come tabelle di solo indice e tabelle partizionate. Finora sono stati introdotti
diversi comandi create table; questo capitolo conferma questi esempi e mostra come utilizzare
le opzioni più recenti. Verranno inoltre analizzati i comandi per la creazione e la gestione di
viste, indici, cluster e sequenze.
describe STRANO
Le colonne della tabella STRANO rappresentano tre dei principali tipi di dati di Oracle,
VARCHAR2, DATE e NUMBER. Ecco l’istruzione SQL che ha creato questa tabella di Oracle:
296 CAPITOLO 17
NOTA Non si devono racchiudere i nomi di tabelle e colonne tra virgolette, altri-
menti le maiuscole e le minuscole avrebbero rilevanza, creando gravi problemi agli utenti o agli
sviluppatori.
Per altre opzioni di create table relative alle caratteristiche che si riferiscono agli oggetti,
fare riferimento alla Parte quinta di questo libro.
ERROR at line 1:
ORA-12899: value too large for column "PRATICA"."STRANO"."CITTA"
(actual: 16, maximum: 13)
CREAZIONE E GESTIONE DI TABELLE, VISTE, INDICI... 297
La larghezza massima per le colonne di tipo CHAR (a lunghezza fissa) è di 2.000 caratteri,
mentre le colonne (di caratteri a lunghezza variabile) di tipo VARCHAR2 possono contenere un
massimo di 4.000 caratteri. Quando si assegna la larghezza a una colonna, occorre riservare
spazio sufficiente per tutte le possibilità future. Per esempio, una colonna CHAR(15) per il
nome di una città prima o poi creerà dei problemi. Per cui si dovrà modificare la tabella oppure
troncare o distorcere i nomi di alcune città.
NOTA Non vi è alcuno svantaggio nel definire in Oracle una colonna di VARCHAR2
di grandi dimensioni. Oracle è abbastanza intelligente da non memorizzare spazi vuoti alla fine
di queste colonne. Il nome della città “SAN FRANCISCO”, per esempio, viene memorizzato in
13 spazi anche se la colonna è stata definita come VARCHAR2(50). Se in una colonna non vi è
nulla (NULL), Oracle non vi memorizza alcunché, nemmeno uno spazio vuoto (in realtà memo-
rizza un paio di byte per informazioni di controllo interne al database, ma questo non dipende
dalla dimensione specificata per la colonna). L’unico effetto che si ha nella scelta di una lar-
ghezza di colonna ampia è nella formattazione predefinita di SQL*Plus per le colonne. Infatti,
SQL*Plus crea un’intestazione predefinita di larghezza corrispondente alla definizione di
VARCHAR2.
1 row created.
1 row created.
1 row created.
La prima, la terza e la quarta riga sono state inserite, mentre il secondo inserimento non è
riuscito perché 101.44 supera la precisione impostata nell’istruzione create table, dove Mezzo-
giorno è stata definita come NUMBER(3,1). 3 indica il numero massimo di cifre memorizzate da
Oracle, mentre 1 specifica che una di queste tre cifre è riservata per una posizione a destra del
punto decimale. Pertanto 12.3 è un numero lecito, ma 123.4 non lo è.
Si osservi che in questo caso l’errore è stato causato da 101, non da .44, perché NUMBER(3,1)
lascia disponibili solo due posizioni a sinistra del punto decimale. 44 non produce un errore
“value larger than specified precision” (valore troppo grande rispetto alla precisione specifica-
ta). Infatti, viene arrotondato semplicemente a una sola cifra decimale. Questo comportamento
verrà dimostrato tra breve, tuttavia prima occorre esaminare i risultati di una query delle quattro
righe che si è cercato di inserire:
Tre righe sono state inserite correttamente; manca solo quella che ha creato problemi. Oracle
non ha mai inserito la singola riga relativa all’istruzione insert fallita.
Ora le quattro istruzioni insert vengono completate con successo. Una query può dimostrarlo:
Si esamini la prima istruzione insert. Il valore per Mezzogiorno è 39.99. Nella query è
arrotondato a 40. Mezzanotte nell’istruzione insert vale –1.31, mentre nella query vale –1.3.
Oracle arrotonda il numero in base alla cifra immediatamente a destra della precisione consenti-
ta. La Tabella 17.1 mostra gli effetti della precisione in vari esempi. Per vedere alcuni esempi
della funzione ROUND, si rimanda al Capitolo 9.
La chiave candidata
Una chiave candidata è una combinazione di una o più colonne, i valori delle quali identificano
in modo univoco ciascuna riga di una tabella. Il listato seguente mostra la creazione di un vinco-
lo UNIQUE per la tabella STRANO:
drop table STRANO;
Tabella 17.1 Esempi degli effetti della precisione sui valori inseriti.
NELL’ISTRUZIONE INSERT VALORE REALE NELLA TABELLA
Con precisione NUMBER(4,1)
123.4 123.4
123.44 123.4
123.45 123.5
123.445 123.4
123.4 123
123.44 123
123.45 123
123.445 123
1234.5 1235
123.4 120
123.44 120
123.45 120
123.445 120
125 130
1234.5 1230
123.4 123.4
123.44 123.44
123.45 123.45
123.445 123.445
125 125
1234.5 1234.5
12345.6789012345678 12345.6789012345678
CREAZIONE E GESTIONE DI TABELLE, VISTE, INDICI... 301
La chiave primaria
La chiave primaria di una tabella è una delle chiavi candidate cui vengono assegnate alcune
caratteristiche speciali. Può esistere una sola chiave primaria e una colonna di tale chiave non
può contenere valori NULL:
L’istruzione create table che segue ha lo stesso effetto di quella precedente, eccetto che si
possono avere più vincoli UNIQUE ma solo un vincolo PRIMARY KEY.
Per chiavi primarie o candidate di una sola colonna, si può definire la chiave sulla colonna
con un vincolo di colonna al posto di un vincolo di tabella:
In questo caso, la colonna NomeAutore è la chiave primaria, quindi Oracle creerà un nome
per il vincolo PRIMARY KEY. Questa soluzione non è consigliata se si desidera imporre uno
standard di denominazione comune per le chiavi, come discusso più avanti nel paragrafo “Asse-
gnazione di nomi ai vincoli”.
L’indice associato al vincolo di chiave primaria, AUTORE_PK, verrà inserito nella tablespace
USERS. Per dettagli sulla gestione delle tablespace, si rimanda al Capitolo 20.
NOTA Nella maggior parte delle installazioni predefinite viene creata la tablespace
USERS, che è anche la tablespace predefinita.
La chiave esterna
Una chiave esterna è una combinazione di colonne con valori basati su quelli della chiave prima-
ria di un’altra tabella. Un vincolo di chiave esterna, detto anche vincolo di integrità referenziale,
specifica che i valori della chiave esterna corrispondono ai valori effettivi della chiave primaria
nell’altra tabella. Nella tabella BIBLIOTECA, per esempio, la colonna NomeCategoria fa riferi-
mento ai valori della colonna NomeCategoria nella tabella CATEGORIA:
È possibile fare riferimento a una chiave primaria o unica, anche nella stessa tabella. Tutta-
via, nella clausola references non si può fare riferimento a una tabella di un database remoto. Per
specificare chiavi esterne con più colonne si può utilizzare la forma delle tabelle (impiegata
nell’esempio precedente per creare una PRIMARY KEY sulla tabella STRANO) al posto della
forma delle colonne.
A volte si desidera cancellare le righe dipendenti quando si elimina la riga da cui dipendono.
Nel caso di BIBLIOTECA e CATEGORIA, se si elimina un NomeCategoria da CATEGORIA,
si potrebbe voler rendere NULL i valori della colonna NomeCategoria corrispondente nella ta-
bella BIBLIOTECA. Talvolta, si vuole cancellare l’intera riga. La clausola on delete cascade
aggiunta alla clausola references comunica a Oracle di cancellare la riga dipendente quando
viene cancellata la riga corrispondente nella tabella principale. Questa azione mantiene automa-
ticamente l’integrità referenziale. Per ulteriori informazioni sulle clausole on delete cascade e
references, si legga il paragrafo “Vincoli di integrità” nel Capitolo 48.
Il vincolo di controllo
Molte colonne devono avere valori compresi in un determinato intervallo o che soddisfino parti-
colari condizioni. Con un vincolo di controllo si può specificare un’espressione che dev’essere
sempre vera per ogni riga della tabella. Per esempio, la tabella VALUTAZIONE memorizza le
valutazioni valide; per limitare i valori disponibili oltre i limiti imposti dalla definizione della
colonna si può ricorrere a un vincolo di controllo, come mostrato nel listato seguente:
Un vincolo di controllo a livello di colonna non può fare riferimento a valori in altre righe;
e non può usare le pseudocolonne, come SysDate, User, Currval, Nextval, Level e RowNum. Si
può utilizzare la forma del vincolo di tabella (invece di quella del vincolo di colonna) per fare
riferimento a più colonne in un vincolo di controllo.
CREAZIONE E GESTIONE DI TABELLE, VISTE, INDICI... 303
La clausola constraint del comando create table assegna un nome al vincolo (in questo caso
STRANO_PK). In seguito, si potrà utilizzare questo nome quando si attiva o disattiva il vincolo.
Le tabelle vengono eliminate quando non servono più. In Oracle, il comando truncate con-
sente di rimuovere tutte le righe di una tabella e recuperare spazio per altre operazioni senza
rimuovere la definizione della tabella dal database.
A partire da Oracle Database 10g, le tabelle eliminate mantengono lo spazio che occupava-
no: l’accesso a esse avviene tramite il “cestino”. Per eliminare una tabella e contemporaneamen-
te rimuoverla dal cestino, è necessario usare la clausola purge del comando drop table:
purge recyclebin;
304 CAPITOLO 17
Table truncated.
Il troncamento non può essere annullato. Se esistono trigger che cancellano righe che dipen-
dono da altre righe della tabella, questi non vengono eseguiti dal troncamento. Occorre essere
sicuri di voler davvero effettuare il troncamento, prima di procedere con l’operazione. È possi-
bile scegliere di rilasciare lo spazio di memorizzazione della tabella (con la clausola drop storage,
opzione predefinita) o di mantenerlo (tramite reuse storage).
Vento NUMBER(3)
);
Si ottiene un messaggio di errore perché, logicamente, non è possibile aggiungere una co-
lonna definita come NOT NULL, dato che è vuota quando si cerca di inserirla. Ogni riga nella
tabella avrebbe una nuova colonna vuota definita come NOT NULL.
La clausola add del comando alter table funziona con una colonna NOT NULL se la tabella è
vuota. Tuttavia, in genere non è pratico svuotare una tabella di tutte le sue righe solo per aggiun-
gere una colonna NOT NULL.
L’alternativa consiste nel modificare la tabella aggiungendo inizialmente una colonna senza
la restrizione NOT NULL:
Table altered.
Quindi è necessario riempire la colonna con dei dati per ogni riga (dati validi oppure fittizi,
finché non si ottengono quelli validi):
Table altered.
Si osservi che è stata modificata anche la colonna Citta per ampliarla a 17 caratteri (solo a
scopo dimostrativo). Quando la tabella viene descritta, appare così:
describe STRANO
Qui è possibile vedere gli effetti delle modifiche. Citta ora è ampia 17 caratteri anziché 13.
Condizione è stata aggiunta alla tabella come NOT NULL e (temporaneamente) ha un valore
“SOLE”. È stata aggiunta anche Vento ed è NULL.
Per rendere annullabile una colonna NOT NULL, occorre utilizzare il comando alter table
con la clausola NULL, come mostrato nel listato seguente:
alter table STRANO modify
(Condizione NULL);
Table created.
1 row created.
Table altered.
desc LONGTEST
LONGCOL
------------------------------------
Questo è un valore LONG
NOTA Una volta contrassegnata come “inutilizzata”, una colonna non sarà più
accessibile.
Si possono eliminare più colonne con un solo comando, come mostrato nel listato seguente:
NOTA Quando si eliminano più colonne, non si dovrebbe utilizzare la parola chiave
column del comando alter table, perché causa un errore di sintassi. I nomi delle colonne devono
essere racchiusi tra parentesi, come mostrato nel listato precedente.
Se le colonne eliminate fanno parte di chiavi primarie o di vincoli unici, si dovrà utilizzare
anche la clausola cascade constraints nel comando alter table. Se si elimina una colonna che
appartiene a una chiave primaria, Oracle eliminerà la colonna e l’indice della chiave primaria.
Table created.
NOTA Il comando create table...as select... non funziona se una delle colonne
selezionate utilizza il tipo di dati LONG.
Quando la nuova tabella viene descritta, si scopre che ha “ereditato” le definizioni delle
colonne dalla tabella STRANO. Una tabella creata in questo modo può includere tutte le colon-
ne, utilizzando un asterisco, o un sottoinsieme delle colonne di un’altra tabella. Può includere
anche delle colonne “inventate”, che sono il prodotto di funzioni o la combinazione di altre
colonne, proprio come per una vista. Le definizioni delle colonne di caratteri si adattano alla
dimensione necessaria a contenere i dati nelle colonne inventate. Le colonne NUMBER che
avevano una precisione specificata nella tabella di origine, ma che vengono sottoposte a calcoli
per la creazione di una nuova colonna, nella nuova tabella sono semplicemente colonne NUMBER
con una precisione non specificata. Quando la tabella PIOGGIA_TABELLA viene descritta,
mostra le definizioni delle colonne:
describe PIOGGIA_TABELLA
Quando viene effettuata una query su PIOGGIA_TABELLA, si può vedere che questa con-
tiene proprio le colonne e i dati selezionati dalla tabella STRANO, così come erano quando
PIOGGIA_TABELLA è stata creata:
CITTA PRECIPITAZIONE
------------- --------------
PLEASANT LAKE 3.6
PLEASANT LAKE 1.63
PLEASANT LAKE 1.00003
PLEASANT LAKE 2.4
NOTA Se una delle colonne della query viene generata attraverso una formula, è
necessario specificare un alias di colonna che Oracle utilizzerà come nome di colonna durante
la creazione della tabella.
Si può utilizzare questa tecnica anche per creare una tabella con definizioni di colonne come
quelle della tabella di origine, ma senza righe, costruendo una clausola where che non seleziona
alcuna riga dalla vecchia tabella:
Table created.
Una query su questa tabella mostra che essa non contiene nulla:
no rows selected.
Si può creare una tabella basata su una query senza generare voci redo log (registrazioni
cronologiche delle azioni del database utilizzate durante i ripristini). Per evitare la creazione di
queste voci si utilizza la parola chiave nologging nel comando create table. Quando si evitano in
questo modo le voci redo log, le prestazioni del comando create table migliorano, perché c’è
meno lavoro da svolgere; più è grande la tabella, maggiore è l’impatto. Tuttavia, poiché la crea-
zione della nuova tabella non viene scritta nei file redo log (che registrano le voci redo log), la
tabella non viene ricreata se, dopo un guasto del database, si utilizzano questi file redo log per
ripristinarlo. Di conseguenza, conviene effettuare un backup del database subito dopo l’utilizzo
dell’opzione nologging, se si desidera avere la possibilità di recuperare la nuova tabella.
L’esempio che segue illustra come usare la parola chiave nologging durante la creazione di
tabelle basate su query (per le quali, per default, vengono generate voci redo log):
Table created.
310 CAPITOLO 17
Si osservi la possibilità di specificare nologging a livello della partizione e a livello del LOB.
L’utilizzo di nologging migliora le prestazioni delle operazioni che caricano i dati nella tabella.
Per creare STRANO come tabella di solo indice, è necessario stabilire per essa un vincolo
PRIMARY KEY.
Una tabella di solo indice è appropriata se si accede sempre ai dati di STRANO attraverso le
colonne Città e DataCampione (nelle clausole where delle query). Per ridurre al minimo la quan-
tità di lavoro necessario per la gestione attiva dell’indice, conviene utilizzare una tabella di solo
indice soltanto se i dati sono molto statici. Se i dati della tabella cambiano di frequente, è
consigliabile utilizzare una tabella normale con gli indici appropriati.
In linea di massima, una tabella di solo indice è più efficiente quando la chiave primaria
costituisce una grossa parte delle colonne della tabella. Se la tabella contiene molte colonne ad
accesso frequente che non fanno parte della chiave primaria, la tabella di solo indice dovrà
accedere ripetutamente alla propria area di overflow. Nonostante questo aspetto negativo, si
potrebbe decidere di usare le tabelle di solo indice per sfruttare una caratteristica fondamentale
che non è disponibile con le tabelle standard: la possibilità di utilizzare l’opzione move online
del comando alter table. Questa opzione può essere utilizzata per spostare una tabella da una
tablespace in un’altra mentre a essa accedono le operazioni insert, update e delete. Non è possi-
bile invece usare l’opzione move online per le tabelle partizionate di solo indice. Il partizionamento
viene descritto nel prossimo paragrafo.
CREAZIONE E GESTIONE DI TABELLE, VISTE, INDICI... 311
tablespace PART1_TS,
partition PART2 values less than (MAXVALUE)
tablespace PART2_TS);
Per qualsiasi valore di Categoria minore di ‘B’ (le categorie ADULTI), i record vengono
memorizzati nella partizione chiamata PART1. Questa partizione viene memorizzata nella
tablespace PART1_TS (per maggiori dettagli sulle tablespace si rimanda al Capitolo 20). Qual-
siasi altra categoria viene memorizzata nella partizione PART2. Si noti che nella definizione di
quest’ultima partizione la clausola dell’intervallo è la seguente:
Non è necessario specificare un valore massimo per l’ultima partizione; la parola chiave
MAXVALUE comunica a Oracle di utilizzare la partizione per memorizzare qualsiasi dato non sia
stato memorizzato nelle partizioni precedenti.
Si possono creare più partizioni, ciascuna con un proprio valore superiore. Per ogni partizione,
è necessario specificare solamente il valore massimo dell’intervallo. Il valore minimo viene
determinato implicitamente da Oracle in base alla definizione della partizione precedente.
Oltre alle partizioni a intervallo, Oracle supporta le partizioni hash. Una partizione hash
determina la collocazione fisica dei dati eseguendo una funzione hash sui valori della chiave di
partizione. Nel partizionamento a intervalli, in genere i valori consecutivi della chiave di partizione
vengono memorizzati nella stessa partizione. Nell’hash partitioning, i valori consecutivi della
chiave di partizione generalmente non sono memorizzati nella stessa partizione. L’hash partitioning
distribuisce un insieme di record tra un gruppo di partizioni più ampio rispetto al partizionamento
a intervalli, riducendo le probabilità di conflitti di I/O.
Per creare una partizione hash, al posto della clausola partition by range occorre utilizzare la
clausola partition by hash, come mostrato nel listato seguente:
Si può denominare ogni partizione e specificare la tablespace, proprio come si farebbe per il
partizionamento a intervalli, come mostrato di seguito:
Dopo la linea partition by hash (NomeCategoria), ci sono due opzioni per il formato:
■ Come mostrato nel listato precedente, è possibile specificare il numero di partizioni e di
tablespace da utilizzare:
partitions 2
store in (PART1_TS, PART2_TS);
Questo metodo produce partizioni con nomi creati dal sistema e nel formato SYS_Pnnn. Il
numero delle tablespace specificato nella clausola store in non deve obbligatoriamente essere
uguale al numero delle partizioni. Se si specificano più partizioni che tablespace, le partizioni
verranno assegnate alle tablespace seguendo uno schema circolare.
■ Si possono specificare anche partizioni con nome:
In questo modo, a ogni partizione vengono assegnati un nome e una tablespace, con la pos-
sibilità di usare una clausola di memorizzazione aggiuntiva lob o varray (si consultino i Capitoli
34 e 35). Questo metodo offre un maggior controllo sulle posizioni delle partizioni, oltre al
grande vantaggio di poter specificare nomi significativi per le partizioni.
Partizionamento a elenco
È possibile utilizzare partizioni a elenco al posto del partizionamento a intervalli e di quello
hash. Nel partizionamento a elenco, si indicano a Oracle tutti i valori possibili, e si stabiliscono
le partizioni in cui dovrebbero essere inserite le righe corrispondenti. L’esempio seguente mo-
stra le voci della tabella BIBLIOTECA partizionate a elenco in base ai valori di NomeCategoria:
a intervalli e le partizioni hash. Le partizioni hash possono essere usate insieme a quelle a inter-
valli, creando così partizioni hash delle partizioni a intervalli. Per le tabelle di grandi dimensio-
ni, questo partizionamento composito può rappresentare un modo efficace per separare i dati in
divisioni gestibili e regolabili.
L’esempio seguente crea partizioni a intervalli per la tabella BIBLIOTECA in base ai valori
della colona Titolo, e partizioni hash delle partizioni di Titolo in base ai valori di NomeCategoria:
La tabella BIBLIOTECA avrà partizioni a intervalli in due partizioni, usando gli intervalli
dei valori di Titolo specificati per le partizioni nominate. Per ciascuna di queste partizioni verrà
creata una partizione hash nella colonna NomeCategoria.
Si noti la parola chiave local. In questo comando create index non viene specificato alcun
intervallo, mentre invece la parola chiave local comunica a Oracle di creare un indice distinto
per ogni partizione della tabella BIBLIOTECA_LIST_PART. In BIBLIOTECA_LIST_PART
sono state create due partizioni. Pertanto, questo indice crea due partizioni a indice separate, uno
per ogni partizione di tabella. Dato che esiste un indice per partizione, le partizioni a indice sono
“locali” rispetto alle partizioni.
Si possono creare anche indici “globali”. Un indice globale può contenere valori di più
partizioni.
CREAZIONE E GESTIONE DI TABELLE, VISTE, INDICI... 315
La clausola global in questo comando create index consente di creare un indice non
partizionato (come mostrato in questo esempio) oppure di specificare intervalli per i valori degli
indici diversi dagli intervalli per le partizioni della tabella. Gli indici locali possono essere più
semplici da gestire di quelli globali; tuttavia, gli indici globali possono svolgere controlli di
unicità più veloci di quelli locali (partizionati).
NOTA Non è possibile creare indici globali per le partizioni o per le partizioni
secondarie hash.
Nella sequenza riportata sotto si crea una vista su una tabella già esistente, si rimuove la
tabella e poi si effettua una query sulla vista.
Innanzi tutto, viene creata la vista:
View created.
Table dropped.
View created.
Table altered.
Nonostante la modifica alla tabella di base della vista, quest’ultima è ancora valida, ma la
colonna Attenzione non risulta visibile attraverso essa. Dopo aver modificato la tabella, è neces-
CREAZIONE E GESTIONE DI TABELLE, VISTE, INDICI... 317
sario sostituire la vista affinché la colonna Attenzione sia visibile. Per creare nuovamente una
vista conservando tutti i privilegi che le sono stati concessi, occorre utilizzare il comando create
or replace view, come mostrato nel listato seguente. Questo comando sostituisce il testo di una
vista già esistente con quello della nuova vista, senza influire sulle vecchie concessioni.
View created.
L’utente potrebbe anche inserire o aggiornare record nella tabella STRANO eseguendo que-
ste operazioni sulla vista PIOGGIA_VISTA. Se la vista è basata sul join di più tabelle, la capa-
cità dell’utente di aggiornare i record della vista è limitata; le tabelle di base di una vista non
possono essere aggiornate, a meno che nell’aggiornamento non sia coinvolta una sola tabella e la
chiave primaria completa della tabella aggiornata non sia inclusa nelle colonne della vista.
Per impedire che le tabelle di base vengano modificate attraverso una vista, si può utilizzare
la clausola with read only del comando create view. Se si usa questa clausola quando si crea una
318 CAPITOLO 17
vista, gli utenti potranno selezionare soltanto record dalla vista. Gli utenti non potranno manipo-
lare i record ottenuti dalla vista, anche se questa è basata su una sola tabella:
Si può anche utilizzare un trigger INSTEAD OF per gestire i comandi di manipolazione dei
dati eseguiti sulla vista. Per ulteriori dettagli sui trigger INSTEAD OF, si rimanda al Capitolo 33.
17.8 Indici
Un indice è un concetto semplice. In genere si tratta di un elenco di parole chiave accompagnate
dalla posizione delle informazioni relative a un particolare argomento. Per trovare informazioni
sugli indici, per esempio, occorre cercare la parola “indici” nell’indice analitico di questo libro:
si trova così il numero di questa pagina. La parola “indici” è la chiave, mentre i numeri di pagina
indicano dove localizzare la trattazione degli indici in questo libro.
Benché sia possibile trovare informazioni sugli indici semplicemente sfogliando il libro
finché non si trova questa pagina, questo processo è lento e richiede molto tempo. Poiché l’indi-
ce analitico alla fine del libro è in ordine alfabetico, si può raggiungere velocemente il punto
appropriato nell’indice (senza leggere tutte le voci) nel quale si trova la voce “indici”. Se la
parola cercata non è comune, questa soluzione è sicuramente più rapida che leggere il libro
dall’inizio. Questi stessi principi si applicano agli indici di Oracle. Per esempio, se si cerca un
libro in particolare, si può eseguire una query con una condizione di limitazione sulla colonna
Titolo:
Se la tabella BIBLIOTECA non ha un indice sulla colonna Editore, Oracle dovrà leggere
ogni riga della tabella fino a quando non trova tutti gli editori che corrispondono alla clausola
where della query. Se la tabella è piccola, questo potrebbe non avere conseguenze sulle presta-
zioni. Quando le dimensioni della tabella aumentano, il tempo necessario per restituire all’uten-
te tutte le righe corrispondenti può influire negativamente sulle prestazioni dell’applicazione e
dei processi che essa supporta.
Per velocizzare il recupero dei dati, si può creare un indice sulla colonna Editore. Pertanto,
quando si esegue la stessa query, Oracle cerca per prima cosa nell’indice, che è in ordine, trovan-
do così molto più velocemente l’editore denominato “SCHOLASTIC” (Oracle non legge ogni
voce, ma salta direttamente nelle vicinanze del nome, proprio come si fa quando si consulta
l’indice di un libro). La voce dell’indice fornisce a Oracle la dislocazione esatta nella tabella (e
sul disco) delle righe relative a quell’editore. Il tipo di indice standard in Oracle prende il nome
di indice B*-tree, che mette in corrispondenza i valori delle colonne con i RowID a essi correlati.
L’indicizzazione di una colonna importante (una che probabilmente sarà presente in una
clausola where) in genere velocizza la risposta di Oracle a una query. La creazione di un indice
velocizza anche query in cui due tabelle vengono unite tramite join, se le colonne cui si fa
riferimento (attraverso la clausola where) sono incluse nell’indice. Questi sono i concetti fonda-
mentali per gli indici; il resto del paragrafo mostra un certo numero di caratteristiche aggiuntive
e alcuni problemi relativi agli indici che influiscono sulla loro velocità di funzionamento. Per
informazioni sull’influsso che gli indici esercitano sull’ottimizzazione delle query, si rimanda al
Capitolo 43.
CREAZIONE E GESTIONE DI TABELLE, VISTE, INDICI... 319
Creazione di un indice
La creazione di un indice avviene attraverso il comando create index. Quando si definisce una
chiave primaria o una colonna unica durante le fasi di creazione o gestione di una tabella, Oracle
crea automaticamente un indice unico per supportare questo vincolo. La sintassi completa del
comando create index è mostrata nel Capitolo 48. La forma più utilizzata di questo comando è
la seguente:
dove indice dev’essere un nome unico e seguire le convenzioni di denominazione per le colonne
in Oracle; tabella è semplicemente il nome della tabella su cui viene costruito l’indice e colonna
è il nome della colonna indicizzata.
Gli indici bitmap consentono di creare indici utili sulle colonne con pochissimi valori distin-
ti; per questo occorre leggere il paragrafo “Creazione di indici bitmap” più avanti in questo
capitolo. La parola chiave reverse indica a Oracle di invertire i byte del valore indicizzato, ope-
razione che potrebbe migliorare la distribuzione dell’I/O durante l’inserimento di più valori di
dati sequenziali.
È possibile costruire un indice singolo su più colonne elencando le colonne una di seguito
all’altra, separate da virgole. Per gli esempi seguenti, la tabella BIBLIOTECA_AUTORE è stata
creata senza una chiave primaria:
Imposizione dell’unicità
Nella Parte prima si è spiegato che una serie di tabelle è detta in terza forma normale se tutte le
colonne in ogni riga della tabella dipendono soltanto dalla chiave primaria. Nella tabella BIBLIO-
TECA_AUTORE la chiave primaria è la combinazione delle colonne Titolo e NomeAutore. In
altre tabelle, la chiave primaria può essere un identificativo dei dipendenti, un identificativo dei
clienti, un numero di conto o, in una banca, una combinazione di un numero di filiale e uno di
conto.
In ognuno di questi casi, l’unicità della chiave primaria è fondamentale. In una banca con
numeri di conto duplicati o in un sistema di fatturazione con identificativi di clienti duplicati si
avrebbero gravi problemi, poiché le transazioni verrebbero assegnate a conti appartenenti a per-
sone diverse, ma che hanno la stessa chiave primaria (questo è il motivo per cui i nomi di solito
non sono utilizzati come chiavi primarie: ci sono troppi doppioni). Per evitare questo pericolo, il
database aiuta a impedire la creazione di chiavi primarie duplicate. Oracle offre due soluzioni:
■ Si può garantire l’unicità di una chiave attraverso l’inserimento in indici o vincoli.
■ Si possono utilizzare i generatori di sequenze (trattati più avanti in questo capitolo).
generare anche delle chiavi primarie che si riferiscono proprio a questo vincolo. Se si crea per
primo l’indice unico, sarà sempre possibile creare una chiave primaria sulla tabella: Oracle userà
l’indice già esistente come indice di chiave primaria.
Il listato seguente mostra il comando create index per questo indice a più colonne:
Per creare un vincolo unico, è sufficiente sostituire la clausola create primary key con unique.
Quando si cerca di creare un indice unico su una tabella che contiene già dei dati, il comando non
riuscirà se esistono dei duplicati. Se l’istruzione create unique index riesce, qualsiasi tentativo
futuro di inserire (o aggiornare) una riga che crea un duplicato nella chiave fallisce e si ottiene
come risultato questo messaggio di errore:
ERROR at line 1:
ORA-00001: unique constraint (BIBLIOTECA_AUTORE.BA_PK) violated
Quando si crea un indice, questo richiede dello spazio di memorizzazione. Per dettagli che
riguardano la posizione degli indici creati, si rimanda al paragrafo “Posizionamento di un indice
nel database” più avanti in questo capitolo.
NOTA Gli indici bitmap non devono essere utilizzati per le tabelle coinvolte in
applicazioni di elaborazione delle transazioni in linea a causa dei meccanismi interni impiegati
da Oracle per la loro manutenzione. Occorre limitare il loro uso alle tabelle coinvolte nelle
transazioni batch.
Gli indici bitmap sono appropriati quando vengono impiegate colonne non selettive come
condizioni limitative in una query. Per esempio, se ci sono pochissimi valori Valutazione distinti
in una tabella BIBLIOTECA molto grande, in genere non è possibile creare un indice B*-tree
tradizionale su Valutazione, anche se questa colonna è utilizzata con frequenza nella clausola
where. Tuttavia, Valutazione potrebbe essere in grado di trarre vantaggio da un indice bitmap.
Internamente, un indice bitmap associa i valori distinti delle colonne a ogni record. Per
questo esempio, si supponga che esistono cinque valori di Valutazione (1, 2, 3, 4 e 5) in una
tabella BIBLIOTECA di grandi dimensioni. Dato che esistono cinque valori di Valutazione, ci
saranno anche cinque voci bitmap distinte per l’indice bitmap di Valutazione. Se le prime cinque
righe nella tabella hanno un valore di Valutazione pari a 1, e le cinque righe successive un valore
pari a 2, le voci bitmap di Valutazione sono come quelle mostrate nel listato seguente:
CREAZIONE E GESTIONE DI TABELLE, VISTE, INDICI... 321
Nel listato precedente ciascuna colonna di zeri e di uno rappresenta una riga nella tabella
BIBLIOTECA. Dato che vengono considerate dieci righe, vengono visualizzati altrettanti valori
bitmap. Leggendo la bitmap per Valutazione, i primi cinque record hanno un valore di Valutazio-
ne pari a 1 (i valori “1”), e i cinque successivi no (i valori ‘0’). Esiste una voce bitmap separata
per ogni valore possibile.
L’ottimizzatore di Oracle è in grado di convertire dinamicamente voci di indici bitmap in
RowID durante l’elaborazione delle query. Questa capacità di conversione consente
all’ottimizzatore di utilizzare indici sia su colonne che hanno molti valori distinti (attraverso
indici B*-tree), sia su quelle che hanno pochi valori distinti (attraverso indici bitmap).
Per creare un indice bitmap, occorre utilizzare la clausola bitmap del comando create index,
come mostrato nel listato seguente. Conviene indicare che si tratta di un indice bitmap nel nome,
in modo che possa essere rilevato facilmente durante le operazioni di messa a punto.
Oltre a supportare clausole where e join, gli indici accettano anche le clausole order by e le
funzioni MAX e MIN. In alcuni caso Oracle potrebbe scegliere di effettuare la scansione di un
indice invece di effettuare una scansione completa della tabella. Per ulteriori dettagli sull’impie-
go che l’ottimizzatore fa degli indici, si rimanda al Capitolo 43.
S o una N non va molto bene per un indice tradizionale e potrebbe effettivamente rallentare una
query; un indice bitmap sarebbe una scelta assai migliore per un esempio di questo tipo. Una
colonna con numeri telefonici è un buon candidato per un indice B*-tree. Una colonna con i
prefissi telefonici sarebbe di poca importanza, poiché dipende dalla distribuzione di valori di
prefissi unici nella tabella.
In un indice a più colonne, per prima cosa occorre assicurarsi di collocare la colonna in una
posizione che garantisca un accesso frequente. È possibile sfruttare la caratteristica skip-scan
dell’ottimizzatore per utilizzare indici a più colonne anche se la prima colonna non è citata nella
query. Per esempi sull’uso degli indici, si rimanda al Capitolo 43.
Conviene lasciare senza indici le piccole tabelle, se non per imporre l’unicità della chiave
primaria. Una tabella viene considerata piccola quando occupa un numero talmente ridotto di
blocchi di database che Oracle è in grado di leggere tutti i suoi dati in una sola lettura fisica. Il
numero di blocchi letti nel corso di una lettura fisica viene impostato tramite il parametro di
inizializzazione DB_FILE_MULTIBLOCK_READ_COUNT.
Gli indici bitmap offrono un’alternativa di indicizzazione attuabile per colonne che hanno
pochissimi valori distinti. Gli indici bitmap vengono comunemente utilizzati per colonne di
“flag” che sono limitate a valori come ‘S’ e ‘N’. Gli indici bitmap sono particolarmente efficaci
quando in una query ne sono utilizzati diversi; l’ottimizzatore può valutare velocemente le bitmap
e determinare quali righe soddisfano tutti i criteri per cui gli indici bitmap sono disponibili.
In questo esempio, BA_INDICI è il nome dato alla tablespace creata in precedenza dall’am-
ministratore del database. L’uso dell’opzione tablespace in un’istruzione create index consente
di separare fisicamente le tabelle dagli indici a esse associati.
Quando si crea una chiave primaria o un vincolo unico, Oracle crea automaticamente un
indice per imporre l’unicità. A meno che non si specifichi diversamente, l’indice viene creato
nella stessa tablespace della tabella cui si applica il vincolo e utilizza i parametri per la
memorizzazione predefiniti per quella tablespace. Dal momento che la locazione dell’area di
memorizzazione è spesso inadeguata, conviene utilizzare la clausola using index quando si cre-
ano chiavi primarie e vincoli unici.
La clausola using index consente di specificare i parametri di memorizzazione e la locazione
della tablespace per un indice creato da un vincolo. Nell’esempio seguente, viene creata una
chiave primaria sulla tabella BIBLIOTECA_AUTORE e viene collocata nella tablespace
BA_INDICI. Questo esempio presuppone che nelle colonne specificate non esista alcun indice.
Per ulteriori opzioni relative alla clausola using index si può consultare la voce “Vincoli di
integrità” nel Capitolo 42. Per le opzioni relative alle prestazioni legate alla creazione di indici si
può consultare la voce dedicata a create index sempre nel Capitolo 48.
Ricostruzione di un indice
Oracle mette a disposizione una funzionalità per la ricostruzione rapida degli indici che consen-
te di ricreare un indice senza dover rimuovere quello già esistente. Al posto della tabella, come
origine di dati per il nuovo indice viene utilizzato l’indice attualmente disponibile. Durante la
ricostruzione dell’indice è possibile cambiarne i parametri di memorizzazione e l’assegnamento
della tablespace.
Nell’esempio seguente viene ricostruito l’indice BA_PK (attraverso la clausola rebuild). I
suoi parametri di memorizzazione vengono modificati in modo da utilizzare una dimensione di
estensione iniziale pari a 8MB e una dimensione di estensione successiva di 4MB, nella tablespace
BA_INDICI.
Quando si crea un indice basato su colonne precedentemente indicizzate, Oracle può essere
in grado di utilizzare gli indici già esistenti come origine di dati per quello nuovo. L’ottimizzatore
di Oracle può utilizzare parti di indici composti esistenti per le query, pertanto potrebbe non
essere necessario creare molti indici a supporto delle query più comuni.
324 CAPITOLO 17
È possibile ricostruire gli indici mentre vi si accede tramite la clausola rebuild online del
comando alter index.
'MIO REGISTRO';
Questa query invece potrebbe, poiché non esegue la funzione UPPER sulla colonna Titolo:
Si possono creare indici che permettono agli accessi tramite indice di supportare accessi
basati sulle funzioni. Invece di creare un indice sulla colonna Titolo, si può creare un indice
sull’espressione della colonna SUPERIORE(Titolo), come mostrato nel listato seguente:
Anche se gli indici basati sulle funzioni possono essere utili, è opportuno considerare queste
domande quando si creano indici di questo tipo:
■ Esiste la possibilità di limitare le funzioni che verranno utilizzate sulla colonna? In caso
affermativo, si può impedire che tutte le funzioni vengano eseguite sulla colonna?
■ Si ha spazio di memoria sufficiente per altri indici?
■ Quando si rimuove la tabella, con essa vengono rimossi più indici (e di conseguenza più
extent) di prima? In che modo questo influisce sul tempo necessario per rimuovere la tabella?
Gli indici basati su funzioni sono utili, tuttavia andrebbero implementati con parsimonia.
Più indici si creano su una tabella, più lente saranno le operazioni di inserimento, aggiornamento
e cancellazione.
17.9 Cluster
La creazione di cluster è un metodo per memorizzare tabelle che sono strettamente correlate, e
spesso unite tramite join nella stessa area sul disco. Per esempio, invece di porre la tabella BI-
BLIOTECA in una sezione del disco e la tabella BIBLIOTECA_AUTORE in un’altra, si potreb-
bero inserire le loro righe in una stessa area, chiamata cluster. La chiave di cluster è la colonna,
o le colonne, con cui le tabelle sono in genere unite tramite join in una query (per esempio Titolo
per le tabelle BIBLIOTECA e BIBLIOTECA_AUTORE). Si possono unire in un cluster solo
tabelle di cui si è proprietari.
La sintassi di base del comando create cluster è la seguente:
Il nome del cluster (cluster) segue le convenzioni di denominazione delle tabelle, mentre
colonna e tipodati sono rispettivamente il nome e il tipo di dati della colonna che si vuole utiliz-
zare come chiave di cluster. Il nome della colonna (colonna) può coincidere con quello di una
delle colonne di una tabella che si desidera inserire nel cluster, oppure può essere qualsiasi altro
nome valido. Ecco un esempio:
Cluster created.
Questo codice crea un cluster (uno spazio riservato, come avverrebbe per una tabella) che
non contiene nulla. L’uso di Col1 come nome per la chiave di cluster è irrilevante; infatti, non
verrà più utilizzato. Tuttavia, la sua definizione dovrebbe corrispondere a quella della chiave
primaria della tabella da aggiungere. Successivamente, vengono create delle tabelle da includere
nel cluster:
Prima di inserire delle righe in BIBLIOTECA, è necessario creare un indice del cluster:
Si ricordi che la presenza della clausola cluster preclude l’utilizzo delle clausole tablespace
o storage. È opportuno osservare come questa struttura sia diversa dall’istruzione create table
standard:
Nella prima istruzione create table, la clausola cluster LIBROeAUTORE (Titolo) segue la
parentesi di chiusura che racchiude l’elenco di colonne create nella tabella. LIBROeAUTORE è il
nome del cluster creato precedentemente. Titolo è la colonna di questa tabella che viene memo-
rizzata nella chiave di cluster Col1. È possibile avere più chiavi di cluster nell’istruzione create
cluster e più colonne memorizzate in queste chiavi nell’istruzione create table. Occorre notare
che in nessun punto un’istruzione specifica esplicitamente che la colonna Titolo dovrà essere
memorizzata nella chiave di cluster Col1. L’accoppiamento viene realizzato solo in base alla
posizione: Col1 e Titolo erano entrambi i primi oggetti menzionati nelle rispettive istruzioni
326 CAPITOLO 17
cluster. Colonne e chiavi di cluster multiple sono accoppiate la prima con la prima, la seconda
con la seconda, la terza con la terza e così via. Ora, viene aggiunta al cluster una seconda tabella:
Quando queste due tabelle vengono unite in un cluster, ogni singolo titolo viene memorizzato
solo una volta nella chiave di cluster. A ogni titolo vengono associate le colonne di entrambe le
tabelle.
I dati di queste tabelle sono effettivamente memorizzati in una singola locazione, come se il
cluster fosse una grande tabella che contiene dati ricavati da entrambe le tabelle che lo costitui-
scono.
Un altro tipo di cluster, detto hash cluster, utilizza i valori delle colonne di cluster per deter-
minare la locazione fisica in cui è memorizzata la riga. Per maggiori informazioni si rimanda
alla voce create cluster nel Capitolo 48.
17.10 Sequenze
Con una sequenza è possibile assegnare numeri unici, come identificativi dei clienti, alle colon-
ne del database; non è necessario creare una tabella e del codice particolare per tenere traccia dei
numeri unici utilizzati. Questo si ottiene utilizzando il comando create table, come mostrato di
seguito:
Questo codice crea una sequenza cui si può accedere durante l’esecuzione dei comandi
insert e update (anche select, ma è alquanto raro). Solitamente, il valore di sequenza unico viene
creato con un’istruzione simile a quella seguente:
NextVal associato a IDCliente comunica a Oracle che si desidera il numero della prossima
sequenza disponibile dalla sequenza IDCliente. Questo numero è sicuramente unico; Oracle non
lo assegna a nessun altro. Per usare lo stesso numero più di una volta (come in una serie di
inserimenti in tabelle correlate), CurrVal viene impiegato al posto di NextVal, dopo il primo
utilizzo. In altre parole, l’uso di NextVal garantisce che la tabella della sequenza venga incremen-
tata e che il numero ottenuto sia unico, quindi la prima volta si deve usare NextVal. Dopo aver
utilizzato NextVal, quel numero viene memorizzato in CurrVal per impiegarlo altrove, finché non
si utilizza di nuovo NextVal, e a quel punto sia NextVal sia CurrVal cambiano, assumendo il
valore del nuovo numero della sequenza.
CREAZIONE E GESTIONE DI TABELLE, VISTE, INDICI... 327
Se si utilizza NextVal e CurrVal in una singola istruzione SQL, entrambi contengono il valo-
re recuperato da NextVal. Nessuno di questi può essere impiegato in una subquery, come colonna
nella clausola select di una vista, con DISTINCT, UNION, INTERSECT o MINUS e nelle clausole
order by, group by o having di un’istruzione select.
Si possono anche memorizzare i valori delle sequenze nella cache per un accesso più veloce,
ed è possibile far ripartire il ciclo della sequenza dal valore iniziale quando viene raggiunto il
valore massimo. Per maggiori informazioni si rimanda alla voce create sequence nel Capitolo 48.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 18
Opzioni di base
per la sicurezza di Oracle
L
e informazioni sono vitali per il successo, ma quando sono
danneggiate o si trovano in mani sbagliate, possono nascere gravi problemi. Oracle mette a
disposizione caratteristiche di sicurezza estese per proteggere le informazioni da visualizzazioni
non autorizzate e da danneggiamenti intenzionali o involontari. Questa protezione è fornita con-
cedendo o revocando privilegi persona per persona e privilegio per privilegio, e si aggiunge (pur
restando indipendente) a qualunque tecnologia di sicurezza già presente sul proprio sistema. Per
controllare l’accesso ai dati, Oracle utilizza i comandi create user, create role e grant.
In questo capitolo verranno introdotte le funzionalità di sicurezza di base disponibili in
Oracle. Per la trattazione delle caratteristiche di sicurezza avanzate, come i virtual private database,
si rimanda al Capitolo 19.
Creazione di un utente
Il sistema Oracle viene fornito con molti utenti già creati, tra cui SYSTEM e SYS. L’utente SYS
possiede le tabelle interne più importanti che Oracle usa per gestire il database; SYSTEM invece
330 CAPITOLO 18
possiede altre tabelle e viste. Per creare altri utenti, è possibile collegarsi all’utente SYSTEM,
che ha questo privilegio.
Quando si installa Oracle, per prima cosa è necessario creare personalmente (o con l’aiuto di
un amministratore di sistema) un utente per se stessi. Questa è la sintassi più semplice del co-
mando create user:
Con questo comando è possibile impostare molte altre caratteristiche di un account; per i
dettagli, si rimanda alla voce relativa al comando create user del Capitolo 48.
Per connettere l’ID utente e la password del sistema del proprio computer alla sicurezza di
Oracle, in modo che per gli utenti basati su host sia sufficiente un solo collegamento, occorre
utilizzare “externally” invece di fornire una password. Un amministratore di sistema (che ha
moltissimi privilegi) può desiderare l’ulteriore sicurezza di una password distinta. Negli esempi
seguenti, l’amministratore del sistema viene chiamato Dora:
Ora, Dora ha come password “psyche” invece di “avocado.” Tuttavia, Dora non può colle-
garsi al proprio account fino a quando non possiede il privilegio di sistema CREATE SESSION:
Più avanti in questo capitolo verranno proposti altri esempi sulle concessioni di privilegi di
sistema.
■ Il numero di tentativi di connessione consecutivi falliti che sono consentiti prima che l’account
venga automaticamente “bloccato”.
■ Il numero di giorni in cui l’account rimane bloccato.
■ Il numero di giorni che devono trascorrere prima di poter riutilizzare una password.
■ Il numero di cambiamenti di password che devono verificarsi prima di poter riutilizzare una
password.
Altre caratteristiche per la gestione delle password consentono di imporre una lunghezza e
una complessità minime per le password.
Per modificare la password, oltre al comando alter user è possibile utilizzare il comando
password in SQL*Plus. Se si usa questo comando, la nuova password non compare sullo scher-
mo mentre la si digita. Gli amministratori di database possono modificare la password di qualsi-
asi altro utente con il comando password; gli altri utenti invece possono cambiare solo la propria
password.
Quando si digita il comando password, vengono richieste la nuova e la vecchia password,
come mostrato nel listato seguente:
connect dora/psyche
password
Changing password for dora
Old password:
New password:
Retype new password:
Una volta che la password è stata cambiata con successo il sistema avvisa con il messaggio:
Password changed
password dora
Changing password for dora
New password:
Retype new password:
Nel listato seguente viene creato il profilo LIMITED_PROFILE che dovrà essere utilizzato
dall’utente JANE:
332 CAPITOLO 18
connect jane/eyre
ERROR:
ORA-28000: the account is locked
Per sbloccare l’account, è necessario ricorrere alla clausola account unlock del comando
alter user (dall’account di un DBA), come mostrato nel listato seguente:
Una volta sbloccato l’account, sarà di nuovo possibile connettersi all’account JANE. Con la
clausola account lock del comando alter user è possibile bloccare un account manualmente.
NOTA È possibile specificare account lock come parte del comando create user.
In questo esempio, il comando alter profile viene utilizzato per modificare il profilo
LIMITED_PROFILE. Il valore PASSWORD_LIFE_TIME viene impostato a 30, quindi la
password di qualsiasi account utilizzi questo profilo scadrà dopo 30 giorni. Se la password è
scaduta, la si dovrà cambiare la prima volta che si cerca di connettersi, a meno che il profilo non
preveda un periodo di proroga per le password scadute. Il parametro del periodo di proroga
prende il nome di PASSWORD_GRACE_TIME. Se la password non viene modificata entro
questo periodo, l’account scade.
Per attivare nuovamente un account scaduto, è necessario eseguire il comando alter user. In
questo esempio, il DBA fa scadere manualmente la password di JANE:
User altered.
connect jane/eyre
ERROR:
ORA-28001: the password has expired
Si possono anche obbligare gli utenti a modificare le password la prima volta che accedono
ai propri account, grazie alla clausola password expire del comando create user. Tuttavia, il
comando create user non consente di impostare una data di scadenza per la nuova password
impostata dall’utente; per poterlo fare, si deve utilizzare il parametro di profilo PASSWORD_LI-
FE_TIME mostrato negli esempi precedenti.
Per visualizzare la data di scadenza della password di qualsiasi account, è necessario esegui-
re una query sulla colonna Expiry_Date della vista del dizionario dati DBA_USERS. Gli utenti
che desiderano visualizzare la data di scadenza della password dei propri account possono ese-
guire una query sulla colonna Expiry_Date della vista del dizionario dati USER_USERS (con
SQL*Plus oppure con uno strumento di query basato su client).
Se ora l’utente JANE cerca di riutilizzare una password recente, il tentativo di modificare la
password non riuscirà. Per esempio, si supponga che JANE modifichi la propria password, come
nella linea seguente:
JANE non può riutilizzare nessuna delle password recenti e dovrà quindi inventarsene una
nuova.
Ruoli standard
All’inizio del capitolo è stato creato un utente denominato Dora. Ora che Dora ha un account,
che cosa può fare in Oracle? A questo punto ancora nulla, in quanto dispone soltanto del privile-
gio di sistema CREATE SESSION. In molti casi gli utenti delle applicazioni ricevono i privilegi
attraverso i ruoli. È possibile raggruppare i privilegi di sistema e gli accessi agli oggetti in ruoli
ritagliati sulle necessità degli utenti dell’applicazione. È possibile creare dei ruoli personalizzati
per l’accesso alle applicazioni e utilizzare i ruoli predefiniti di Oracle per alcune necessità di
accesso al sistema. Ecco un elenco dei ruoli standard più importanti prodotti durante la creazio-
ne di un database:
CONNECT, RESOURCE e DBA vengono forniti per garantire una certa compatibilità con
il passato e non devono essere più utilizzati. CONNECT dà agli utenti la possibilità di connetter-
si e di eseguire le funzioni base. Gli utenti con CONNECT possono creare tabelle, viste, sequen-
ze, cluster, sinonimi e database link. Gli utenti con RESOURCE possono creare tabelle, sequen-
ze, procedure, trigger, tipi di dati, operatori, tipi di indice, indici e cluster personalizzati. Gli
utenti con il ruolo RESOURCE ricevono inoltre il privilegio di sistema UNLIMITED
TABLESPACE, che consente loro di ignorare le quote su tutte le tablespace. Gli utenti con il
ruolo DBA possono eseguire funzioni di amministrazione del database, come creare e modifica-
re utenti, tablespace e oggetti.
Invece di ricorrere a CONNECT, RESOURCE e DBA, occorre creare dei ruoli personalizzati
dotati dei privilegi necessari per l’esecuzione di privilegi di sistema specifici. Nei paragrafi se-
guenti si vedrà come concedere privilegi a utenti e ruoli.
Revoca di privilegi
I privilegi concessi possono anche essere annullati. Il comando revoke è simile al comando
grant:
Una persona con ruolo DBA può revocare CONNECT, RESOURCE, DBA o qualsiasi altro
privilegio o ruolo a chiunque altro, compreso un altro DBA. Ciò naturalmente è pericoloso,
quindi i privilegi DBA dovrebbero essere concessi con cautela e solo a una stretta minoranza di
persone per cui sono realmente necessari.
NOTA Se a un utente vengono revocate tutte le concessioni, esso non viene co-
munque eliminato da Oracle, né vengono distrutte le tabelle da lui create; gli viene semplice-
mente proibito di accedervi. Altri utenti con accesso alle tabelle possono accedervi esattamente
come prima.
336 CAPITOLO 18
Per rimuovere un utente e tutte le risorse da lui possedute, occorre utilizzare il comando
drop user:
L’opzione cascade rimuove l’utente con tutti gli oggetti da lui posseduti, compresi i vincoli
di integrità referenziale. Questa opzione rende non più validi viste, sinonimi, stored procedure,
funzioni o package che si riferiscono a oggetti presenti nello schema dell’utente rimosso. Se non
si usa l’opzione cascade ed esistono ancora oggetti posseduti dall’utente, Oracle non rimuove
l’utente e restituisce invece un messaggio di errore.
User created.
Grant succeeded.
User created.
Grant succeeded.
User altered.
Questa sequenza di comandi consente sia a Judy sia a Bob di connettersi a Oracle e concede
a Bob qualche capacità in più. Ma questi utenti possono fare qualcosa con le tabelle di Dora?
Non senza un accesso esplicito.
Per concedere ad altri utenti l’accesso alle proprie tabelle, occorre fare ricorso a una seconda
forma del comando grant:
FLASHBACK
INSERT
UPDATE (tutte le colonne o solo colonne specifiche)
DELETE
SELECT
I privilegi INSERT, UPDATE e DELETE possono essere concessi sulle viste materializzate
solo se queste ultime sono aggiornabili. Per dettagli sulla creazione delle viste materializzate, si
rimanda al Capitolo 24.
■ Sulle tabelle è possibile concedere anche quanto segue:
■ Sulle procedure, funzioni, package, tipi di dati astratti, librerie, tipi di indici e operatori:
EXECUTE
DEBUG
■ Sulle sequenze:
SELECT
ALTER
READ
WRITE
UNDER (per la capacità di creare viste secondarie in una vista, oppure tipi secondari in un
tipo)
Quando si esegue una procedura o una funzione di un altro utente, in genere la si esegue
utilizzando i privilegi del suo proprietario. Questo significa che non è necessario un accesso
esplicito ai dati utilizzati dalla procedura o funzione; si vedono solo i risultati dell’esecuzione,
non i dati di base. Inoltre, si possono creare stored procedure che vengono eseguite con i privile-
gi dell’utente invocante e non del proprietario della procedura; per i dettagli si rimanda al Capi-
tolo 31.
Dora concede a Bob l’accesso SELECT alla tabella COMFORT:
338 CAPITOLO 18
Grant succeeded.
La clausola with grant option del comando grant permette a chi riceve la concessione di
trasmettere i privilegi ricevuti ad altri utenti. Se Dora concede privilegi sulle sue tabelle all’uten-
te Bob con with grant option, quest’ultimo può fare concessioni sulle tabelle di Dora ad altri
utenti (Bob può solo trasmettere i privilegi che gli sono stati concessi, come SELECT). Se si ha
intenzione di creare delle viste basate sulle tabelle di un altro utente, e di concedere l’accesso a
queste viste ad altri utenti, innanzi tutto è necessario avere un accesso with grant option alle
tabelle di base.
connect Bob/carolyn
Connected.
Una volta connessa, Dora può effettuare selezioni dalla tabella su cui ha concesso a Bob
l’accesso SELECT.
NOTA A meno che non si utilizzi un sinonimo, il nome della tabella dev’essere
preceduto dal nome utente del proprietario, altrimenti Oracle comunica che la tabella non esiste.
Viene creata una vista chiamata COMFORT, che è una semplice selezione completa della
tabella Dora.COMFORT:
View created.
OPZIONI DI BASE PER LA SICUREZZA DI ORACLE 339
Una selezione da questa vista produce esattamente gli stessi risultati di una selezione dalla
tabella Dora.COMFORT:
Ora, Dora ritorna al proprio nome utente e crea una vista che seleziona soltanto una parte
della tabella COMFORT:
connect Dora/psyche
Connected.
View created.
Successivamente concede a Bob i privilegi SELECT e UPDATE su questa vista e gli revoca
(attraverso il comando revoke) tutti i privilegi sulla tabella COMFORT:
Grant succeeded.
Revoke succeeded.
Dora poi si connette di nuovo al nome utente di Bob per verificare gli effetti di questo
cambiamento:
connect Bob/carolyn
Connected.
Il tentativo di effettuare selezioni dalla vista COMFORT non riesce, perché la tabella di base
per questa vista di Bob è Dora.COMFORT. Ovviamente, un tentativo di selezione dalla tabella
Dora.COMFORT produce esattamente lo stesso messaggio. Poi viene effettuato un tentativo di
selezione da Dora.QUALCHECOMFORT:
340 CAPITOLO 18
Questa query funziona perfettamente, anche se l’accesso diretto alla tabella COMFORT era
stato revocato, perché Dora ha concesso a Bob l’accesso a una parte di COMFORT attraverso la
vista QUALCHECOMFORT. È solo la parte della tabella relativa a KEENE.
Questo esempio mette in luce una potente caratteristica di sicurezza di Oracle: la possibilità
di creare viste utilizzando praticamente qualsiasi restrizione si desideri o qualsiasi calcolo nelle
colonne, per poi concedere ad altri utenti l’accesso alla vista, invece che alle tabelle di base. Gli
utenti sono in grado di vedere solo le informazioni presentate dalla vista. Il meccanismo può
essere esteso in modo che sia specifico per ogni utente. Più avanti in questo capitolo, nel para-
grafo “Sicurezza con User” verrà fornita una spiegazione dettagliata di questa caratteristica.
Ora viene creata la vista POCOCOMFORT sulla vista QUALCHECOMFORT, sotto il nome
utente di Bob:
View created.
1 row updated.
Quando viene effettuata una query sulla vista POCOCOMFORT, saranno visibili gli effetti
dell’aggiornamento:
Una query di Dora.QUALCHECOMFORT mostrerebbe gli stessi risultati, come anche una
query di COMFORT effettuata da Dora nel proprio nome utente. L’aggiornamento si è avuto
anche sulla tabella di base, nonostante sia stato effettuato attraverso due viste (POCOCOMFORT
e QUALCHECOMFORT).
create synonym
Un metodo alternativo alla creazione di una vista che include un’intera tabella o una vista di un
altro utente consiste nel creare un sinonimo:
Questo sinonimo può essere trattato esattamente come una vista. Per informazioni, si riman-
da al comando create synonym nel Capitolo 48.
A Bob non sono stati concessi da Dora i privilegi DELETE, pertanto il tentativo non riesce.
Passaggio di privilegi
Bob può concedere ad altri utenti l’autorità per accedere alle sue tabelle, ma non può assegnare
ad altri l’accesso a tabelle che non gli appartengono. In questo esempio, tenta di concedere a
Judy l’autorità INSERT:
Dato che Bob non ha questa autorità, non riesce a trasmetterla a Judy. Successivamente, Bob
cerca di trasmettere un privilegio di cui dispone, SELECT:
Non può concedere neanche questo privilegio, perché la vista QUALCHECOMFORT non
gli appartiene. Se gli fosse stato concesso l’accesso a QUALCHECOMFORT con with grant
option, il comando grant precedente avrebbe avuto successo. La vista POCOCOMFORT gli
appartiene, quindi Bob può cercare di trasmettere l’autorità su questa vista a Judy:
ERROR at line 1:
ORA-01720: grant option does not exist for ‘DORA.QUALCHECOMFORT’
Dato che POCOCOMFORT si basa su una delle viste di Dora, e a Bob non è stato concesso
SELECT with grant optino su questa vista, la concessione di Bob non riesce.
342 CAPITOLO 18
In aggiunta viene creata una nuova tabella posseduta da Bob e caricata con le informazioni
correnti della vista POCOCOMFORT:
create table NOCOMFORT as
select * from POCOCOMFORT;
Table created.
Grant succeeded.
Dall’account di Judy vengono effettuate delle query sulla tabella per la quale Bob ha con-
cesso a Judy il privilegio SELECT:
connect Judy/sarah
select * from Bob.NOCOMFORT;
Questa concessione è riuscita. È stata creata la tabella NOCOMFORT dal nome utente di
Bob, che quindi la possiede. Egli è stato quindi in grado di concedere l’accesso a questa tabella.
Se Dora vuole che Bob possa trasmettere i suoi privilegi ad altri, può aggiungere un’altra
clausola all’istruzione grant:
connect Dora/psyche
Grant succeeded.
Questo messaggio che appare non fa alcun cenno al fatto che non si ha il privilegio di acces-
so; in tal modo un utente che non ha il permesso di effettuare una query su una tabella non saprà
neppure che questa esiste.
Creazione di un ruolo
Oltre ai ruoli predefiniti mostrati in precedenza nel capitolo, in Oracle esiste la possibilità di
creare ruoli propri. I ruoli creati possono comprendere privilegi di tabelle o di sistema o una
combinazione di entrambi. I paragrafi seguenti mostrano come creare e amministrare i ruoli.
OPZIONI DI BASE PER LA SICUREZZA DI ORACLE 343
Per creare un ruolo, è necessario avere il privilegio di sistema CREATE ROLE. La sintassi
per la creazione di un ruolo è mostrata nel listato seguente:
Un ruolo appena creato non è associato ad alcun privilegio. Le opzioni di password per i
ruoli sono trattate nel paragrafo “Aggiunta di una password a un ruolo” più avanti nel capitolo.
Ecco due esempi di comandi create role:
Il primo comando crea un ruolo denominato IMPIEGATO, che verrà usato negli esempi dei
prossimi paragrafi di questo libro. Il secondo comando crea un ruolo denominato MANAGER,
anch’esso utilizzato in questi esempi.
Come mostrato in questo esempio, il nome del ruolo sostituisce nel comando grant il nome
utente. Il privilegio di effettuare selezioni dalla tabella COMFORT è ora disponibile per tutti gli
utenti del ruolo IMPIEGATO.
Un DBA, o chi ha il ruolo di sistema GRANT ANY PRIVILEGE, può concedere ai ruoli
privilegi di sistema come CREATE SESSION, CREATE SYNONYM e CREATE VIEW. Questi
privilegi saranno quindi utilizzabili da ogni utente del ruolo.
La possibilità di collegarsi al database è concessa attraverso il privilegio CREATE SESSION.
Nell’esempio seguente, questo privilegio viene concesso al ruolo IMPIEGATO. Questo privile-
gio viene concesso anche al ruolo MANAGER, insieme al privilegio di sistema CREATE VIEW.
NOTA Le concessioni non possono essere circolari, quindi ora non è possibile
concedere MANAGER a IMPIEGATO.
344 CAPITOLO 18
In questo esempio, il ruolo IMPIEGATO viene concesso al ruolo MANAGER. Anche se non
si è concesso direttamente alcun privilegio di tabella al ruolo MANAGER, esso eredita tutti i
privilegi concessi al ruolo IMPIEGATO. La disposizione dei ruoli in questo modo è abbastanza
comune nelle organizzazioni gerarchiche.
Quando si concede un ruolo a un altro ruolo (o ad un utente, come viene spiegato nel para-
grafo seguente) si può utilizzare la clausola with admin option, come illustra il listato seguente:
grant IMPIEGATO to MANAGER with admin option;
NOTA I privilegi concessi agli utenti attraverso ruoli non possono essere utilizza-
ti come base per viste, procedure, funzioni, package o chiavi esterne. Quando si creano questi
tipi di oggetti del database, occorre concedere direttamente i privilegi necessari.
È possibile concedere un ruolo a un utente attraverso il comando grant, come mostrato nel-
l’esempio seguente:
grant IMPIEGATO to Bob;
In questo esempio, l’utente Bob ha tutti i privilegi concessi al ruolo IMPIEGATO (ossia i
privilegi CREATE SESSION e SELECT su COMFORT).
Quando si concede un ruolo a un utente, si può utilizzare la clausola with admin option, come
mostrato nel listato seguente:
grant MANAGER to Dora with admin option;
Dora ha ora l’autorità di concedere il ruolo MANAGER ad altri utenti o ruoli, oppure di
modificare e rimuovere il ruolo.
Ogni volta che un utente cerca di attivare questo ruolo, viene richiesta la password. Se tutta-
via questo ruolo è impostato come ruolo predefinito per l’utente, quando l’utente si connette,
non viene richiesta alcuna password. Per ulteriori dettagli su questi argomenti si rimanda al
paragrafo “Attivazione e disattivazione di ruoli” di questo capitolo.
OPZIONI DI BASE PER LA SICUREZZA DI ORACLE 345
I ruoli possono anche essere legati ai privilegi del sistema operativo. Se il sistema operativo
prevede questa possibilità, allora si può utilizzare la clausola identified externally del comando
alter role. Quando il ruolo viene attivato, Oracle controlla il sistema operativo per verificare
l’accesso. Nell’esempio seguente viene mostrato come modificare il ruolo per sfruttare questa
caratteristica di sicurezza:
Nella maggior parte dei sistemi UNIX il processo di verifica impiega il file denominato /etc/
group. Per utilizzare questo file in qualsiasi sistema operativo, il parametro OS_ROLES di avvio
del database nel file init.ora dovrà essere impostato a TRUE.
L’ esempio seguente mostra questo processo di verifica per un’istanza del database chiamata
“Local” su un sistema UNIX. Il file /etc/group del server può contenere la voce seguente:
ora_local_manager_d:NONE:1:dora
Questa voce concede il ruolo MANAGER all’account Dora. Il suffisso “_d” indica che que-
sto ruolo dev’essere concesso per default quando Dora si connette. Un suffisso “_a” avrebbe
indicato che questo ruolo doveva essere attivato with admin option. Se questo ruolo fosse anche
quello predefinito per l’utente, il suffisso sarebbe stato “_ad”. Se questo ruolo fosse stato con-
cesso a più di un utente, si sarebbero dovuti aggiungere i nomi utente alla voce di /etc/group,
come mostrato nel listato seguente:
ora_local_manager_d:NONE:1:dora,judy
Se si applica questa opzione, i ruoli nel database verranno attivati attraverso il sistema ope-
rativo.
NOTA Il numero massimo di ruoli che si possono attivare per un utente viene
impostato con il parametro di inizializzazione del database MAX_ENABLED_ROLES.
Come mette in luce questa sintassi, un utente può essere modificato in modo da avere attiva-
ti, per default, ruoli specifici, tutti i ruoli, tutti i ruoli tranne quelli specifici oppure nessun ruolo.
Per esempio, il seguente comando alter user attiva il ruolo IMPIEGATO ogni volta che Bob si
connette:
Per attivare un ruolo non predefinito, occorre utilizzare il comando set role, come mostrato
in questo esempio:
set role IMPIEGATO;
Per vedere quali ruoli sono abilitati nella sessione corrente, occorre effettuare una selezione
dalla vista del dizionario dati SESSION_ROLES. Un query su SESSION_PRIVS consente di
vedere quali sono i privilegi di sistema attualmente abilitati.
Si possono utilizzare anche le clausole all e all except che erano disponibili nel comando
alter user:
Se un ruolo è associato a una password, questa dev’essere specificata attraverso una clausola
identified by:
Per disattivare un ruolo nella propria sessione, occorre utilizzare il comando set role none,
come mostrato nel listato seguente. Questo disattiva tutti i ruoli nella sessione corrente. Dopo
che tutti i ruoli sono stati disattivati, occorre attivare di nuovo quelli che si desiderano.
set role none;
Dato che potrebbe essere necessario eseguire ogni tanto un comando set role none, è
preferibile concedere agli utenti il privilegio CREATE SESSION direttamente invece che attra-
verso i ruoli.
Ora, gli utenti del ruolo IMPIEGATO non possono più effettuare query sulla tabella
COMFORT.
Eliminazione di un ruolo
Per eliminare un ruolo, occorre utilizzare il comando drop role, come mostrato nell’esempio
seguente:
OPZIONI DI BASE PER LA SICUREZZA DI ORACLE 347
I ruoli specificati, e i privilegi loro associati, verranno rimossi completamente dal database.
La concessione e la revoca di privilegi di sistema e di oggetto ha effetto immediato. Le conces-
sione e la revoca di ruoli vengono osservate solo quando un utente corrente impartisce un co-
mando set role o quando viene avviata una sessione per un nuovo utente.
NOME SUBSTR(TITOLO,1,30)
------------------------- ------------------------------
JED HOPKINS INNUMERACY
GERHARDT KENTGEN WONDERFUL LIFE
DORAH TALBOT EITHER/OR
EMILY TALBOT ANNE OF GREEN GABLES
PAT LAVAY THE SHIPPING NEWS
ROLAND BRANDT THE SHIPPING NEWS
ROLAND BRANDT THE DISCOVERERS
ROLAND BRANDT WEST WITH THE NIGHT
EMILY TALBOT MIDNIGHT MAGIC
EMILY TALBOT HARRY POTTER AND THE GOBLET OF
PAT LAVAY THE MISMEASURE OF MAN
DORAH TALBOT POLAR EXPRESS
DORAH TALBOT GOOD DOG, CARL
GERHARDT KENTGEN THE MISMEASURE OF MAN
FRED FULLER JOHN ADAMS
FRED FULLER TRUMAN
JED HOPKINS TO KILL A MOCKINGBIRD
DORAH TALBOT MY LEDGER
GERHARDT KENTGEN MIDNIGHT MAGIC
Per consentire a ogni utente che prende un libro in prestito di accedere alla tabella, restrin-
gendo però l’accesso a una vista costituita soltanto dalla propria riga, si potrebbero creare 19
viste distinte, ciascuna con nomi differenti nella clausola where e si potrebbero effettuare con-
cessioni separate di queste viste per ogni persona. In alternativa, si può creare una vista la cui
clausola where contiene User, la pseudocolonna, in questo modo:
User created.
Grant succeeded.
Grant succeeded.
connect jed/hop
Connected.
NOME
-------------------------
TITOLO
---------------------------------------------------------
DATAPREST DATAREST
--------- ---------
JED HOPKINS
INNUMERACY
01-JAN-02 22-JAN-02
JED HOPKINS
TO KILL A MOCKINGBIRD
15-FEB-02 01-MAR-02
Ogni volta che si effettua una query su MIO_PRESTITO, si otterranno dei record che dipen-
dono dai valori della pseudocolonna User, ossia dall’utente di SQL*Plus la cui vista viene sotto-
posta a query.
Questo dà l’accesso a tutti, compresi gli utenti creati dopo che questa concessione è stata
effettuata. Tuttavia, ogni utente continuerà ad accedere alla tabella utilizzando come prefisso il
nome utente del proprietario. Per evitare questo, un DBA potrebbe creare un sinonimo pubblico
(un nome accessibile a tutti gli utenti che sostituisce Pratica.MIO_PRESTITO).
La quota di spazio di un utente può essere stabilita quando l’utente viene creato, attraverso
il comando create user. Se si desidera eliminare i limiti nella quota di spazio di un utente, si può
concedere all’utente il privilegio di sistema UNLIMITED TABLESPACE. Per ulteriori dettagli
su questi comandi, è possibile consultare le voci relative ai comandi create user e alter user nel
Capitolo 48.
Anche i profili possono essere utilizzati per imporre limiti di altre risorse, come la quantità
di tempo CPU o il tempo di inattività che può essere necessario per le richieste di un utente a
Oracle. Viene creato un profilo che descrive dettagliatamente questi limiti di risorse e poi viene
assegnato a uno o più utenti. Per i dettagli completi, si consultino le voci dei comandi create
profile e alter user nel Capitolo 48.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Parte terza
AVANZATE
CARATTERISTICHE
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 19
Sistemi di protezione
avanzati: virtual private
database
N
ei capitoli precedenti si è visto come utilizzare le viste per
migliorare la sicurezza visualizzando solo le righe che rispondono a particolari criteri. In questo
capitolo si vedrà come utilizzare un Virtual Private Database (VPD) per offrire una protezione a
livello di record nelle tabella delle applicazioni. In VPD i criteri di protezione vengono collegati
direttamente a tabelle, viste e sinonimi in modo che gli utenti non abbiano modo di aggirare le
impostazioni di sicurezza.
In un VPD qualunque istruzione SQL utilizzata per accedere a una tabella, vista o sinonimo
protetti da un criterio VPD viene modificata dinamicamente in modo da includere una condizio-
ne di limitazione: una clausola where o una clausola and. La modifica avviene in modo traspa-
rente e l’utente vede solo i dati che passano la condizione limitante specificata nella clausola
where. Questo accesso capillare permette di avere un notevole controllo su tutti gli accessi alle
tabelle delle applicazioni. I criteri VPD possono essere applicati ai comandi select, insert, update,
index e delete. È possibile dar vita a diversi criteri di protezione per ciascun tipo di accesso: uno
per gli inserimenti, un altro per le selezioni e così via.
A partire da Oracle Database 10g, la tecnologia VPD è stata estesa per includere i VPD a
livello di colonna, nei quali i criteri di protezione vengono applicati solo quando si accede a delle
colonne particolari. Oracle Database 10g permette inoltre il mascheramento delle colonne, in
cui le colonne protette possono essere visualizzate con valori NULL se le loro righe vengono
restituite. Oltre a ciò, le capacità di audit sono state potenziate in modo che i DBA possano
effettuare un controllo capillare dei comandi select, insert, update e delete.
Dall’account con privilegi SYSDBA creare l’utente PRACTICE (se non esiste già) e asse-
gnargli i privilegi di sistema CREATE ANY CONTEXT e CREATE PUBLIC SYNONYM:
Ora come utente PRACTICE è necessario creare due tabelle: la tabella STOCK_ACCOUNT
e la tabella STOCK_TRX. La prima contiene una riga per ciascun account in grado di effettuare
operazioni azionarie, mentre la tabella STOCK_TRX contiene una riga per ciascuna azione ac-
quistata o venduta dal detentore di quell’account.
connect practice/practice
Una volta create queste tabelle, occorre concedere l’accesso a esse agli utenti ADAMS e
BURLINGTON:
Ora l’applicazione è configurata: lo schema PRACTICE è proprietario della tabella dei dati
(STOCK_TRX) e ha una tabella che può essere utilizzata per mettere in corrispondenza nomi
utente con numeri di account (STOCK_ACCOUNT). Una volta definita questa configurazione,
è possibile creare un contesto di applicazione, come descritto nel paragrafo seguente.
connect PRACTICE/PRACTICE
Poi si crea il package con lo stesso nome (CONTEXT_PACKAGE). Per dettagli sull’uso dei
package, si rimanda al Capitolo 31. Il package è costituito da una singola chiamata a procedura:
Ora che è stata creata l’intestazione del package, si può procedere con la realizzazione del
corpo di quest’ultimo. Il listato che segue illustra il corpo del package che imposterà il contesto
per ciascuna sessione.
DBMS_SESSION.SET_CONTEXT('PRACTICE','SETUP','FALSE');
end SET_CONTEXT;
end CONTEXT_PACKAGE;
/
select Account
into v_id
from STOCK_ACCOUNT
where NomeCompletoAccount = v_user;
La tabella STOCK_ACCOUNT conterrà una riga per ciascun utente (Adams, Burlington e
così via). Questa query prende il nome dell’utente che si è collegato e lo confronta con i valori
della colonna NomeCompletoAccount della tabella STOCK_ACCOUNT. Se c’è una corrispon-
denza, viene restituito il valore di Account. Se non ci sono corrispondenze, un’altra parte del
package restituisce 0 come numero di account. Il valore di Account è impostato come la variabi-
le User_ID per la sessione:
DBMS_SESSION.SET_CONTEXT('PRACTICE','USER_ID', v_id);
Sarà possibile fare riferimento a questo valore di contesto nei propri programmi e le restri-
zioni VPD si baseranno sull’impostazione del contesto.
Ora che il package è stato creato, occorre concedergli accesso pubblico:
Le regole per stabilire il contesto per le sessioni ora sono pronte per essere attivate, come
descritto nel paragrafo che segue.
Ogni volta che un utente si collega, Oracle esegue la procedura SET_CONTEXT nel package
CONTEXT_PACKAGE dell’utente PRACTICE. Tale procedura interrogherà la tabella
STOCK_ACCOUNT per vedere se esiste un numero di account corrispondente; se c’è una cor-
rispondenza, il contesto della sessione verrà modificato per riflettere il valore di Account.
SISTEMI DI PROTEZIONE AVANZATI: VIRTUAL PRIVATE DATABASE 357
connect adams/john7
USERNAME
------------------------------------------------------------
ID
------------------------------------------------------------
ADAMS
1234
L’output della funzione SYS_CONTEXT permette di rendersi conto della potenza della con-
figurazione VPD. Per ciascun utente che si collega, Oracle verificherà la tabella
STOCK_ACCOUNT e utilizzerà il valore di Account corrispondente per impostare un valore
per la variabile User_ID della sessione. In questo caso Oracle ha cercato l’utente ADAMS nella
tabella STOCK_ACCOUNT, ha trovato il suo valore di Account (1234) e ha impostato su questo
valore la variabile User_ID della sessione. Se si dispone di queste informazioni, è possibile
limitare l’accesso alle righe di altre tabelle in base ai dati di Account della tabella
STOCK_ACCOUNT. VPD consente di limitare automaticamente questo accesso senza ricorrere
alla creazione di viste. Ogni volta che un utente tenta di accedere a una tabella, l’accesso può
essere limitato a prescindere dallo strumento utilizzato.
Se ci si collega come utente non elencato nella tabella STOCK_ACCOUNT (innescando
pertanto un’eccezione NO_DATA_FOUND), il valore di User_ID sarà 0, come determinato dal-
la procedura:
connect PRACTICE/PRACTICE
Poi si crea il corpo del package. Le funzioni seguono entrambe lo stesso modello, volto alla
generazione di un predicato che verrà applicato ogni volta che l’utente interroga la tabella
STOCK_TRX. Se il nome utente della sessione è il proprietario della tabella, il predicato è
NULL. Per tutti gli altri utenti verrà valutata la variabile di contesto User_ID, che sarà passata
come condizione di limitazione a qualunque query. L’obiettivo di queste funzioni è la generazio-
ne di un predicato come where Account=1234 da applicare ogni volta che la tabella viene inter-
rogata da un utente.
Dal momento che questo sarà eseguito da tutti gli utenti che accedono alla tabella
STOCK_TRX, occorre concedere agli utenti il privilegio per eseguirlo e creare un sinonimo
pubblico.
begin
DBMS_RLS.ADD_POLICY('PRACTICE', 'STOCK_TRX', 'STOCK_TRX_INSERT_POLICY',
'PRACTICE', 'SECURITY_PACKAGE.STOCK_TRX_INSERT_SECURITY',
SISTEMI DI PROTEZIONE AVANZATI: VIRTUAL PRIVATE DATABASE 359
'INSERT', TRUE);
DBMS_RLS.ADD_POLICY('PRACTICE', 'STOCK_TRX', 'STOCK_TRX_SELECT_POLICY',
'PRACTICE', 'SECURITY_PACKAGE.STOCK_TRX_SELECT_SECURITY',
'SELECT');
end;
/
La procedura ADD_POLICY viene eseguita due volte. Alla prima esecuzione, si specifica
che la funzione STOCK_TRX_INSERT_SECURITY viene eseguita durante i tentativi di inserire
righe nella tabella STOCK_TRX. Alla seconda esecuzione la funzione
STOCK_TRX_SELECT_SECURITY viene applicata alle query della tabella STOCK_TRX. È
possibile avere regole di protezione distinte per le diverse operazioni sulla tabella. Le variabili
passate alla procedura ADD_POLICY sono il nome dello schema, il nome della tabella e il nome
del criterio, il nome dello schema e il nome della funzione per la funzione di protezione e l’ope-
razione interessata.
connect adams/john7
Benché l’utente ADAMS non fornisca una clausola where nella sua query, Oracle ha appli-
cato a quest’ultima un predicato, limitando i risultati alle righe con il valore di Account 1234.
Ma cosa accade se l’utente BURLINGTON tenta di eseguire la stessa query?
connect burlington/newj2
L’utente BURLINGTON vede solo le righe con il valore di Account 7777 in base a quanto
specificato nella riga a lui dedicata nella tabella STOCK_ACCOUNT.
NOTA Dato che la tabella STOCK_ACCOUNT sarà interrogata per ciascun col-
legamento, occorre accertarsi che la query responsabile del recupero dei dati di contesto del-
l’utente sia messa a punto correttamente. Per una panoramica sulle opzioni per la messa a
punto, si veda il Capitolo 43.
360 CAPITOLO 19
E gli altri utenti? Se non sono presenti nella tabella STOCK_ACCOUNT, non possono recu-
perare righe dalla tabella STOCK_TRX:
connect system/manager
no rows selected
Oltre alle selezioni, anche gli inserimenti sono stati limitati dal criterio di protezione; un
utente può inserire righe in STOCK_TRX solo se il valore di Account corrisponde alle
impostazioni di contesto dell’utente. I tentativi di inserire altre righe falliscono:
connect PRACTICE/PRACTICE
grant INSERT on STOCK_TRX to ADAMS;
connect adams/john7
ERROR at line 1:
ORAC-28115: policy with check option violation
L’errore ORA-28115 indica che l’utente ha tentato di inserire una riga che non era in gradi
di selezionare a causa delle impostazioni VPD.
begin
DBMS_RLS.ADD_POLICY
(object_schema=>'PRACTICE',
object_name=>'STOCK_TRX',
policy_name=>'STOCK_TRX_SELECT_POLICY',
function_schema=>'PRACTICE',
policy_function=>'SECURITY_PACKAGE.STOCK_TRX_SELECT_SECURITY',
sec_relevant_cols=>'Prezzo');
end;
/
SISTEMI DI PROTEZIONE AVANZATI: VIRTUAL PRIVATE DATABASE 361
Per default, le righe verranno restituite in base alla funzione del criterio di protezione quan-
do una query fa riferimento alla colonna Prezzo. Per utilizzare l’opzione di mascheramento delle
colonne, occorre indicare a Oracle di restituire tutte le righe impostando il parametro
sec_relevant_cols_opt a DBMS_RLS.ALL_ROWS dopo l’impostazione del parametro
sec_relevant_cols.
Quando viene usata questa versione del criterio, tutte le righe verranno restituite dalla query.
Per le righe che l’utente normalmente non potrebbe vedere, la colonna protetta (Prezzo)
visualizzerà valori NULL. I valori di Prezzo verranno visualizzati per le righe che l’utente può
vedere normalmente.
Il mascheramento delle colonne si applica alle query, non alle operazioni DML. Si osservi
che le proprie applicazioni devono consentire la visualizzazione dei valori NULL nel caso in cui
si adotti il mascheramento delle colonne.
ENABLE_POLICY Abilita (o disabilita) un criterio aggiunto in precedenza a una tabella, una vista o un sinonimo.
A questo punto il criterio viene eliminato, ma il trigger di collegamento verrà sempre ese-
guito a ciascun collegamento. Occorre pertanto ricordarsi di eliminare il trigger (in questo caso
PRACTICE.SET_SECURITY_CONTEXT) in modo che il database non debba fare lavoro su-
perfluo. Se le restrizioni imposte dal VPD non sono più necessarie, è possibile eliminare i package
che impostano il contesto dell’applicazione.
DBMS_RLS.CREATE_POLICY_GROUP (
object_schema VARCHAR2,
object_name VARCHAR2,
policy_group VARCHAR2);
DBMS_RLS.ADD_GROUPED_POLICY(
object_schema VARCHAR2,
object_name VARCHAR2,
policy_group VARCHAR2,
policy_name VARCHAR2,
function_schema VARCHAR2,
policy_function VARCHAR2,
statement_types VARCHAR2,
update_check BOOLEAN,
enabled BOOLEAN,
static_policy IN BOOLEAN FALSE,
policy_type IN BINARY_INTEGER NULL,
SISTEMI DI PROTEZIONE AVANZATI: VIRTUAL PRIVATE DATABASE 363
Per esempio, è possibile dar vita a un gruppo di criterio denominato TRXAUDIT e poi
aggiungervi il criterio STOCK_TRX_SELECT_POLICY:
begin
DBMS_RLS.CREATE_POLICY_GROUP('PRACTICE','STOCK_TRX','TRXAUDIT');
DBMS_RLS.ADD_GROUPED_POLICY('PRACTICE','STOCK_TRX','TRXAUDIT',
'STOCK_TRX_SELECT_POLICY','PRACTICE', 'SECURITY_PACKAGE.STOCK_TRX_SELECT_SECURITY');
end;
/
DBMS_SESSION.SET_CONTEXT('PRACTICE','SETUP','TRUE');
Per i gruppi di criteri, il terzo parametro passato a SET_CONTEXT sarà il nome del gruppo
di criteri. Affinché l’applicazione richiami un gruppo di contesto specifico, occorre riscrivere
CONTEXT_PACKAGE in modo che supporti una terza variabile di input (il gruppo di criteri) e
aggiungerlo all’esecuzione di SET_CONTEXT:
DBMS_SESSION.SET_CONTEXT('PRACTICE','SETUP', gruppo_criteri);
Q
uesto capitolo offre una panoramica generale sull’utilizzo
delle tablespace e sui comandi necessari per crearle e modificarle. Per utilizzare tali comandi, è
indispensabile disporre dei privilegi di amministratore di database. Nel Capitolo 46 sono de-
scritte in dettaglio le procedure per la creazione e la gestione delle tablespace. Scopo di questo
capitolo è introdurre i concetti, presentare le nuove funzionalità e fornire agli sviluppatori le
informazioni necessarie per prendere decisioni di progettazione ponderate relative all’utilizzo
delle tablespace.
spazio, gli viene assegnato l’extent successivo, ovvero un’altra singola area di spazio su disco;
quando ha utilizzato anche questo, gliene viene assegnato un’altro. Il processo continua con
ogni tabella finché l’intera tablespace non è piena. A questo punto, occorre aggiungere un nuovo
file alla tablespace o estenderne i file prima di poter ampliare le tabelle.
In ogni database c’è anche una tablespace SYSTEM la quale contiene il dizionario dati, i
nomi e le posizioni di tutte le tablespace, le tabelle, gli indici e i cluster per il database. Gli
oggetti all’interno della tablespace SYSTEM sono di proprietà degli utenti SYS e SYSTEM;
nessun altro utente deve possedere oggetti in questa tablespace, in quanto ciò potrebbe influire
sul resto del database.
Quando creano una tablespace, gli amministratori di database specificano un metodo per
allocarne lo spazio. Nell’esempio seguente viene creata una tablespace la cui allocazione dello
spazio iniziale è un unico file da 100MB; questo file tuttavia può ingrandirsi automaticamente a
seconda delle necessità:
Questo capitolo concentra la propria attenzione sul modo in cui lo sviluppatore utilizza le
tablespace. Per le opzioni e i comandi dettagliati utilizzati nella creazione delle tablespace, gli
amministratori di database dovrebbero fare riferimento ai Capitoli 46 e 48.
La colonna Contents di USER_TABLESPACES mostra i tipi di oggetti supportati in ciascu-
na tablespace. Di seguito, è mostrato un listato di esempio preso da un’installazione di Oracle
Database 10g:
TABLESPACE_NAME CONTENTS
------------------------------ ---------
SYSTEM PERMANENT
UNDOTBS1 UNDO
SYSAUX PERMANENT
TEMP TEMPORARY
USERS PERMANENT
ossia segmenti creati e gestiti da Oracle per supportare le operazioni di ordinamento. La tablespace
UNDOTBS1 supporta la gestione dei segmenti di undo (fare riferimento ai Capitoli 27 e 28).
Quando si crea una tabella senza specificare una tablespace, questa tabella viene memoriz-
zata nella tablespace predefinita. Si può visualizzare tale impostazione con la vista del diziona-
rio dati USER_USERS:
DEFAULT_TABLESPACE TEMPORARY_TABLESPACE
------------------------------ ------------------------------
USERS TEMP
TABLESPACE_NAME EXTENT_MAN
------------------------------ ----------
SYSTEM LOCAL
UNDOTBS1 LOCAL
SYSAUX LOCAL
TEMP LOCAL
USERS LOCAL
In una tabella gestita a livello locale, la mappa dello spazio della tablespace è conservata
nelle intestazioni dei file di dati della tablespace. Per visualizzare i file di dati allocati per una
tablespace, gli amministratori di database possono eseguire una query sulla vista del dizionario
dati DBA_DATA_FILES; per gli utenti sprovvisti di privilegi, non esiste una vista equivalente.
I valori predefiniti per la memorizzazione dipendono dal sistema operativo. È possibile ese-
guire una query su USER_TABLESPACES per vedere la dimensione del blocco e le impostazioni
368 CAPITOLO 20
select Tablespace_Name,
Block_Size,
Initial_Extent,
Next_Extent,
Min_Extents,
Max_Extents,
Pct_Increase
from USER_TABLESPACES;
Per ridefinire le impostazioni predefinite, si può ricorrere alla clausola storage mentre si
crea una tabella o un indice. Per la sintassi completa, si consulti la voce relativa alla clausola
storage nel Capitolo 48. In genere è opportuno lavorare insieme agli amministratori di database
per definire impostazioni predefinite adatte alle tablespace gestite a livello locale e poi basarsi su
questo ridimensionamento per i propri oggetti. A meno che non ci siano oggetti con requisiti di
spazio eccezionali, conviene evitare di impostare dimensioni personalizzate per ogni tabella e
indice. Se non si specifica una clausola storage quando si crea un oggetto, quest’ultimo utilizze-
rà l’impostazione predefinita della relativa tablespace. Se non si specifica una clausola tablespace,
l’oggetto verrà memorizzato nella tablespace predefinita.
Si può eseguire una query per conoscere lo spazio libero in una tablespace mediante la vista
del dizionario dati USER_FREE_SPACE, che visualizzerà una riga per ogni extent libero adia-
cente all’interno di una tablespace, la sua posizione e lunghezza esatta.
Per ulteriori dettagli, consultare la voce relativa al comando purge nel Capitolo 48 e il Capi-
tolo 28.
I dati contenuti in una tablespace di sola lettura non possono essere modificati. Anche se gli
utenti sprovvisti di privilegi non possono eseguire questi comandi, è opportuno conoscerli in
quanto potrebbero alterare il modo in cui si memorizzano fisicamente i dati. Se è possibile spo-
stare i dati immutati nelle rispettive tablespace, si potrebbe progettare l’intera tablespace come
tablespace di sola lettura. L’utilizzo di tablespace di sola lettura può semplificare i tentativi di
backup e recupero.
Lo stato di sola lettura delle tablespace è visualizzato nella colonna Status della vista del
dizionario dati USER_TABLESPACES, come mostrato nell’esempio seguente:
Tablespace altered.
STATUS
---------
READ ONLY
Tablespace altered.
STATUS
---------
ONLINE
Tablespace temporanee
Quando si esegue un comando che effettua un’operazione di ordinamento o raggruppamento,
Oracle può creare un segmento temporaneo per gestire i dati. Questo segmento temporaneo
viene creato in una tablespace temporanea, e l’utente che esegue il comando non deve preoccu-
parsi di gestire anche i dati. Oracle crea il segmento temporaneo in modo dinamico e rilascia il
370 CAPITOLO 20
suo spazio dopo che l’istanza è stata chiusa e riavviata. Se non c’è spazio temporaneo sufficiente
e i file di dati della tablespace temporanea non sono in grado di allargarsi da soli, il comando
fallisce. A ciascun utente del database è associata una tablespace temporanea, ma potrebbe esi-
sterne solo una condivisa da tutti gli utenti. A livello di database viene impostata una tablespace
temporanea predefinita in modo che tutti gli utenti nuovi abbiano la medesima tablespace tem-
poranea a meno che, durante l’esecuzione del comando create user o alter user, non ne venga
specificata un’altra.
A partire da Oracle Database 10g, è possibile creare più tabelle temporanee e raggrupparle.
Per prima cosa, è necessario assegnare le tablespace temporanee a gruppi di tablespace attraver-
so la clausola tablespace group del comando create temporary tablespace o alter tablespace.
Quindi si può specificare il gruppo come tablespace predefinita di un utente. I gruppi di tablespace
possono aiutare a supportare operazioni parallele che implicano ordinamenti.
è indispensabile spostare la tablespace con le tabelle base degli indici come parte integrante del
medesimo insieme di tablespace trasportabile. Meglio si organizzano e si distribuiscono gli og-
getti tra le tablespace, più facile sarà creare un insieme autonomo di tablespace da trasportare.
Per trasportare le tablespace, è necessario generare un insieme di tablespace, copiarlo o
spostarlo nel database nuovo e infine inserirlo nel nuovo database. Dal momento che si tratta di
operazioni che richiedono determinati privilegi, si deve disporre dei privilegi di amministratore
di database per eseguirle. Uno sviluppatore dovrebbe essere a conoscenza di questa capacità,
poiché può ridurre sensibilmente il tempo richiesto per migrare i dati autonomi tra i database.
Per esempio, si potrebbe creare e popolare una tablespace di sola lettura con dati cronologici in
un ambiente di prova e poi trasportarla in un database di produzione, anche tra piattaforme
diverse. Per ulteriori dettagli sulle modalità per il trasporto delle tablespace, si rimanda al Capi-
tolo 46.
Uso di SQL*Loader
per caricare i dati
N
egli script forniti per le tabelle di esercizio viene eseguito un
grande numero di comandi insert. Al posto di questi inserimenti, si potrebbe creare un file con-
tenente i dati da caricare, quindi usare l’utility SQL*Loader di Oracle per caricarli. Questo
capitolo offre una panoramica sull’impiego di SQL*Loader e sulle sue capacità principali. Nel
Capitolo 22, verranno analizzate altre due utility per lo spostamento di dati, Data Pump Export
e Data Pump Import. SQL*Loader, Data Pump Export e Data Pump Import sono descritte in
dettaglio in Oracle Database Utilities, fornito con la documentazione standard di Oracle.
SQL*Loader carica i dati da file esterni in tabelle contenute nel database Oracle. SQL*Loader
utilizza due file principali: un file di dati, che contiene le informazioni da caricare, e un control
file che contiene informazioni relative al formato dei dati, i record e i campi contenuti nel file,
l’ordine in cui andranno caricati e, se necessario, i nomi dei file che verranno utilizzati per i dati.
Si possono unire le informazioni del control file con quelle del file di dati, sebbene questi due
siano in genere separati per semplificare il riutilizzo del control file.
Una volta eseguito, SQL*Loader creerà automaticamente un file di log e un file “non vali-
do”. Il file di log registra lo stato del carico, come il numero di righe elaborate e il numero di
righe eseguite; il file “non valido” conterrà tutte le righe rifiutate durante il caricamento per
errori nei dati, come valori non univoci nelle colonne di chiave primaria.
All’interno del control file è possibile specificare altri comandi allo scopo di regolare i
criteri di carico. Se una riga non soddisfa questi criteri, verrà scritta in un file “di scarto”. I file di
log, “non valido” e di scarto per default avranno rispettivamente le estensioni .log, .bad e .dsc.
Solitamente, i control file presentano l’estensione .ctl.
SQL*Loader è un’utility che per diversi motivi si rivela molto potente per il caricamento dei
dati.
■ È estremamente flessibile, tanto da consentire la manipolazione dei dati mentre vengono
caricati.
■ Può essere utilizzata per dividere un unico grande gruppo di dati in più gruppi di dati duran-
te il processo di esecuzione, riducendo significativamente la dimensione delle transazioni elabo-
rate dal carico.
374 CAPITOLO 21
■ L’opzione di caricamento a percorso diretto può servire per eseguire le operazioni di carico
in modo molto rapido.
Per iniziare a utilizzare SQL*Loader, per prima cosa è necessario acquisire una certa fami-
liarità con il control file, descritto nel prossimo paragrafo.
LOAD DATA
INFILE 'bookshelf.dat'
INTO TABLE BIBLIOTECA
(Titolo POSITION(01:100) CHAR,
Editore POSITION(101:120) CHAR,
NomeCategoria POSITION(121:140) CHAR,
Valutazione POSITION(141:142) CHAR)
In questo esempio, i dati verranno caricati dal file bookshelf.dat nella tabella BIBLIOTECA.
Il file bookshelf.dat conterrà dati per tutte e quattro le colonne di BIBLIOTECA, con degli spazi
vuoti che spaziano i caratteri non utilizzati in questi campi. Pertanto il valore della colonna
Editore inizia sempre allo spazio 101 nel file, anche se il valore Titolo è inferiore ai 100 caratteri.
Anche se questa formattazione ingrandisce il file di input, potrebbe semplificare il processo di
caricamento. Per i campi non è necessario specificare la lunghezza, dato che le posizioni iniziale
e finale nel flusso dei dati di input indicano effettivamente la lunghezza del campo.
La clausola infile assegna un nome al file di input, mentre la clausola into table specifica la
tabella in cui verranno caricati i dati. Ogni colonna viene elencata, insieme alla posizione dove si
trovano i propri dati in ciascun record fisico del file. Questo formato permette di caricare i dati
anche se l’ordine della colonna dei dati di origine non corrisponde a quello delle colonne nella
tabella.
Per eseguire questo caricamento, l’utente che se ne incarica dovrà possedere il privilegio
INSERT per la tabella BIBLIOTECA.
LOAD DATA
INFILE 'bookshelf.dat'
BADFILE '/user/load/bookshelf.bad'
TRUNCATE
INTO TABLE BIBLIOTECA
FIELDS TERMINATED BY ","
(Titolo, Editore, NomeCategoria, Valutazione)
NOTA Occorre accertarsi di selezionare un delimitatore che non sia presente nei
valori da caricare. In questo esempio il delimitatore è la virgola, pertanto qualunque virgola
presente in una stringa di testo che viene caricata sarà interpretata come carattere di fine campo.
Quando si esegue SQLLDR, è necessario specificare il control file, il nome utente e la password
e altre informazioni di carico importanti, come mostrato nella Tabella 21.1.
Ogni operazione di carico deve avere un control file, perché nessuno dei parametri di input
specifica le informazioni importanti per il carico, il file di input e la tabella caricata.
Esiste la possibilità di separare gli argomenti da SQLLDR con delle virgole: è sufficiente
inserirli con parole chiave (come userid o log), seguite dal valore del parametro. Le parole chiave
sono sempre seguite da un segno di uguale (=) e dall’argomento appropriato.
376 CAPITOLO 21
Discardmax Massimo numero di righe da scartare prima di interrompere il caricamento. Il funzionamento predefinito
prevede di consentire lo scarto di tutte le righe.
Skip Numero di righe logiche del file di input da saltare prima di iniziare a caricare i dati. In genere utilizzata
durante i ricaricamenti dallo stesso file di input in seguito a un caricamento parziale. Il valore predefinito è 0.
Rows Numero di righe da confermare in una volta. Utilizzare questo parametro per ridurre la dimensione della
transazione durante il caricamento. Il valore predefinito per i caricamenti a percorso convenzionale è 64;
per i caricamenti a percorso diretto è tutte le righe.
Bindsize Dimensione dell’array di bind a percorso convenzionale, in byte. Il valore predefinito dipende dal sistema
operativo.
Parfile Nome del file dei parametri che contiene le specifiche dei parametri di caricamenti aggiuntivi.
Skip_Unusable_Indexes Consente il caricamento in tabelle che hanno indici in stati non utilizzabili. Il valore predefinito è FALSE.
Skip_Index_Maintenance Interrompe il mantenimento degli indici per i caricamenti a percorso diretto, lasciandoli in stati non
utilizzabili. Il valore predefinito è FALSE.
External_table Usare le tabelle esterne per il caricamento; il valore predefinito è NOT_USED; altri valori validi sono
GENERATE_ONLY ed EXECUTE.
Columnarrayrows Numero di righe per l’array di colonne a percorso diretto: il valore predefinito è 5.000.
Streamsize Dimensione in byte dello stream buffer a percorso diretto: il valore predefinito è 256.000.
Multithreading Un flag per indicare se dev’essere utilizzato il multithreading durante un caricamento a percorso diretto.
Resumable Un flag TRUE/FALSE per attivare o disattivare le operazioni che possono essere riprese per la sessione
corrente; il valore predefinito è FALSE.
Resumable_timeout Tempo di attesa per un’operazione che può essere ripresa; il valore predefinito è 7200 secondi.
Se si omette la parola chiave userid e non viene fornita nessuna coppia di nome utente/
password come primo argomento, verrà richiesto di inserirla. Se dopo il segno di uguale compa-
re una barra (/), verrà utilizzato un account identificato esternamente. Inoltre, per connettersi a
USO DI SQL*LOADER PER CARICARE I DATI 377
un database remoto e caricare in esso dei dati si può utilizzare una stringa di specifica del database
Oracle Net. Per esempio, il comando potrebbe iniziare in questo modo:
sqlldr userid=usernm/mypass@dev
La parola chiave direct, che richiama l’opzione di carico a percorso diretto, verrà descritta
nel paragrafo “Caricamento a percorso diretto” più avanti in questo capitolo.
La parola chiave silent indica a SQLLDR di eliminare alcuni dati informativi:
■ HEADER elimina l’intestazione di SQL*LOADER.
■ FEEDBACK elimina il feedback a ogni punto di esecuzione.
■ ERRORS elimina il log (in un file di log) di tutti quei record che hanno causato un errore di
Oracle, anche se il conteggio viene sempre registrato.
■ DISCARDS elimina il log (in un file di log) di tutti i record che sono stati eliminati, anche
se il conteggio viene sempre registrato.
■ PARTITIONS disabilita la scrittura delle statistiche di pre-partizione nel file di log.
■ ALL elimina tutte i dati informativi precedenti.
Se si inseriscono più dati informativi, li si dovrà separare con una virgola e racchiudere la
lista tra parentesi. Per esempio, è possibile eliminare le informazioni header ed errors con
l’impostazione della parola chiave seguente:
silent=(HEADER,ERRORS)
NOTA I comandi nel control file si sovrappongono a quelli nella linea di comando
chiamante.
Si provi a caricare un gruppo di dati di esempio nella tabella BIBLIOTECA, che ha quattro
colonne (Titolo, Editore, NomeCategoria e Valutazione). Si crei un file di testo semplice di nome
bookshelf.txt; i dati da caricare devono essere due sole linee nel file:
NOTA Ogni linea termina con un ritorno a capo. Anche se l’ultimo valore della
prima linea non è lungo come la colonna in cui viene caricato, la riga si fermerà al ritorno a
capo.
LOAD DATA
INFILE 'bookshelf.txt'
APPEND
INTO TABLE BIBLIOTECA
FIELDS TERMINATED BY ","
(Titolo, Editore, NomeCategoria, Valutazione)
Si salvi questo file con il nome bookshelf.ctl, nella stessa directory in cui si trova il file di
dati di input. Successivamente, si esegua SQLLDR comunicandogli di usare il control file. Que-
sto esempio presuppone che la tabella BIBLIOTECA esista sotto lo schema PRACTICE:
select Titolo
from BIBLIOTECA
where Editore like '%Editore';
TITOLO
------------------------------------------
Good Record
Perché il record è stato rifiutato? Si verifichi il file di log, bookshelf.log, che in parte dirà:
Table BIBLIOTECA:
1 Row successfully loaded.
1 Row not loaded due to data errors.
La riga 2, quella di “Another Title”, è stata rifiutata perché il valore della colonna
NomeCategoria non rispettava le limitazioni di chiave esterna: ILLUSADULTI non è elencato
come categoria nella tabella CATEGORIA.
Dato che le righe rifiutate vengono isolate nel file non valido, questo file potrà servire da
input per un caricamento successivo dopo aver corretto i dati.
in questo caso, tra il record fisico e quello logico così creato si stabilirebbe una relazione uno a
uno. Tuttavia, il file di dati potrebbe assumere questo aspetto:
Good Record,
Some Publisher,
SAGGIADULTI,
3
Per unire i dati, si dovranno specificare le regole di continuazione. In questo caso, i valori
della colonna vengono divisi uno per linea in modo che ogni record logico possegga un certo
numero di record fisici. Per unirli, si utilizzi la clausola concatenate nel control file. In questo
caso, si specificherebbe concatenate 4 per creare un’unica riga logica a partire dalle quattro
righe fisiche.
USO DI SQL*LOADER PER CARICARE I DATI 379
La logica per la creazione di un unico record logico a partire da più record fisici può essere
molto più complessa di una semplice concatenazione. La clausola continueif può servire per
specificare le condizioni che causano la continuazione dei record logici. I dati di input possono
essere manipolati ulteriormente allo scopo di creare più record logici partendo da un unico record
fisico (grazie all’uso di più clausole into table). Si analizzi la sintassi del control file nella voce
“SQLLDR” del Capitolo 42 di questo libro, nonché le note indicate nel paragrafo successivo.
SQL*Loader può essere utilizzato per generare più inserimenti da un’unica riga fisica (ana-
loga alla capacità di inserire più tabelle descritta nel Capitolo 15). Per esempio, si supponga che
i dati di input siano denormalizzati con i campi Citta e Precipitazione, mentre i dati di input sono
nel formato Citta, Precipitazione1, Precipitazione2, Precipitazione3. Il control file assomiglie-
rebbe a quanto segue (ovviamente in base alle posizioni fisiche di arresto e di avvio dei dati nel
file):
Si osservi che su ogni riga fisica operano clausole into table separate. In questo esempio,
esse generano righe separate nella tabella PRECIPITAZIONE; potrebbero essere utilizzate an-
che per inserire delle righe in più tabelle.
when Valutazione>'3'
per caricare solo quei libri che hanno valutazioni maggiori di 3 nella tabella. Qualunque riga non
superi la condizione when verrà scritta nel file di scarto, che pertanto raccoglie le righe che
potranno essere impiegate per operazioni successive di carico, ma che non passavano
l’impostazione attuale delle condizioni when. Si possono utilizzare più condizioni when, colle-
gate con clausole and.
Se si effettua il caricamento di record a lunghezza variabile le cui ultime colonne non hanno
sempre un valore, occorre utilizzare la clausola trailing nullcols. Quando si usa questa clausola,
SQL*Loader genererà dei valori NULL per queste colonne.
Come mostrato in un esempio precedente di questo capitolo, è possibile utilizzare la clauso-
la fields terminated by per caricare dati a lunghezza variabile. Invece di essere terminati da un
carattere, i campi possono essere terminated by whitespace, enclosed by caratteri oppure optionally
enclosed by altri caratteri.
Per esempio, la voce seguente carica i valori di NomeAutore e imposta i valori come maiu-
scoli durante l’operazione di inserimento. Se il valore è vuoto, verrà inserito NULL:
Quando si caricano i valori del tipo di dati DATE, è possibile specificare un formato di
visualizzazione per la data. Per esempio, nel caso in cui si abbia una colonna chiamata
DataRestituzione e i dati in ingresso presentino il formato Mon-DD-YYYY nelle prime 11 posi-
zioni del record, si potrebbe specificare la parte DataRestituzione del carico nel modo seguente:
Nella clausola into table, la parola chiave recnum può essere usata per assegnare un numero
di record a ciascun record logico mentre viene letto dal file di dati, e questo valore verrà inserito
nella colonna assegnata della tabella. La parola chiave constant permette di assegnare un valore
costante a una colonna durante l’operazione di caricamento. Per le colonne di caratteri, si rac-
chiuda il valore costante tra apici. Se si usa la parola chiave sysdate, la colonna selezionata verrà
popolata con la data e l’ora correnti del sistema.
DataPrestito SYSDATE
Se invece si usa l’opzione sequence, SQL*Loader manterrà una sequenza di valori durante
il processo di caricamento. Man mano che i record vengono elaborati, il valore della sequenza
verrà aumentato dell’incremento specificato. Se durante l’inserimento le righe falliscono (e ven-
gono inviate nel file non valido), i valori di tale sequenza non saranno riutilizzati. Se nell’opzio-
ne di sequenza si utilizza la parola chiave max, i valori della sequenza useranno il valore attual-
mente massimo della colonna come punto iniziale della sequenza. Il listato seguente mostra
l’uso dell’opzione sequence:
Seqnum_col SEQUENCE(MAX,1)
Per una sequenza, si possono specificare anche un valore iniziale e uno di incremento da
utilizzare durante gli inserimenti. L’esempio seguente inserisce dei valori che partono da 100,
con un incremento di 2. Se durante l’inserimento una riga viene rifiutata, il suo valore di sequen-
za verrà ignorato.
Seqnum_col SEQUENCE(100,2)
USO DI SQL*LOADER PER CARICARE I DATI 381
Se si memorizzano dei numeri nelle colonne di tipo VARCHAR2, non si utilizzi l’opzione
sequence per queste colonne. Per esempio, se la tabella contiene già i valori da 1 a 10 in una
colonna VARCHAR2, allora il valore più grande in questa colonna sarà 9, ossia la stringa di
caratteri più grande. L’uso di questa stringa come base per un’opzione sequence farà in modo
che SQL*Loader cerchi di inserire un record con 10 come valore creato più recentemente, e
questo potrebbe causare dei conflitti con il record già esistente. Questo comportamento illustra
perché la memorizzazione dei numeri in colonne di caratteri è in genere una pratica sconsigliabile.
I control file di SQL*Loader sono in grado di supportare regole di logica e business com-
plesse. Per esempio, i dati di input di una colonna contenente valori monetari potrebbero avere
un valore decimale implicito; 9990 verrebbe inserito come 99.90. In SQL*Loader, si potrebbe
inserire questo valore eseguendo i calcoli durante il caricamento dei dati:
Per ulteriori esempi su SQL*Loader e control file di esempio, fare riferimento al paragrafo
“SQL*Loader Case Studies” della Oracle Utilities Guide.
Se i commenti sono stati inseriti correttamente nel control file, le possibilità che quest’ulti-
mo venga riutilizzato durante le future operazioni di caricamento aumenteranno. Inoltre, si sem-
plificherà la gestione dello stesso processo di caricamento dei dati, come descritto nel prossimo
paragrafo.
DIRECT=TRUE
come parola chiave nella linea di comando SQLLDR, oppure includere questa opzione nel control
file.
Se si usa l’opzione a percorso diretto, per migliorare le prestazioni del caricamento dei dati
si può utilizzare la parola chiave unrecoverable, che ordina a Oracle di non creare voci di redo
log per il caricamento. Se più avanti si avrà la necessità di recuperare il database, si dovrà esegui-
re nuovamente il caricamento dei dati per recuperare i dati della tabella. Tutti i caricamenti con
percorso convenzionale sono recuperabili e tutti i caricamenti a percorso diretto sono recuperabili
per default.
USO DI SQL*LOADER PER CARICARE I DATI 385
I caricamenti a percorso diretto sono più rapidi di quelli convenzionali, e anche i caricamenti
a percorso diretto irrecuperabili sono comunque più veloci. Dato che l’esecuzione di caricamenti
irrecuperabili influisce sulle operazioni di recupero, si dovranno valutare le conseguenze di que-
sto impatto rispetto ai vantaggi, in termini di prestazioni, che si otterranno. Se l’ambiente hardware
possiede delle risorse aggiuntive disponibili durante il processo di caricamento, si potrà utilizza-
re l’opzione di caricamento a percorso diretto parallel per suddividere il lavoro di caricamento
dei dati tra più processi. Le operazioni a percorso diretto parallele potrebbero completare il
lavoro di caricamento più rapidamente di un singolo caricamento a percorso diretto.
Invece di usare l’opzione parallel, si potrebbe suddividere la tabella da caricare (si veda il
Capitolo 17). Dato che SQL*Loader consente di caricare una singola partizione, si potrebbero
eseguire più operazioni SQL*Loader contemporaneamente per popolare le parti separate di una
tabella suddivisa. Questo metodo richiede un maggiore lavoro di amministrazione del database
(per configurare e gestire le varie partizioni), tuttavia garantisce più flessibilità nell’esecuzione
in parallelo e nella programmazione delle operazioni di carico.
È possibile sfruttare la funzionalità di caricamento multithread per i caricamenti a percorso
diretto per convertire gli array di colonne in buffer di stream, e per eseguire il caricamento di
buffer di stream in parallelo. Per attivare questa soluzione, occorre utilizzare il parametro
streamsize e il flag multithreading.
Il caricamento a percorso diretto potrebbe influire sulla quantità di spazio necessaria per i
dati della tabella. Dato che il caricamento a percorso diretto inserisce blocchi di dati, non segue
i metodi usuali impiegati per allocare lo spazio in una tabella. I blocchi vengono inseriti alla fine
della tabella, dopo l’high watermark, che è il blocco più elevato in cui i dati della tabella siano
mai stati scritti. Se si inseriscono 100 blocchi di dati in una tabella e poi si cancellano tutte le
righe, l’high watermark della tabella sarà ancora impostato a 100. Se in seguito si esegue un’ope-
razione di caricamento dei dati SQL*Loader convenzionale, le righe verranno inserite nei bloc-
chi già allocati. Se invece si effettua un caricamento a percorso diretto, Oracle inserirà nuovi
blocchi di dati dopo il blocco numero 100, comportando un probabile aumento dello spazio da
allocare per la tabella. L’unico modo di ridurre l’high watermark di una tabella consiste nel
troncarla (il che comporta la cancellazione di tutte le righe e l’impossibilità di annullare questa
operazione), oppure nell’eliminarla per poi ricrearla. Per identificare i problemi di spazio prima
di iniziare un’operazione di caricamento si dovrebbe collaborare con il proprio amministratore
di database.
I
ntrodotto con Oracle Database 10g, Data Pump fornisce una
utility per l’estrazione e l’importazione di dati basata su server. Le sue caratteristiche presentano
notevoli miglioramenti a livello di architettura e funzionale rispetto alle utility Import ed Export
originali. Data Pump consente di arrestare e riavviare processi, vedere lo stato dei processi in
esecuzione e limitare i dati che vengono esportati e importati.
NOTA Data Pump può utilizzare i file generati con l’utility Export originale, mentre
l’utility Import originale non è in grado di usare i file generati da Data Pump Export.
Data Pump esegue un processo sul lato server, il che presenta diversi vantaggi per gli utenti.
Il processo client che avvia il job può disconnettersi e in seguito riconnettersi al job. Le presta-
zioni sono migliori (in confronto a Export/Import) perché i dati non devono più essere elaborati
da un programma client. Le estrazioni e i caricamenti con Data Pump possono avvenire in paral-
lelo, migliorando ulteriormente le prestazioni.
Questo capitolo illustra come utilizzare Data Pump e presenta descrizioni ed esempi delle
sue opzioni principali.
L’esempio seguente crea una directory di nome DTPUMP e concede gli accessi READ e
WRITE allo schema PRACTICE:
Gli schemi PRACTICE e SYSTEM ora possono usare la directory DTPUMP per i processi
di Data Pump.
Quando si dà il via a un job, Oracle gli assegnerà un nome generato dal sistema. Nel caso in
cui si specifichi un nome per il job tramite il parametro JOB_NAME, occorre accertarsi che il
nome del job non sia in conflitto con quello di qualunque tabella o vista presente nel proprio
schema. Durante i processi di Data Pump, Oracle creerà e manterrà una tabella master per tutta
la durata del processo. Questa tabella master avrà lo stesso nome del job di Data Pump, quindi il
suo nome non può creare conflitti con quelli di altri oggetti già esistenti.
Quando un processo è in esecuzione, è possibile eseguire i comandi elencati nella Tabella
22.2 tramite l’interfaccia di Data Pump.
Come implicano le voci della Tabella 22.2, è possibile modificare molte caratteristiche di un
job di Data Pump Export in esecuzione tramite la modalità di comando interattiva. Se l’area di
dump esaurisce lo spazio, è possibile collegarla al job, aggiungere file e riavviare il job a quel
punto; non c’è alcun bisogno di sopprimere il processo o di rieseguirlo dall’inizio. È possibile
visualizzare lo stato dei processi in qualunque momento tramite il parametro STATUS, con le
viste del dizionario dati USER_DATAPUMP_JOBS e DBA_DATAPUMP_JOBS o tramite la
vista V$SESSION_LONGOPS.
DIRECTORY=dtpump
DUMPFILE=metadataonly.dmp
CONTENT=METADATA_ONLY
DIRECTORY Specifica la directory di destinazione per il file di log e l’insieme dei file di dump.
ESTIMATE Determina il metodo usato per stimare la dimensione del file di dump (BLOCKS o STATISTICS).
ESTIMATE_ONLY Il flag Y/N viene utilizzato per indicare a Data Pump se i dati devono essere esportati o soltanto stimati.
FLASHBACK_SCN SCN per il database in caso di flashback durante l’esportazione (Capitolo 27).
FLASHBACK_TIME Indicatore orario per il database in caso di flashback durante l’esportazione (Capitolo 27).
FULL Indica a Data Pump di esportare tutti i dati e i metadati in modalità di esportazione Full.
JOB_NAME Specifica un nome per il processo; per default viene generato dal sistema.
NETWORK_LINK Specifica il database link di origine per un processo di esportazione Data Pump da un database remoto.
NOLOGFILE Flag Y/N usato per sopprimere la creazione del file di log.
TRANSPORT_FULL_CHECK Specifica se le tablespace esportate devono prima essere verificate come insieme autonomo.
VERSION Specifica la versione degli oggetti del database da creare in modo che il gruppo dei file di dump possa
essere compatibile con le versioni precedenti di Oracle. Le opzioni sono COMPATIBLE, LATEST e i
numeri di versione del database (non inferiori a 10.0.0).
390 CAPITOLO 22
Tabella 22.2 Parametri per i processi Data Pump Export in modalità interattiva.
PARAMETRO DESCRIZIONE
ADD_FILE Aggiunge file di dump.
EXIT_CLIENT Esce dalla sessione client, lasciando però in esecuzione il processo Data Pump Export sul server.
Oracle a questo punto passerà le voci di dp1.par al processo di Data Pump Export. Verrà
eseguito un processo di Data Pump Export di tipo Schema (il tipo predefinito) e l’output (gli
elenchi di metadati, ma non i dati) verranno scritti in un file situato nella directory dtpump
definita in precedenza. Quando si esegue il comando expdp, l’output avrà il formato seguente (ci
saranno righe separate per ciascuno dei principali tipi di oggetto, ossia tabelle, concessioni,
indici e così via):
Il file di output, come illustrato nel listato, prende il nome di metadataonly.dmp. Il file di
dump di output contiene voci XML per la ricreazione delle strutture per lo schema Practice.
USO DI DATA PUMP EXPORT E IMPORT 391
Durante l’esportazione, Data Pump ha creato e utilizzato una tabella esterna di nome
SYS_EXPORT_SCHEMA_01.
NOTA I file di dump non sovrascriveranno quelli già esistenti nella medesima
directory.
È possibile utilizzare più directory e file di dump per un singolo processo di Data Pump
Export. Nell’impostazione del parametro DUMPFILE la directory dev’essere elencata assieme
al nome di file, attenendosi a questo formato:
DUMPFILE=directory1:file1.dmp,
directory2:file2.dmp
Premendo CTRL-C per uscire dalla visualizzazione del log, Data Pump riporterà al prompt di
Export:
Export>
Export> EXIT_CLIENT
Se si è dato un nome al processo di Data Pump Export, occorre specificarlo come parte della
chiamata del parametro ATTACH. Per esempio, se si fosse denominato il processo
PRACTICE_JOB, è necessario collegarsi per nome:
Export> CONTINUE_CLIENT
392 CAPITOLO 22
Export> STOP_JOB
Una volta arrestato il processo, è possibile aggiungere altri file di dump in nuove directory
tramite l’opzione ADD_FILE e poi riavviare il processo:
Export> START_JOB
È possibile specificare una posizione di file di log per il log di esportazione tramite il para-
metro LOGFILE. Se non si specifica un valore per LOGFILE, il file di log verrà scritto nella
medesima directory del file di dump.
Nel proprio file dei parametri (o sulla linea di comando di expdp), occorre impostare il
parametro NETWORK_LINK uguale al nome del proprio database link. Data Pump Export
scriverà i dati provenienti dal database remoto nella directory definita nel proprio database locale.
EXCLUDE=tipo_oggetto[:clausola_nome] [, ...]
EXCLUDE=SCHEMA:"='PRACTICE'"
NOTA È possibile specificare più di una opzione EXCLUDE nello stesso processo
di Data Pump Export.
EXCLUDE=TABLE:"LIKE 'TEMP%'"
Quando si immette questo comando, potrebbe essere necessario utilizzare i caratteri di escape
in modo che gli apici e gli altri caratteri speciali vengano passati correttamente a Oracle. Il
comando expdp avrà quindi il formato seguente:
NOTA Questo esempio mostra soltanto una parte della sintassi, non la sintassi
completa.
Se non viene fornito alcun valore di clausola_nome, tutti gli oggetti del tipo specificato
sono esclusi. Per escludere tutti gli indici, per esempio, si specificherebbe quanto segue:
Per ottenere un elenco degli oggetti che è possibile filtrare, si possono interrogare le viste
del dizionario dati DATABASE_EXPORT_OBJECTS, SCHEMA_EXPORT_OBJECTS e
TABLE_EXPORT_OBJECTS. Se il valore di tipo_oggetto è CONSTRAINT, i vincoli NOT
NULL non saranno esclusi. Oltre a ciò, non è possibile escludere i vincoli necessari per la corret-
ta creazione di una tabella (come un vincolo di chiave primaria per le tabelle organizzate tramite
indici. Se il valore di tipo_oggetto è USER, le definizioni degli utenti sono escluse, ma gli
oggetti racchiusi all’interno degli schemi degli utenti saranno comunque esportati. Per escludere
gli oggetti di un utente e di tutti gli utenti si utilizza il tipo_oggetto SCHEMA, come mostrato
nell’esempio precedente. Se il valore di tipo_oggetto fosse GRANT, verrebbero escluse tutte le
concessioni di oggetti e di privilegi di sistema.
È disponibile anche una seconda opzione, INCLUDE. Quando si impiega INCLUDE, solo
gli oggetti che rispondono al criterio vengono esportati, mentre tutti gli altri saranno esclusi.
INCLUDE ed EXCLUDE si escludono reciprocamente. Il formato di INCLUDE è il seguente:
Per esempio, per esportare due tabelle e tutte le procedure, il file dei parametri potrebbe
comprendere queste due linee:
INCLUDE=TABLE:"IN ('BIBLIOTECA','BIBLIOTECA_AUTORE')"
INCLUDE=PROCEDURE
Quali righe verranno esportate per tutti gli oggetti che rispondono ai criteri EXCLUDE o
INCLUDE? Per default vengono esportate tutte le righe di ciascuna tabella. È tuttavia possibile
utilizzare l’opzione QUERY per limitare le righe restituite; il formato di questa opzione è il
seguente:
Se non si specificano dei valori per le tabelle schema e nome_tabella, clausola_query sarà
applicata a tutte le tabelle esportate. Dato che clausola_query in genere includerà dei nomi di
colonna specifici, occorre prestare molta attenzione quando si selezionano le tabelle da include-
re nell’esportazione.
394 CAPITOLO 22
Si può specificare un valore QUERY per una singola tabella, come illustrato nel listato
seguente:
Ne risulta che il file di dump conterrà solo le righe che rispondono ai criteri di QUERY
nonché a quelli di INCLUDE o EXCLUDE. Queste restrizioni possono essere applicate anche
durante l’operazione Data Pump Import successiva, come descritto nel prossimo paragrafo del
capitolo.
NOTA La directory per il file di dump e il file di log deve esistere già; fare riferi-
mento al paragrafo precedente a proposito del comando create directory.
Come per Data Pump Export, le modalità supportate sono cinque: Full, Schema, Table,
Tablespace e Transportable Tablespace. Se non viene specificata alcuna modalità, Oracle tenta di
caricare l’intero file di dump.
La Tabella 22.4 elenca i parametri validi nella modalità interattiva di Data Pump Import.
Molti parametri di Data Pump Import sono uguali a quelli disponibili per Data Pump Export.
Nei parametri seguenti si vedrà coma avviare un processo di importazione, insieme alle descri-
zioni delle principali opzioni esclusive Data Pump Import.
DIRECTORY=dtpump
DUMPFILE=metadataonly.dmp
CONTENT=METADATA_ONLY
L’importazione creerà gli oggetti dello schema PRACTICE in uno schema diverso. L’opzio-
ne REMAP_SCHEMA consente di importare oggetti da uno schema diverso da quello utilizzato
per l’esportazione. Se nello stesso tempo si desiderano cambiare le assegnazioni delle tablespace
per gli oggetti, si utilizza l’opzione REMAP_TABLESPACE. Il formato di REMAP_SCHEMA
è il seguente:
USO DI DATA PUMP EXPORT E IMPORT 395
DIRECTORY Specifica la posizione del gruppo dei file di dump e la directory di destinazione per i file di log e SQL.
DUMPFILE Specifica i nomi e facoltativamente le directory per l’insieme dei file di dump.
ESTIMATE Determina il metodo usato per stimare la dimensione del file di dump (BLOCKS o STATISTICS).
FLASHBACK_SCN SCN per il database in caso di flashback durante l’importazione (Capitolo 27).
FLASHBACK_TIME Indicatore orario per il database in caso di flashback durante l’importazione (Capitolo 27).
FULL Flag Y/N usato per specificare che si desidera importare il file di dump completo.
JOB_NAME Specifica un nome per il processo; per default viene generato dal sistema.
NETWORK_LINK Specifica il database link di origine per un processo di importazione Data Pump da un database remoto.
NOLOGFILE Flag Y/N usato per sopprimere la creazione del file di log.
REMAP_DATAFILE Cambia il nome del file di dati di origine nel file di dati di destinazione nei comandi create library, create
tablespace e create directory durante l’importazione.
REUSE_DATAFILES Specifica se i file di dati esistenti devono essere riutilizzati dai comandi create tablespace durante le
importazioni in modalità Full.
SKIP_UNUSABLE_INDEXES Flag Y/N. Se Y, l’importazione non carica i dati nelle tabelle i cui indici sono impostati allo stato Index
Unusable.
SQLFILE Denomina il file in cui verrà scritto il DDL per l’importazione. I dati e i metadati non verranno caricati nel
database di destinazione.
(segue)
396 CAPITOLO 22
Tabella 22.3 Parametri per la linea di comando di Data Pump Import. (continua)
PARAMETRO DESCRIZIONE
STREAMS_CONFIGURATION Flag Y/N flag utilizzato per specificare se devono essere importate le informazioni per la configurazione
Streams.
TABLE_EXISTS_ACTION Indica a Import come procedere se la tabella importata esiste già. I valori possibili sono SKIP, APPEND,
TRUNCATE e REPLACE. Il valore predefinito è APPEND se CONTENT=DATA_ONLY, altrimenti è SKIP.
TRANSFORM Indirizza le modifiche agli attributi di segmento o alla memorizzazione durante l’importazione.
TRANSPORT_DATAFILES Elenca i file di dati da importare durante un’importazione in modalità Transportable Tablespace.
TRANSPORT_FULL_CHECK Specifica se le tablespace importate devono prima essere verificate come insieme autonomo.
VERSION Specifica la versione degli oggetti del database da creare in modo che il gruppo dei file di dump possa
essere compatibile con le versioni precedenti di Oracle. Le opzioni sono COMPATIBLE, LATEST e i
numeri di versione del database (non inferiori a 10.0.0). Sono valide solo per NETWORK_LINK e SQLFILE.
REMAP_SCHEMA=schema_origine:schema_destinazione
DIRECTORY=dtpump
DUMPFILE=metadataonly.dmp
CONTENT=METADATA_ONLY
REMAP_SCHEMA=Practice:Newpractice
Ora si può avviare il processo di importazione. Dato che si sta cambiando lo schema pro-
prietario dei dati, è necessario disporre del privilegio di sistema IMP_FULL_DATABASE. I
processi di Data Pump Import vengono avviati con l’eseguibile impdp. Il listato che segue illu-
stra la creazione di un processo Data Pump Import con il file dei parametri dp1.par:
NOTA Tutti i file di dump devono essere specificati al momento dell’avvio del
processo.
Dato che non è stata specificata l’opzione NOLOGFILE, il file di log per l’importazione
verrà collocato nella stessa directory del file di dump e sarà denominato import.log. È possibile
USO DI DATA PUMP EXPORT E IMPORT 397
EXIT_CLIENT Esce dalla sessione client, lasciando però in esecuzione il processo Data Pump Import sul server.
verificare il successo dell’importazione collegandosi allo schema NEWPRACTICE, che ora deve
avere una copia di tutti gli oggetti validi creati nello schema PRACTICE.
Cosa accade se una tabella importata esisteva già? In questo esempio, con l’opzione
CONTENT impostata a METADATA_ONLY, la tabella verrebbe saltata per default. Se l’opzio-
ne CONTENT fosse impostata a DATA_ONLY, i nuovi dati verrebbero aggiunti alle tabelle dei
dati esistenti. Per modificare questo comportamento, si usa l’opzione TABLE_EXISTS_ACTION,
che come valori validi può accettare SKIP, APPEND, TRUNCATE e REPLACE.
Premendo CTRL-C per uscire dalla visualizzazione del log, Data Pump riporterà al prompt di
Import:
Import>
Import> EXIT_CLIENT
Se si è dato un nome al processo di Data Pump Import, occorre specificarlo come parte della
chiamata del parametro ATTACH. Quando ci si collega a un processo in esecuzione, Data Pump
398 CAPITOLO 22
Import> CONTINUE_CLIENT
Import> STOP_JOB
Import> START_JOB
TRANSFORM = nome_trasformazione:valore[:tipo_oggetto]
TRANSFORM=STORAGE:n:table
TRANSFORM=SEGMENT_ATTRIBUTES:n
Quando gli oggetti vengono importati, verranno assegnati alla tablespace predefinita del-
l’utente e utilizzeranno i parametri di memorizzazione predefiniti di quella tablespace.
SQLFILE=[oggetto_directory:]nome_file
Il listato seguente mostra un esempio di file dei parametri per un’importazione con l’opzio-
ne SQFILE: Si osservi che l’opzione CONTENT non è specificata. L’output verrà scritto nella
directory dtpump.
DIRECTORY=dtpump
DUMPFILE=metadataonly.dmp
SQLFILE=sql.txt
Nel file sql.txt creato dall’importazione saranno presenti delle voci per ciascuno dei tipi di
oggetti all’interno dello schema. Il formato del file di output sarà simile al listato seguente,
anche se gli ID e gli SCN degli oggetti saranno specifici del proprio ambiente. Per brevità qui
non vengono riprodotte tutte le voci:
-- CONNECT PRACTICE
-- new object type path is: SCHEMA_EXPORT/
SE_PRE_SCHEMA_PROCOBJACT/PROCACT_SCHEMA
BEGIN
sys.dbms_logrep_imp.instantiate_schema(schema_name=>'PRACTICE',
export_db_name=>'ORCL', inst_scn=>'3377908');
COMMIT;
END;
/
A
mano a mano che le dimensioni e il numero dei database
crescono, si presenta la necessità di condividere i dati in essi contenuti. La condivisione dei dati
richiede un metodo per l’individuazione e l’accesso ai dati stessi. In Oracle, gli accessi a dati
remoti come query e aggiornamenti sono abilitati grazie ai database link. Come descritto in
questo capitolo, i database link consentono agli utenti di considerare un gruppo di database
distribuiti come se fosse un unico database integrato. Questo capitolo contiene inoltre informa-
zioni sulle connessioni dirette a database remoti, come quelle utilizzate in applicazioni client-
server.
Data-
Database base Database
LOCALE link REMOTO
Host Host
Filiale Quartiergenerale
select *
from BIBLIOTECA;
select *
from BIBLIOTECA@REMOTE_CONNECT;
Quando nella query precedente viene utilizzato il database link, Oracle si connette al database
specificato dal link utilizzando il nome utente e la password forniti dal collegamento. Successi-
vamente, eseguirà una query sulla tabella BIBLIOTECA in questo account e restituirà i dati
all’utente che ha inizializzato la query. Queste operazioni sono rappresentate graficamente nella
Figura 23.2. Il database link REMOTE_CONNECT, mostrato in questa figura, si trova nel database
LOCALE.
ACCESSO A DATI REMOTI 405
Come illustrato nella Figura 23.2, la connessione al database LOCALE e l’uso del database
link REMOTE_CONNECT nella clausola from restituiscono gli stessi risultati di una connessio-
ne diretta al database remoto e dell’esecuzione della query senza il database link. Il database
remoto appare come locale.
NOTA Il numero massimo di database link che possono essere utilizzati in una
singola query è impostato mediante il parametro OPEN-LINKS nel file dei parametri di
inizializzazione del database. Tale parametro è normalmente impostato al valore 4.
Le query eseguite tramite database link presentano alcune limitazioni. Occorre evitare di
usare i database link in query che utilizzano le parole chiave connect by, start with e prior. Alcune
query che ricorrono a queste parole chiave possono funzionare (per esempio, se prior non viene
utilizzata all’esterno della clausola connect by e start with non utilizza una subquery), ma la
maggior parte delle query strutturate ad albero non funzionerà con i database link.
In questo esempio, l’account remoto utilizzato dal database link non possiede la tabella
BIBLIOTECA, né ha un sinonimo con lo stesso nome. Tuttavia, l’account remoto dispone di
alcuni privilegi sulla tabella BIBLIOTECA di proprietà dell’utente remoto Pratica nel database
REMOTO. Per questo motivo, vengono specificati il proprietario e il nome della tabella: entram-
bi verranno interpretati nel database REMOTO. La sintassi per queste query e sinonimi è in gran
parte la stessa che si utilizzerebbe se tutto si trovasse nel database locale: l’unica aggiunta è
costituita dal nome del database link.
Per utilizzare un database link in una vista, è sufficiente aggiungerlo come suffisso ai nomi
delle tabelle nel comando create view. L’esempio riportato di seguito crea una vista nel database
locale di una tabella remota utilizzando il database link REMOTE_CONNECT:
update BIBLIOTECA@REMOTE_CONNECT
set Valutazione = '5'
where Titolo = 'INNUMERACY';
NOTA Se non si aggiunge il nome del database link ai nomi delle tabelle nella
clausola from delle subquery update, vengono utilizzate le tabelle nel database locale. Ciò vale
anche se la tabella aggiornata si trova in un database remoto.
In questo esempio, la tabella remota BIBLIOTECA viene aggiornata basandosi sul valore
Valutazione nella tabella remota BIBLIOTECA. Se nella subquery non viene utilizzato il database
link, come nell’esempio seguente, al suo posto viene utilizzata la tabella BIBLIOTECA del
database locale. Se questo non è intenzionale, i dati locali verranno mischiati nella tabella del
database remoto. Se invece si intende realmente procedere in questo modo, è consigliata un’estrema
cautela.
La sintassi specifica da utilizzare per la creazione di un database link dipende da due criteri:
■ Lo stato “pubblico” o “privato” del database link.
■ L’uso di connessioni predefinite o esplicite per il database remoto.
Questi criteri e la sintassi a essi associata sono descritti nei paragrafi seguenti.
NOTA Per creare un database link, è necessario disporre del privilegio di sistema
CREATE DATABASE LINK. L’account cui ci si connette nel database remoto dovrà disporre del
privilegio di sistema CREATE SESSION. Entrambi i privilegi di sistema sono compresi nel ruolo
CONNECT di Oracle. Il ruolo CONNECT in Oracle Database 10g esiste solo per garantire la
compatibilità con le versioni precedenti.
Per definire un database link come pubblico, si utilizza la parola chiave public nel comando
create database link, come mostrato nell’esempio seguente.
NOTA Per creare un database link pubblico, è necessario disporre del privilegio
di sistema CREATE PUBLIC DATABASE LINK. Questo privilegio è compreso nel ruolo DBA di
Oracle. Il ruolo DBA in Oracle Database 10g esiste solo per garantire la compatibilità con le
versioni precedenti.
Se utilizzato, questo database link cercherà di connettersi al database remoto identificato dal
nome di servizio ‘HQ’ utilizzando il nome utente e la password dell’utente corrente. Se nel
database remoto il nome utente corrente non è valido, o se la password è diversa, il tentativo di
connessione non riuscirà. Ciò comporterà anche il fallimento dell’istruzione SQL che utilizza il
collegamento.
Una connessione esplicita specifica un nome utente e una password che il database link
utilizzerà durante la connessione al database remoto. A prescindere da quale account locale
utilizzi il collegamento, verrà usato sempre lo stesso account remoto. Di seguito è riportata la
creazione di un database link con connessione esplicita:
Questo esempio mostra un uso comune delle connessioni esplicite nei database link. Nel
database remoto è stato creato un utente di nome Warehouse, cui è stata assegnata la password
ACCESS339. All’account Warehouse si potrà quindi concedere l’accesso SELECT a tabelle spe-
cifiche, esclusivamente per l’utilizzo mediante database link. Il database link
REMOTE_CONNECT fornirà quindi a tutti gli utenti locali l’accesso all’account Warehouse.
incontra un nome di servizio, Oracle controlla il file di configurazione locale di Oracle Net
(chiamato tnsnames.ora) per determinare quale protocollo, nome di host e nome di database
utilizzare durante la connessione. Tutte le informazioni di connessione si trovano in file esterni.
Quando si usa Oracle Net, è necessario conoscere il nome del servizio che punta al database
remoto. Per esempio, se il nome di servizio ‘HQ’ specifica i parametri di connessione per il
database necessario, allora ‘HQ’ dovrà essere utilizzato come stringa di connessione nel coman-
do create database link. L’esempio seguente mostra un database link privato che utilizza una
connessione predefinita e un nome di servizio di Oracle Net:
Quando si utilizza questo collegamento, Oracle verifica il file tnsnames.ora sull’host locale
per determinare il database cui connettersi. Quando cerca di connettersi a questo database, Oracle
usa il nome utente e la password dell’utente corrente.
I file tnsnames.ora per una rete di database dovrebbero essere coordinati dai DBA. Nel
listato seguente, è riportata una tipica voce del file tnsnames.ora (per una rete che utilizza il
protocollo TCP/IP).
HQ =(DESCRIPTION=
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL=TCP)
(HOST=host1)
(PORT=1521))
)
(CONNECT DATA=
(SERVICE_NAME = HQ.host1)
)
)
select *
from Pratica.BIBLIOTECA;
si potrebbe creare un sinonimo per detta tabella e poi nella query fare riferimento a questo
sinonimo, come illustrato qui:
select *
from BIBLIOTECA;
La logica richiesta per l’individuazione dei dati viene così spostata all’esterno dell’applica-
zione e all’interno del database. Lo spostamento della logica di dislocazione della tabella verso
il database rappresenterà un vantaggio ogni volta che la tabella stessa verrà spostata da uno
schema a un altro.
Oltre a nascondere la proprietà delle tabelle a un’applicazione, è anche possibile nascondere
la dislocazione fisica dei dati grazie a database link e sinonimi. Utilizzando sinonimi locali per
tabelle remote, un altro livello di logica viene spostato all’esterno dell’applicazione e all’interno
del database. Per esempio, il sinonimo locale BIBLIOTECA, come definito nel listato seguente,
fa riferimento a una tabella collocata in un database differente, su un host diverso. Se questa
ACCESSO A DATI REMOTI 411
tabella verrà spostata, sarà sufficiente modificare solo il collegamento, mentre il codice applicativo
che utilizza il sinonimo resterà invariato.
Se l’account remoto utilizzato dal database link non è il proprietario dell’oggetto cui si fa
riferimento, vi sono due possibilità. Per prima cosa è possibile fare riferimento a un sinonimo
disponibile nel database remoto:
In questo caso BIBLIOTECA, nell’account remoto utilizzato dal database link, è un sinonimo
per la tabella BIBLIOTECA di un altro utente.
In secondo luogo è possibile includere il nome del proprietario remoto durante la creazione
del sinonimo locale, come nel listato seguente.
Questi due esempi avranno la stessa funzionalità per le query, ma con alcune differenze. Il
secondo, che comprende il nome del proprietario, comporta una gestione potenzialmente più
difficile, in quanto non viene utilizzato un sinonimo nel database remoto e l’oggetto remoto
potrebbe essere spostato in un secondo tempo, rendendo di conseguenza non valido il sinonimo
locale.
NOTA Per questa discussione è necessario cambiare punto di vista. Dato che al
momento si sta parlando di operazioni sul database che possiede la tabella su cui si effettua la
query, questo database viene indicato come “locale”, mentre gli utenti di altri database sono
considerati come “remoti”.
Quando si applicano restrizioni all’accesso remoto a righe della tabella, in primo luogo è
necessario considerare quali colonne è opportuno utilizzare per tali restrizioni. Solitamente, esi-
stono divisioni logiche nei dati di una tabella, come Reparto o Area. Per ciascuna singola divi-
sione, occorre creare un account utente separato nel database locale. Per questo esempio, si
aggiunga una colonna Area alla tabella BIBLIOTECA. Ora, si potrà registrare l’elenco dei libri
da più dislocazioni distribuite in un’unica tabella:
Si supponga che nella tabella BIBLIOTECA siano rappresentate quattro aree principali e
che per ciascuna di esse sia stato creato un account Oracle. Sarà quindi possibile configurare
ciascun database link dell’utente remoto in modo che utilizzi il proprio account utente specifico
nel database locale. Per questo esempio, si supponga che le aree si chiamino NORD, EST, SUD
e OVEST. Per ciascuna area si dovrà creare un database link specifico. Per esempio, i membri
del reparto SUD utilizzerebbero il database link riportato nel listato seguente:
Il database link di questo esempio è privato con una connessione esplicita all’account SUD
nel database remoto.
Quando gli utenti remoti eseguono query mediante i propri database link (come SUD_LINK
nell’esempio precedente), verranno connessi al database HQ, con il nome del proprio Reparto
(come SUD) come nome utente. Pertanto il valore della colonna Utente, per qualsiasi tabella su
cui l’utente esegue una query, sarà ‘SUD’.
Ora si crei una vista della tabella base, mettendo a confronto la pseudocolonna User con il
valore della colonna Area nella clausola where della vista:
Un utente che si connette mediante il database link SUD_LINK, e viene così connesso come
utente SUD, visualizzerebbe solo i record di BIBLIOTECA che hanno un valore di Area uguale
a ‘SUD’. Se gli utenti accedono alla tabella da un database remoto, le loro connessioni avvengo-
no attraverso database link e gli account locali da essi utilizzati sono noti all’operatore poiché li
ha configurati.
Questo tipo di restrizione può essere imposto anche nel database remoto, invece che nel
database in cui risiede la tabella. Gli utenti nel database remoto possono creare viste nei propri
database con il formato seguente:
from BIBLIOTECA@REMOTE_CONNECT
where Area = 'SUD';
In questo caso, le restrizioni di Area restano ancora in vigore, tuttavia sono amministrate
localmente e codificate nella query della vista. La scelta tra le due possibilità di restrizione
(locale o remota) dipende dal numero di account necessari per imporre la restrizione desiderata.
Per proteggere il database di produzione, si dovrebbero limitare i privilegi concessi agli
account utilizzati dai database link. Inoltre, sarebbe opportuno concedere questi privilegi tramite
i ruoli, e utilizzare le viste (con la clausola with read only o with check option) per limitare
ulteriormente la possibilità che questi account vengano utilizzati per apportare modifiche non
autorizzate ai dati.
NOTA Il comando copy non verrà migliorato per gestire tipi di dati o caratteristi-
che introdotte con Oracle8i o dopo di esso. Probabilmente questo comando diventerà obsoleto
in una versione futura.
Il primo comando crea il database link, mentre il secondo crea una nuova tabella basata su tutti
i dati della tabella remota.
Sfortunatamente, questo metodo porta alla creazione di una transazione molto grande (tutte
le 100.000 righe verrebbero inserite nella nuova tabella come una singola transazione) che im-
pone un carico pesante alle strutture interne di Oracle, chiamate segmenti di rollback. I segmenti
di rollback e gli undo gestiti a livello di sistema (si consulti il Capitolo 46) memorizzano l’im-
magine dei dati fino a quando questi non vengono trasmessi al database. Dato che questa tabella
viene popolata con un singolo inserimento, verrà generata un’unica transazione di grandi dimen-
sioni, che potrebbe superare lo spazio nei segmenti di rollback attualmente disponibili. Tale
insuccesso causerà a sua volta il fallimento della creazione della tabella.
414 CAPITOLO 23
Per suddividere la transazione in porzioni più piccole, occorre utilizzare il comando copy di
SQL*Plus, che ha la sintassi seguente:
copy from
[nomeutente remoto/remoto password@stringa connessione]
[to nomeutente/password@stringa connessione]
{append|create|insert|replace}
nome tabella
using subquery;
Se la destinazione dei dati copiati è l’account corrente, la parola to, il nome utente locale, la
password e la stringa di connessione non sono necessari. Se l’account corrente è l’origine dei
dati copiati, non sono necessarie le informazioni di connessione remota per l’origine dei dati.
Per impostare le dimensioni delle voci di transazione si utilizza il comando set di SQL*Plus
che serve per impostare un valore per il parametro arraysize. Ciò consente di definire il numero
di record che verranno recuperati in ciascun “batch”. Il parametro copycommit specifica a
SQL*Plus quanti batch dovranno essere trasmessi per volta. Lo script SQL*Plus riportato di
seguito esegue la stessa copia dei dati consentita dal comando create table as; tuttavia, suddivide
la singola transazione in più transazioni. Nell’esempio seguente, i dati sono trasmessi dopo cia-
scun gruppo di 1.000 record. In questo modo, si riducono le dimensioni necessarie per i segmen-
ti di rollback della transazione da 100 MB a 1 MB.
set copycommit 1
set arraysize 1000
NOTA Ad eccezione dell’ultima, ciascuna linea nel comando copy deve terminare
con un trattino (-), in quanto si tratta di un comando SQL*Plus.
OPZIONE DESCRIZIONE
APPEND Inserisce le righe nella tabella di destinazione. Crea automaticamente la tabella se non esiste.
INSERT Inserisce le righe nella tabella di destinazione se esiste, altrimenti restituisce un errore. Quando si usa
INSERT, tutte le colonne devono essere specificate nella subquery using.
REPLACE Elimina la tabella di destinazione esistente e la sostituisce con una nuova tabella contenente i dati copia-
ti.
sqlplus nomeutente/password
e accedere al database locale, è possibile accedere direttamente a un database remoto. A tal fine,
occorre inserire il proprio nome utente e la propria password insieme alla stringa di connessione
Oracle Net per il database remoto:
sqlplus nomeutente/password@HQ
database ORACLE
e database HQ
Oracle Net
24.1 Funzionalità
24.2 Privilegi di sistema richiesti
24.3 Privilegi di tabella richiesti
24.4 Viste materializzate di sola lettura
e viste materializzate aggiornabili
24.5 Sintassi di create materialized view
24.6 Uso di viste materializzate per alterare
i percorsi di esecuzione delle query
24.7 Uso di DBMS_ADVISOR
24.8 Aggiornamento delle viste materializzate
24.9 Sintassi di create materialized view log
24.10 Modifica dei log e delle viste materializzate
24.11 Eliminazione di viste materializzate e log
P
er migliorare le prestazioni di un’applicazione è possibile cre-
are delle copie locali di tabelle remote che utilizzano dati distribuiti, oppure creare summary
table basate su operazioni group by. Oracle mette a disposizione delle viste materializzate per
memorizzare le copie di dati o di aggregazioni. Le viste materializzate possono essere utilizzate
per replicare un’intera tabella o parte di essa, oppure per replicare il risultato di una query ese-
guita su più tabelle; gli aggiornamenti dei dati replicati possono essere effettuati automatica-
mente dal database a intervalli di tempo definibili. Questo capitolo spiegherà l’uso generale
delle viste materializzate, comprese le loro strategie di aggiornamento, seguite da una descrizio-
ne delle strategie di ottimizzazione disponibili.
24.1 Funzionalità
Le viste materializzate sono copie (dette anche repliche) di dati basate su query. Nella sua forma
più semplice, una vista materializzata può essere considerata come una tabella creata da un
comando come il seguente:
In questo esempio, viene creata nel database locale una tabella di nome
BIBLIOTECA_LOCALE, che viene popolata con dati provenienti da un database remoto (defi-
nito dal database link REMOTE_CONNECT). Dopo che la tabella BIBLIOTECA_LOCALE è
418 CAPITOLO 24
stata creata, i suoi dati potrebbero perdere immediatamente la sincronizzazione con la tabella
principale (BIBLIOTECA@REMOTE_CONNECT). Inoltre, gli utenti locali possono aggior-
nare BIBLIOTECA_LOCALE, complicando ulteriormente la sua sincronizzazione con la tabel-
la principale.
Nonostante questi problemi di sincronizzazione, la replica dei dati eseguita in questo modo
porta notevoli vantaggi. La creazione di copie locali di dati remoti può migliorare le prestazioni
delle query distribuite, in particolare se i dati della tabella master non cambiano molto di fre-
quente. Si potrebbe utilizzare il processo di creazione di tabelle locali anche per limitare il nu-
mero di righe o di colonne restituite, oppure per creare nuove colonne (per esempio, applicando
le funzioni a valori selezionati). Si tratta di una strategia molto comune per ambienti di supporto
decisionale, in cui query complesse servono per effettuare il “riepilogo” periodico dei dati in
summary table da utilizzare durante le analisi.
Le viste materializzate automatizzano i processi di aggiornamento e di replica dei dati. Quando
si creano le viste materializzate, viene fissato un intervallo di aggiornamento per programmare
gli aggiornamenti dei dati replicati. Gli aggiornamenti locali possono essere evitati ripiegando
su aggiornamenti basati sulle transazioni. Gli aggiornamenti basati sulle transazioni, disponibili
per molti tipi di viste materializzate, inviano dal database master solo le righe che sono cambiate
per la vista materializzata. Questa capacità, descritta più avanti nel capitolo, può migliorare in
modo significativo le prestazioni degli aggiornamenti.
avere accesso alle tabelle e alle viste utilizzate dal link stesso. Non è possibile creare una vista
materializzata basata su oggetti di proprietà dell’utente SYS.
All’interno del database locale, è possibile concedere ad altri utenti locali il privilegio SELECT
su una vista materializzata. Dato che la maggior parte delle viste materializzate è di sola lettura
(anche se possono essere aggiornabili), non sono necessarie altre concessioni. Se si crea una
vista materializzata aggiornabile, si dovrà concedere agli utenti il privilegio UPDATE sia sulla
vista materializzata sia sulla tabella locale di base cui accede.
Il comando create materialized view ha quattro sezioni principali. La prima di esse è l’inte-
stazione, in cui viene nominata la vista materializzata (la prima linea del listato):
La vista materializzata viene creata nell’account dell’utente (schema), a meno che non ven-
ga specificato un nome di utente differente nell’intestazione. Nella seconda sezione vengono
impostati i parametri di memorizzazione:
I parametri di memorizzazione vengono applicati a una tabella che verrà creata nel database
locale. Per informazioni sui parametri di memorizzazione disponibili, si consulti la voce
“Memorizzazione” nel Capitolo 48. Se i dati sono stati appena replicati in una tabella locale, è
possibile utilizzare la clausola on prebuilt table per comunicare a Oracle di usare questa tabella
come vista materializzata.
[ clausola aggiornamento ]
{ refresh
{ { fast | complete | force }
| on { demand | commit }
| { start with | next } data
| with { primary key | rowid }
| using
USO DELLE VISTE MATERIALIZZATE 421
L’opzione refresh specifica il meccanismo che Oracle deve usare per l’aggiornamento della
vista materializzata. Le tre opzioni disponibili sono: fast, complete e force. Gli aggiornamenti
rapidi sono disponibili solo se Oracle è in grado di associare le righe nella vista materializzata
direttamente alle righe delle tabelle base; questi aggiornamenti usano tabelle denominate log
delle viste materializzate per inviare righe specifiche dalla tabella master alla vista materializzata.
Gli aggiornamenti completi troncano i dati e rieseguono la query di base sulla vista materializzata
per ripopolarla. L’opzione force per gli aggiornamenti indica a Oracle di usare, se disponibile,
un aggiornamento rapido e solo in caso contrario un aggiornamento completo. Se si è creata una
vista materializzata semplice, ma si desidera eseguire aggiornamenti completi, è necessario spe-
cificare refresh complete nel comando create materialized view. Le opzioni di aggiornamento
sono descritte in modo più dettagliato nel paragrafo “Aggiornamento delle viste materializzate”,
più avanti nel capitolo. All’interno di questa sezione del comando create materialized view è
anche possibile specificare il meccanismo utilizzato per correlare i valori nella vista materializzata
a quelli della tabella master, ovvero stabilire se devono essere utilizzati valori RowID o valori
della chiave primaria. Per default, vengono utilizzate le chiavi primarie.
Se la query master per la vista materializzata fa riferimento a un join o ad un aggregato
composto da un’unica tabella, è possibile usare l’opzione on commit per controllare la replica
delle modifiche. Con questa opzione, le modifiche verranno inviate dal master alla replica men-
tre vengono trasmesse alla tabella master. Se invece si specifica l’opzione on demand, l’aggior-
namento avviene quando si esegue manualmente un comando di aggiornamento.
La quarta sezione del comando create materialized view contiene la query utilizzata dalla
vista materializzata:
dati. Le viste materializzate aggiornabili sono un esempio di replica multimaster; per ulteriori
dettagli sull’implementazione di un ambiente di replica multimaster, si consulti la Advanced
Replication Guide.
NOTA La query che forma la base per la vista materializzata non deve utilizzare
le pseudocolonne User o SysDate.
Nell’esempio seguente, viene creata in un database locale una vista materializzata di sola
lettura denominata BIBLIOTECA_LOCALE, basata su una tabella remota BIBLIOTECA, ac-
cessibile tramite il database link REMOTE_CONNECT. La vista materializzata viene inserita
nella tablespace USERS.
Il comando dell’esempio precedente creerà una vista materializzata di sola lettura di nome
BIBLIOTECA_LOCALE. La sua tabella base verrà creata in una tablespace di nome USERS. I
log delle viste materializzate possono essere collocati in tablespace separatamente rispetto alle
viste materializzate supportate. L’opzione di aggiornamento force viene specificata poiché per la
vista materializzata non esiste un log delle viste materializzate nella tabella base; Oracle cerche-
rà di eseguire un aggiornamento rapido ma alla fine ricorrerà a un aggiornamento completo fino
a quando il log delle viste materializzate non verrà creato. La query della vista materializzata
specifica che l’intera tabella BIBLIOTECA, senza modifiche, dovrà essere copiata nel database
locale. Non appena la vista materializzata BIBLIOTECA_LOCALE è stata creata, la sua tabella
base verrà popolata con i dati della tabella BIBLIOTECA. Da quel momento in poi la vista
materializzata verrà aggiornata ogni sette giorni. I parametri di memorizzazione che non sono
specificati utilizzano i valori predefiniti in relazione alla tablespace USERS.
Nell’esempio seguente, in un database locale viene creata una vista materializzata di nome
CONTA_CATEGORIA_LOCALE, basata su una tabella remota di nome BIBLIOTECA in un
database cui si accede tramite il database link REMOTE_CONNECT.
Se nelle query si accede spesso a un gruppo di colonne, si potrà creare su di esse un indice
concatenato (per ulteriori informazioni sull’ottimizzatore di Oracle, si rimanda al capitolo 43).
Oracle non crea automaticamente degli indici per le viste materializzate complesse su co-
lonne diverse da quelle di chiave primaria. Questi indici devono essere creati manualmente. Per
crearli sulla tabella base locale, è necessario ricorrere al comando create index (si consulti il
Capitolo 48). Non occorre creare alcun vincolo sulla tabella di base della vista materializzata;
Oracle manterrà infatti le relazioni basate su vincoli sulle tabelle master.
Dal momento che sulle colonne su cui gli utenti probabilmente eseguiranno query dalla
vista materializzata non vengono creati indici, questi dovrebbero essere creati sulla tabella base
locale della vista materializzata.
NOTA È necessario specificare enable query rewrite nella definizione della vista
materializzata per far sì che la vista venga utilizzata nell’operazione di riscrittura della query.
Per usare la caratteristica di riscrittura delle query in modo efficiente, si dovrebbe creare una
dimensione che definisce le gerarchie all’interno dei dati della tabella. Per eseguire il comando
create dimension, sarà necessario disporre del privilegio di sistema CREATE DIMENSION. È
possibile creare una dimensione che supporti la gerarchia tra le tabelle di esempio PAESE e
CONTINENTE:
Per abilitare una vista materializzata alla riscrittura delle query, tutte le tabelle master della
vista materializzata dovranno trovarsi nello schema della vista materializzata e si dovrà disporre
del privilegio di sistema QUERY REWRITE. Se la vista e le tabelle si trovano in schemi separa-
ti, si dovrà disporre del privilegio di sistema GLOBAL QUERY REWRITE. In linea di massima,
426 CAPITOLO 24
le viste materializzate andrebbero create nello stesso schema delle tabelle su cui si basano; in
caso contrario sarà necessario gestire i permessi e le concessioni necessari per creare e gestire la
vista materializzata.
NOTA Le decisioni relative alla riscrittura delle query si basano sui costi dei
diversi percorsi di esecuzione, pertanto le statistiche devono essere tenute aggiornate.
gliare l’uso di indici (e tipi di indice) specifici per migliorare le prestazione delle unioni join e
delle altre query. SQL Access Advisor può anche generare consigli per la modifica di una vista
materializzata in modo che supporti la riscrittura delle query o gli aggiornamenti rapidi. È pos-
sibile eseguire SQL Access Advisor da Oracle Enterprise Manager o tramite esecuzioni del package
DBMS_ADVISOR.
Ecco la procedura da seguire per utilizzare SQL Access Advisor da Oracle Enterprise Mana-
ger o tramite DBMS_ADVISOR:
1. Creare un compito.
2. Definire il carico di lavoro.
3. Generare i consigli.
4. Visualizzare e implementare i consigli.
Esistono due modi per creare un compito: con l’esecuzione della procedura
DBMS_ADVISOR.CREATE_TASK o utilizzando la procedura DBMS_ADVISOR.QUICK_
TUNE (come illustrato nel prossimo paragrafo).
Il carico di lavoro è costituito da una o più istruzioni SQL più le statistiche e gli attributi
relativi all’istruzioni. Il carico di lavoro può includere tutte le istruzioni SQL per un’applicazio-
ne. SQL Access Advisor valuta ed effettua una graduatoria del carico di lavoro in base alle
statistiche e all’importanza aziendale. Il carico di lavoro viene creato con la procedura
DBMS_ADVISOR.CREATE_SQLWKLD. Per associare un carico di lavoro con un compito di
Advisor di livello superiore, si usa la procedura DBMS_ADVISOR.ADD_SQLWKLD_REF. Se
non viene fornito un carico di lavoro, SQL Access Advisor può generare e utilizzare un carico di
lavoro ipotetico basato sulle dimensioni definite nel proprio schema.
Quando un compito esiste ed è associato a un carico di lavoro, è possibile generare dei
consigli con la procedura DBMS_ADVISOR.EXECUTE_TASK. SQL Access Advisor prenderà
in considerazione il carico di lavoro e le statistiche del sistema e cercherà di generare dei consi-
gli per la messa a punto dell’applicazione. È possibile vedere i consigli eseguendo la funzione
DBMS_ADVISOR.GET_TASK_SCRIPT o tramite le viste del dizionario dati. Ogni consiglio
può essere visualizzato tramite USER_ADVISOR_RECOMMENDATIONS (sono disponibili
versioni “ALL” e “DBA” di questa vista). Per correlare i consigli a un’istruzione SQL, sarà
necessario ricorrere alla vista USER_ADVISOR_SQLA_WK_STMTS e a USER_ADVISOR_
ACTIONS.
Quando si esegue la procedura GET_TASK_SCRIPT, Oracle genera un file SQL eseguibile
che conterrà i comandi necessari per creare, modificare o eliminare gli oggetti consigliati. Si
consiglia di analizzare lo script generato prima di eseguirlo, prestando particolare attenzione alle
specificazioni relative alle tablespace. Nel paragrafo che segue si vedrà come utilizzare la proce-
dura QUICK_TUNE per semplificare il processo di consiglio di messa a punto per un singolo
comando.
un’istruzione SQL. L’uso di QUICK_TUNE mette al riparo l’utente dai passaggi coinvolti nella
creazione di carichi di lavoro e compiti con DBMS_ADVISOR.
Per esempio, la chiamata a procedura che segue valuta una query:
execute DBMS_ADVISOR.QUICK_TUNE(DBMS_ADVISOR.SQLACCESS_ADVISOR, -
'MV_TUNE','SELECT EDITORE FROM BIBLIOTECA');
NOTA L’utente che esegue questo comando deve disporre del privilegio di siste-
ma ADVISOR.
Poi si segue la procedura CREATE_FILE, che ha tre variabili di input: lo script (generato
tramite GET_TASK_SCRIPT, al quale si passa il nome del compito), la directory di output e il
nome del file da creare:
execute DBMS_ADVISOR.CREATE_FILE(DBMS_ADVISOR.GET_TASK_SCRIPT('MV_TUNE'),-
'SCRIPTS','MV_TUNE.sql');
Il file MV_TUNE.sql creato dalla procedura CREATE_FILE conterrà dei comandi simili a
quelli illustrati nel listato seguente. In relazione alla versione specifica di Oracle, i consigli
possono essere diversi.
set feedback 1
set linesize 80
set trimspool on
set tab off
set pagesize 60
begin
dbms_stats.gather_table_stats('"PRACTICE"',
'"MV$$_021F0001"',NULL,dbms_stats.auto_sample_size);
end;
/
begin
dbms_advisor.mark_recommendation('MV_TUNE',1,'IMPLEMENTED');
end;
/
desc TABELLA_CAPACITA_VM
Nome Null? Type
----------------------------------------- -------- ----------------
ISTRUZIONE_ID VARCHAR2(30)
PROPRIETARIOVM VARCHAR2(30)
NOMEVM VARCHAR2(30)
NOME_CAPACITA VARCHAR2(30)
430 CAPITOLO 24
POSSIBILE CHAR(1)
TESTO_CORRELATO VARCHAR2(2000)
NUME_CORRELATO NUMBER
MSGNO NUMBER(38)
MSGTXT VARCHAR2(2000)
SEQ NUMBER
execute DBMS_MVIEW.EXPLAIN_MVIEW('conta_categoria_locale');
Lo script utlxmv.sql aiuta nell’interpretazione dei valori di colonna, come mostrato nel lista-
to seguente:
NOME_CAPACITA
------------------------------
MSGTXT
------------------------------------------------------------
TABELLA_PCT
la relazione non è una tabella partizionata
432 CAPITOLO 24
REFRESH_FAST_AFTER_INSERT
la tabella dei dettagli non contiene un log delle viste materializzate
REFRESH_FAST_AFTER_ONETAB_DML
vedere perché REFRESH_FAST_AFTER_INSERT è disattivato
REFRESH_FAST_AFTER_ANY_DML
vedere perché REFRESH_FAST_AFTER_ONETAB_DML è disattivato
REFRESH_FAST_PCT
PCT non può essere eseguito su nessuna delle tabelle di dettagli nella vista materializzata
REWRITE_FULL_TEXT_MATCH
la riscrittura delle query è disattivata nella vista materializzata
REWRITE_PARTIAL_TEXT_MATCH
la riscrittura delle query è disattivata nella vista materializzata
REWRITE_GENERAL
riscrittura delle query è disattivata nella vista materializzata
REWRITE_PCT
la riscrittura generale non è consentita e PCT non può essere eseguito su nessuna delle
tabelle di dettagli
PCT_TABLE_REWRITE
la relazione non è una tabella partizionata
10 rows selected.
Dato che la clausola query rewrite non è stata specificata durante la creazione della vista
materializzata, le capacità di riscrittura delle query non sono state attivate per BIBLIOTECA_
LOCALE. Le capacità di aggiornamento rapido non sono supportate perché la tabella base non
ha un log delle viste materializzate. Se si modifica la vista materializzata o la sua tabella base, si
dovrebbero creare nuovamente i dati di TABELLA_CAPACITA_VM per visualizzare le nuove
capacità.
Come illustrato nel listato precedente, la vista materializzata BIBLIOTECA_LOCALE non
può utilizzare un aggiornamento rapido perché la sua tabella di base non ha un logo delle viste
materializzate. Ci sono altri vincoli che limiteranno la capacità di utilizzare gli aggiornamenti
rapidi:
■ La vista materializzata non deve contenere riferimenti a espressioni non ripetute come SysDate
e RowNum.
■ La vista materializzata non deve contenere riferimenti a tipi di dati RAW o LONG RAW.
■ Per le viste materializzate basate su join, i RowID di tutte le tabelle dell’elenco from devono
far parte dell’elenco select.
■ Se ci sono degli outer join, tutti i join devono essere connessi tramite and, la clausola where
non deve avere selezioni, e devono esistere dei vincoli unici sulle colonne di join della tabella di
join interna.
■ Per le viste materializzate basate su aggregati, i log delle viste materializzate devono conte-
nere tutte le colonne delle tabelle di riferimento, devono specificare le clausole rowid e including
new values e devono specificare la clausola sequence.
Per conoscere ulteriori vincoli relativi agli aggiornamenti rapidi di aggregati complessi, si
consulti la Data Warehousing Guide.
USO DELLE VISTE MATERIALIZZATE 433
Aggiornamenti automatici
Si consideri la vista materializzata BIBLIOTECA_LOCALE descritta in precedenza. Le
impostazioni relative agli intervalli di aggiornamento, definite dal comando create materialized
view, sono riportate in grassetto nel listato seguente:
next SysDate+7
Ogni volta che si aggiorna la vista materializzata, l’aggiornamento successivo verrà pianifi-
cato sette giorni dopo. Anche se in questo esempio la programmazione dell’aggiornamento è
piuttosto semplice, è possibile utilizzare numerose funzioni di data di Oracle per personalizzare
la pianificazione degli aggiornamenti. Per esempio, se si desidera eseguire un aggiornamento
ogni lunedì a mezzogiorno, a prescindere dalla data corrente, si può impostare la clausola next a:
NEXT_DAY(TRUNC(SysDate),'MONDAY')+12/24
Così si individua il primo lunedì dopo la data corrente di sistema. La porzione relativa al-
l’ora di tale data viene troncata e vengono aggiunte 12 ore alla data. Per informazioni sulle
funzioni di data in Oracle, si rimanda al Capitolo 10.
Per abilitare gli aggiornamenti automatici delle viste materializzate, occorre fare in modo
che nel database venga eseguito almeno un processo in background per l’aggiornamento delle
viste materializzate. Il processo di aggiornamento si “risveglia” periodicamente e verifica se
qualche vista materializzata del database dev’essere aggiornata. Il numero di processi eseguiti
434 CAPITOLO 24
Aggiornamenti manuali
Oltre agli aggiornamenti automatici del database, è anche possibile eseguire aggiornamenti ma-
nuali delle viste materializzate. Questi sostituiscono gli aggiornamenti pianificati normalmente.
Il nuovo valore di start with si baserà sull’ora dell’aggiornamento manuale.
Per aggiornare un’unica vista materializzata, si utilizza DBMS_MVIEW.REFRESH. I due
parametri principali di questa procedura sono il nome della vista materializzata da aggiornare e
il metodo da utilizzare. Per questo metodo, si può specificare “c” per un aggiornamento comple-
to, “r” per un aggiornamento rapido e “?” per la clausola force. Per esempio:
execute DBMS_MVIEW.REFRESH('biblioteca_locale','c');
NOTA Il Partition Change Tracking (PCT) si verifica quando sono state effettuate
operazioni di manutenzione delle partizioni sulle tabelle cui fa riferimento la vista materializzata.
In PCT Oracle effettua l’aggiornamento ricalcolando le righe della vista materializzata influen-
zate dalle partizioni modificate nelle tabelle dei dettagli, evitando di ricorrere a un aggiorna-
mento completo.
execute DBMS_MVIEW.REFRESH('biblioteca_locale,conta_categoria_locale','?c');
execute DBMS_MVIEW.REFRESH_ALL_MVIEWS;
Dato che le viste materializzate verranno aggiornate tramite REFRESH_ALL una di seguito
all’altra, non potranno essere aggiornate tutte alla stessa ora. Di conseguenza, un guasto al server
o al database durante l’esecuzione di questa procedura potrà provocare la perdita di sincronizza-
zione a livello locale tra una vista materializzata e l’altra. In tal caso sarà sufficiente avviare
nuovamente la procedura, una volta recuperato il database. In alternativa, si possono creare gruppi
di aggiornamento, come descritto nel prossimo paragrafo.
Un’altra procedura all’interno di DBMS_MVIEWS, REFRESH_ALL_MVIEWS, aggiorna
tutte le viste materializzate che hanno le proprietà seguenti:
USO DELLE VISTE MATERIALIZZATE 435
■ La vista materializzata non è stata aggiornata dall’ultima modifica apportata alla tabella
master o alla vista materializzata master da cui dipende.
■ La vista materializzata e tutte le tabelle master o le viste materializzate master da cui dipen-
de sono locali.
■ La vista materializzata si trova nella vista DBA_MVIEWS.
Se si creano viste materializzate nidificate, è possibile utilizzare la procedura DBMS_
MVIEW.REFRESH_DEPENDENT per garantire che tutte le viste materializzate di una struttu-
ra ad albero vengano aggiornate.
Il comando create materialized view log viene eseguito nel database della tabella master, in
genere dal proprietario della tabella master. I log delle viste materializzate non dovrebbero esse-
re creati per tabelle coinvolte solo in viste materializzate complesse (poiché non verrebbero
utilizzate). Per il log delle viste materializzate non viene specificato alcun nome.
Un log delle viste materializzate per la tabella BIBLIOTECA può essere creato con il co-
mando riportato di seguito, eseguito dall’interno dell’account proprietario della tabella.
La clausola with sequence è necessario per supportare la replica delle operazioni DML
miste su più tabelle di base.
Dato che i log delle viste materializzate possono crescere con il tempo in modo imprevedi-
bile, nei database di produzione, sarebbe opportuno memorizzare gli oggetti loro associati in
tablespace dedicate ai log della viste materializzate.
NOTA Quando si elimina una vista materializzata che è stata creata in base a una
tabella precostruita, quest’ultima continua a esistere, mentre la vista materializzata viene elimi-
nata.
I log delle viste materializzate possono essere eliminati tramite il comando drop materialized
view log. Una volta eliminato il log delle viste materializzate da una tabella master, non si po-
tranno più eseguire aggiornamenti rapidi per le viste materializzate semplici basate su questa
tabella. Sarebbe opportuno eliminare un log delle viste materializzate quando nessuna vista
materializzata semplice si basa sulla tabella master. Il comando seguente elimina il log delle
viste materializzate che era stato creato precedentemente sulla tabella BIBLIOTECA:
Per eliminare un log delle viste materializzate, è necessario essere in grado di eliminare sia
il log delle viste materializzate sia gli oggetti a esso correlati. Se si è proprietari del log delle
viste materializzate, si deve disporre dei privilegi di sistema DROP TABLE e DROP TRIGGER.
Se invece non si è proprietari del log delle viste materializzate, è necessario disporre dei privilegi
di sistema DROP ANY TABLE e DROP ANY TRIGGER per eseguire questo comando.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 25
C
on l’aumento della quantità di testo nel database, cresce an-
che la complessità delle query di testo eseguite sul database. Invece di eseguire semplici corri-
spondenze di stringa, ora sono necessarie nuove caratteristiche di ricerca di testo, come l’attribu-
zione di priorità durante ricerche di più termini o l’ordinamento in graduatoria dei risultati di
una ricerca di testo.
Per eseguire ricerche di testo è possibile usare Oracle Text. Tra le capacità di ricerca del
testo ci sono le ricerche con caratteri jolly, le corrispondenze non esatte, gli ordinamenti per
rilevanza, le ricerche di prossimità, la ponderazione dei termini e l’espansione delle parole. In
questo capitolo si imparerà a configurare e utilizzare Oracle Text.
set linesize 74
select Testo_Recensione
from CONTEXT_RECENSIONI_LIBRI
where Titolo = 'MY LEDGER';
TESTO_RECENSIONE
----------------------------------------------------------------------
Un’analisi molto interessante sulle transazioni e le finanze di G. B. Talbot e Dora Talbot
quando intorno al 1900 gestivano una proprietà nel New Hampshire. Le storie passano in
rassegna le spese, per i medicinali, le visite mediche e le tombe, per i lavoratori durante
i raccolti e per i regali di Natale. Un gran bel libro.
NOTA Prima di creare un indice testuale su una tabella, è necessario creare una
chiave primaria per la tabella stessa (se non ne esiste già una).
USO DI ORACLE TEXT PER LE RICERCHE DI TESTO 441
Tramite una versione speciale del comando create index, è possibile creare un indice testua-
le. Per un indice CONTEXT occorre specificare il tipo di indice Ctxsys.Context nella clausola
indextype, come mostrato nel listato seguente:
Una volta creato l’indice testuale, Oracle genera diversi indici e tabelle nello schema del-
l’utente per supportare le query sul testo. È possibile ricostruire l’indice testuale con il comando
alter index, come si farebbe con un qualunque altro indice.
Si può anche sostituire il tipo di indice CONTEXT con il tipo di indice CTXCAT:
Il tipo di indice CTXCAT supporta la sincronizzazione transazionale dei dati tra la tabella
base (CTXCAT_RECENSIONI_LIBRI) e il suo indice testuale. Con gli indici CONTEXT è
necessario comunicare manualmente a Oracle di aggiornare i valori nell’indice testuale dopo le
modifiche dei dati apportate alla tabella base. I tipi di indici CTXCAT non creano valori di
“punteggio” durante le query sul testo (come invece avviene con gli indici CONTEXT), ma la
sintassi della query è davvero molto simile per entrambi i tipi di indici. I prossimi paragrafi
illustrano i vari tipi di query di testo che è possibile eseguire con Oracle Text.
select Titolo
from CONTEXT_RECENSIONI_LIBRI
where CONTAINS(Testo_Recensione, 'proprietà') >0;
La funzione CONTAINS accetta due parametri, il nome della colonna e la stringa di ricerca,
e controlla l’indice testuale per la colonna Testo_Recensione. Se nell’indice testuale della colon-
na Testo_Recensione viene individuata la parola ‘proprietà’, il database restituirà un punteggio
maggiore di zero e il valore di Titolo corrispondente. Il punteggio rappresenta una valutazione
della corrispondenza del record restituito con i criteri specificati nella funzione CONTAINS.
Se si crea un indice CTXCAT, occorre utilizzare la funzione CATSEARCH al posto di
CONTAINS. CATSEARCH accetta tre parametri: il nome della colonna, la stringa di ricerca e il
nome del gruppo di indici. I gruppi di indici sono descritti nel paragrafo “Gruppi di indici” più
avanti nel capitolo. Per questo esempio non viene utilizzato nessun gruppo di indici, quindi il
parametro corrispondente è impostato a NULL:
select Titolo
from CTXCAT_RECENSIONI_LIBRI
where CATSEARCH(Testo_Recensione, 'proprietà', NULL) >0;
442 CAPITOLO 25
All’interno delle chiamate a funzione, il simbolo > viene detto operatore di soglia. La pre-
cedente ricerca di testo può essere tradotta nel modo seguente:
USO DI ORACLE TEXT PER LE RICERCHE DI TESTO 443
TITOLO PUNTEGGIO(10)
------------------------------ -------------
MY LEDGER 3
In questo listato, i parametri della funzione CONTAINS vengono modificati per contenere
un’etichetta (‘10’) per l’operazione di ricerca di testo eseguita. La funzione SCORE visualizza il
punteggio della ricerca di testo associata a tale etichetta. Il punteggio è un calcolo interno basato
sulla misura in cui il testo indicizzato corrisponde ai criteri di ricerca.
Per gli indici CONTEXT, è possibile utilizzare la funzione SCORE nell’elenco select (come
nella query precedente), in una clausola group by o in una clausola order by.
NOTA Questa query non cerca la frase “proprietà e raccolti”, bensì le due singo-
le parole all’interno di tutto il testo esaminato. Nel prossimo paragrafo si analizzerà la sintassi
per le ricerche di frasi.
Nella query sull’indice CONTEXT, al posto di AND si sarebbe potuto usare il simbolo della
e commerciale (&). Prima di usare questo metodo in SQL*Plus, si consiglia di impostare il
comando set define off in modo che il carattere & non compaia come parte del nome di una
variabile:
L’uso del carattere & o della parola AND denota un’operazione AND, pertanto la funzione
CONTAINS restituisce una riga solo se il testo della recensione include entrambe le parole “pro-
prietà” e “raccolti”. Ciascuna ricerca dovrà superare i criteri di soglia definiti per i punteggi di
ricerca. Per cercare più di due termini, sarà sufficiente aggiungerli alla clausola CONTAINS o
CATSEARCH, come mostrato nel listato seguente:
La query di questo listato restituisce una riga solo se i punteggi di ricerca per “proprietà”,
“raccolti” e “lavoratori” sono tutti maggiori di 0.
Oltre ad AND, è possibile utilizzare l’operatore OR, nel qual caso viene restituito un record
se una delle condizioni di ricerca soddisfa la soglia definita. In Oracle Text, il simbolo per l’ope-
ratore OR è una barra verticale (|), quindi le due query seguenti sono elaborate allo stesso modo.
select Titolo
from CONTEXT_RECENSIONI_LIBRI
where CONTAINS(Testo_Recensione, 'proprietà | raccolti')>0;
USO DI ORACLE TEXT PER LE RICERCHE DI TESTO 445
Quando si eseguono queste query, viene restituito un record se una delle due ricerche sepa-
rate (“proprietà” e “raccolti”) restituisce un punteggio maggiore di 0.
select Titolo
from CTXCAT_RECENSIONI_LIBRI
where CATSEARCH(Testo_Recensione, 'proprietà OR raccolti', NULL)>0;
select Titolo
from CTXCAT_RECENSIONI_LIBRI
where CATSEARCH(Testo_Recensione, 'proprietà | raccolti', NULL)>0;
select Titolo
from CONTEXT_RECENSIONI_LIBRI
where CONTAINS(Testo_Recensione, 'proprietà , raccolti')>0;
select Titolo
from CONTEXT_RECENSIONI_LIBRI
where CONTAINS(Testo_Recensione, 'proprietà - casa')>0;
Al posto dell’operatore MINUS è possibile inserire il simbolo ‘–’, come mostrato nel listato
precedente.
Per gli indici CONTEXT, l’operatore – riduce il punteggio quando si confronta il punteggio
di ricerca totale con il valore di soglia, ma non smette di considerare la riga in questione. Per
446 CAPITOLO 25
eliminare le righe in base ai termini di ricerca negli indici CONTEXT, occorre utilizzare il carat-
tere ~ come operatore NOT.
Per gli indici CTXCAT, il simbolo – ha un significato diverso di quello che assume per gli
indici CONTEXT. Nel caso degli indici CTXCAT, – comunica a Oracle Text di non restituire la
riga se il termine di ricerca si trova dopo – (come ~ negli indici CONTEXT). Se si trova il
secondo termine, CATSEARCH non restituisce la riga. Per le query CATSEARCH, è possibile
sostituire “–” con la parola NOT.
select Titolo
from CTXCAT_RECENSIONI_LIBRI
where CATSEARCH(Testo_Recensione, 'proprietà - raccolti', NULL)>0;
select Titolo
from CTXCAT_RECENSIONI_LIBRI
where CATSEARCH(Testo_Recensione, 'proprietà NOT raccolti', NULL)>0;
Per rendere più chiara la logica dei criteri di ricerca è possibile utilizzare le parentesi. Se la
ricerca contiene sia operatori AND sia operatori OR, è opportuno inserire delle parentesi per
rendere più chiaro il modo in cui le righe vengono elaborate. Per esempio, la query seguente
restituisce una riga se il testo esaminato contiene la parola ‘casa’ o contiene entrambe le parole
‘lavoratori’ e ‘raccolti’.
CATSEARCH non richiede l’inserimento della parola AND tra i termini “lavoratori” e “rac-
colti”:
Modificando la posizione delle parentesi si modifica anche la logica della ricerca di testo.
La query seguente restituisce una riga se il testo esaminato contiene la parola ‘casa’ o la parola
‘lavoratori’ e contiene anche la parola ‘raccolti’:
select Titolo
from CONTEXT_RECENSIONI_LIBRI
where CONTAINS(Testo_Recensione, '(casa OR lavoratori) AND raccolti')>0;
Quando si valutano i punteggi di più ricerche negli indici CONTEXT, si può comunicare a
Oracle Text di valutare i punteggi di alcune ricerche come più importanti di altri. Per esempio, se
si desidera che il punteggio di ricerca del termine ‘raccolti’ valga il doppio quando confrontato
con il punteggio di soglia, si può utilizzare il simbolo asterisco (*) per indicare il fattore per cui
il punteggio di ricerca dev’essere moltiplicato.
La query seguente raddoppia il punteggio di ricerca per ‘raccolti’ nella valutazione all’inter-
no di una condizione OR.
USO DI ORACLE TEXT PER LE RICERCHE DI TESTO 447
Grazie agli operatori AND, OR, ACCUM e MINUS è possibile ricercare qualsiasi combina-
zione di corrispondenze dei termini.
NOTA L’operatore EQUIV tratta due termini di ricerca come uguali durante l’as-
segnazione del punteggio della ricerca. EQUIV (che può essere sostituito con =) può essere utile
in combinazione con gli operatori che confrontano i punteggi della ricerca.
La query seguente presuppone che la recensione sia in inglese e cerca la frase ‘transactions
and finances’. La parola ‘and’ è racchiusa tra parentesi graffe.
La query ‘transactions {and} finances’ è diversa dalla query ‘transactions and finances’. La
query ‘transactions {and} finances’ restituisce un record solo se nel testo esaminato esiste la
frase ‘transactions and finances’. La query ‘transactions and finances” restituisce un record se il
punteggio di ricerca del termine “transactions” e quello del termine “finances” superano entram-
bi il punteggio di soglia (o con un indice CTXCAT, se si trovano entrambi).
448 CAPITOLO 25
È possibile racchiudere l’intera frase tra parentesi graffe, nel qual caso qualsiasi parola riser-
vata all’interno della frase stessa verrà trattata come parte del criterio di ricerca, come mostrato
nell’esempio seguente:
L’operatore NEAR può essere sostituito con il suo simbolo equivalente, il punto e virgola (;).
Di seguito è riportata la query modificata:
Nelle query sugli indici CONTEXT è possibile specificare il numero massimo di parole tra
i termini di ricerca. Per esempio, per le parole separate da dieci termini, si potrebbe applicare
una stringa di ricerca come ‘NEAR((lavoratori, raccolti),10)’.
I metodi di ricerca di frasi e parole descritti in questo capitolo possono essere utilizzati per
cercare corrispondenze esatte di parole e frasi e per effettuare ricerche di prossimità di parole e
frasi esatte. Finora tutte le ricerche hanno utilizzato come base corrispondenze esatte dei termini
cercati. Nei prossimi quattro paragrafi, si imparerà a espandere i termini di ricerca tramite quat-
tro metodi: caratteri jolly, radici delle parole, corrispondenze non esatte e ricerche SOUNDEX.
CARATTERE DESCRIZIONE
% Simbolo di percentuale: carattere jolly che sta per più caratteri.
La query seguente cerca tutte le corrispondenze di testo per tutte le parole che iniziano con
i caratteri ‘lavor’.
La query seguente limita l’espansione della stringa di testo esattamente a tre caratteri. Al
posto del simbolo di percentuale %, utilizzato nella query precedente, vengono inseriti tre tratti-
ni di sottolineatura (_ _ _). Dato che il trattino di sottolineatura è un carattere jolly per il singolo
carattere, durante la ricerca la stringa di testo non potrà espandersi oltre i tre caratteri. Per esem-
pio, la ricerca di testo potrebbe restituire la parola ‘lavoro’, mentre la parola ‘lavoratore’ è troppo
lunga per essere restituita.
I caratteri jolly devono essere utilizzati quando si è certi della presenza di alcuni caratteri
all’interno della stringa di ricerca. Se non si è sicuri della stringa di ricerca, è possibile utilizzare
uno dei metodi descritti nei paragrafi seguenti: radici delle parole, corrispondenze non esatte o
corrispondenze SOUNDEX.
story stories
Dato che ‘works’ e ‘work’ hanno la stessa radice, una ricerca con espansione etimologica
che utilizza la parola ‘works’ restituirà anche il testo contenente la parola ‘work.’
450 CAPITOLO 25
Per usare l’espansione etimologica all’interno di una query, occorre inserire il simbolo del
dollaro ($), che nella stringa di ricerca deve precedere immediatamente la parola da espandere.
Il listato seguente mostra il risultato di una query eseguita sulla tabella
CONTEXT_RECENSIONI_LIBRI per tutte le recensioni che contengono una parola che condi-
vide la radice della parola “manage”:
Quando si esegue questa query, Oracle espande la parola “$manage” fino a includere tutte le
parole che hanno la stessa radice, quindi esegue la ricerca. Se una recensione include una delle
parole con una radice “manage”, il record verrà restituito all’utente.
L’espansione dei termini di ricerca tramite le radici delle parole semplifica il processo di
query. Non è più necessario sapere in quale forma un verbo o un termine sia stato utilizzato al
momento dell’inserimento del testo: tutte le forme serviranno come base per la ricerca. Non è
necessario specificare stringhe di testo particolari, come avviene per le query relative a corri-
spondenze esatte o quando si utilizzano i caratteri jolly. È sufficiente specificare una parola, e
Oracle Text determinerà dinamicamente tutte le parole che devono essere cercate, basandosi su
quella specificata.
Tuttavia, contiene la parola “raccolti”. Una corrispondenza non esatta restituirà le recensio-
ni contenenti la parola ‘raccolti’ anche se ha una radice di parola differente da quella della parola
utilizzata come termine di ricerca.
Per usare una corrispondenza non esatta, è necessario anteporre al termine di ricerca un
punto interrogativo, senza spazi tra il punto di domanda e l’inizio del termine di ricerca. L’esem-
pio seguente illustra l’uso della capacità di corrispondenza non esatta:
Se una recensione contenesse la parola “great”, verrebbe restituita come risultato, in quanto
le parole “grate” e “great” hanno lo stesso valore SOUNDEX.
Gli operatori possono anche essere nidificati, consentendo l’esecuzione di espansioni eti-
mologiche sui termini restituiti da una corrispondenza non esatta. Nell’esempio seguente, viene
eseguita una corrispondenza non esatta della parola ‘stir’. I termini restituiti dalla corrisponden-
za non esatta vengono quindi ampliati utilizzando l’espansione etimologica.
Le principali opzioni di ricerca per la funzione CONTAINS sono riassunte nella Tabella 25.1.
Per un elenco di tutta la sintassi supportata (incluso l’uso del thesaurus, l’espansione dei sinoni-
mi e il supporto XML), si consulti la guida Oracle Text Reference. Le opzioni di ricerca della
funzione CATSEARCH sono elencate nella Tabella 25.2. Questa tabella non elenca le caratteri-
stiche di CONTAINS disapprovate, come ACCUM, che non sono documentate come caratteristi-
che supportate per CATSEARCH.
| Come OR.
AND Restituisce un record se entrambi i termini di ricerca hanno un punteggio superiore alla soglia.
ACCUM Restituisce un record se la somma dei punteggi dei termini di ricerca supera la soglia.
, Come ACCUM.
MINUS Restituisce un record se il punteggio della prima ricerca meno quello della seconda supera la soglia.
– Come MINUS.
NEAR Il punteggio sarà basato sulla vicinanza dei termini di ricerca nel testo.
; Come NEAR.
~ Come NOT.
EQUIV Tratta due termini (termine1 equiv termine2) come uguali nella determinazione del punteggio della ricerca.
= Come EQUIV.
{} Racchiude le parole riservate come AND se fanno parte del termine di ricerca.
$ Esegue l’espansione della radice del termine di ricerca prima di eseguire la ricerca stessa.
AND Restituisce un record se trova entrambi i termini di ricerca. Questa è l’azione predefinita, quindi
(a b) viene trattato come (a AND b).
– Restituisce le righe che contengono il termine che precede l’operatore “–” e che non contengono il
termine che lo segue.
NOT Identico a –.
Testo_Recensione viene aggiornato, il suo indice testuale non è più sincronizzato con la tabella
base. Per sincronizzare l’indice, è necessario eseguire la procedura SYNC_INDEX del package
CTX_DDL, come mostrato nel listato seguente.
execute CTX_DDL.SYNC_INDEX(‘CONTEXT_INDICE_RECENSIONI’);
A partire da Oracle Database 10g, gli indici CONTEXT possono essere mantenuti automa-
ticamente, al momento della conferma o a intervalli specificati. Come parte del comando create
index per un indice CONTEXT, è possibile utilizzare la clausola sync:
Ecco un esempio:
Per creare un gruppo di indici, si utilizza il package CTX_DDL, che serve per creare il
gruppo di indici e aggiungere a quest’ultimo degli indici. Quando si crea un indice testuale, è
possibile specificare il gruppo di indici al quale appartiene. Per eseguire questo esempio, per
prima cosa si dovrebbe eliminare l’indice testuale CTXCAT_INDICE_RECENSIONI (creato in
precedenza in questo capitolo) sulla tabella CTXCAT_RECENSIONI_LIBRI:
execute CTX_DDL.CREATE_INDEX_SET(‘Recensioni’);
Ora si possono aggiungere degli indici al gruppo di indici tramite la procedura ADD_INDEX.
Per prima cosa, si aggiunga un indice non testuale standard:
Ora, si crei un indice testuale CTXCAT, specificando Ctxsys.Ctxcat come tipo di indice ed
elencando il gruppo di indici nella clausola parameters:
Ora, si possono ordinare i risultati in base al risultato della ricerca di gruppi di indici combi-
nata.
Per risolvere questa query, Oracle Text utilizzerà il gruppo di indici concedendo la possibi-
lità di ordinare i risultati in modo corretto. Si osservi che intorno alla stringa ‘EMILY TALBOT’
ci sono delle virgolette perché si tratta della ricerca di una stringa di testo; quando si esegue la
query queste virgolette verranno convertite in un gruppo di apici.
I gruppi di indici possono contenere fino a 99 indici sui tipi di dati NUMBER, DATE,
CHAR e VARCHAR2. Nessuna colonna, in un indice che faccia parte di un gruppo di indici, può
superare i 30 byte (pertanto, in questo esempio la colonna Titolo non potrà essere indicizzata
come parte di un gruppo di indici). Le colonne indicizzate non devono contenere valori NULL.
A partire da Oracle Database 10g, Oracle Text include uno strumento che aiuta a identificare
i colli di bottiglia nell’indicizzazione e nell’interrogazione. Per abilitare questa funzionalità si
ricorre alla procedura ADD_TRACE del package CTX_OUTPUT. Tra li indicazioni disponibili
ci sono il tempo dedicato ai diversi componenti della ricerca, il numero di byte letti e il numero
di righe elaborate.
Per ulteriori dettagli sui gruppi di indici, la gestione degli indici testuali, lo sviluppo di
applicazioni di testo e la funzionalità di identificazione, si consulti la Oracle Text Application
Developer’s Guide e la Oracle Text Reference, entrambe fornite come parte della documentazio-
ne standard di Oracle.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 26
O
racle consente di utilizzare la funzionalità delle tabelle esterne,
con le quali è possibile accedere ai file esterni come se questi fossero tabelle contenute nel
database. Quando si crea una tabella esterna, la sua struttura viene definita insieme alla sua
posizione in Oracle. Quando si interroga la tabella, Oracle legge la tabella esterna e restituisce i
risultati come se i dati fossero stati memorizzati nel database. Dal momento però che i dati non
sono nel database, non ci si dovrà preoccupare di caricarli nel database, un vantaggio che potrebbe
essere davvero notevole per le data warehouse e per i database di grandi dimensioni.
Le tabelle esterne hanno dei limiti; infatti non è possibile aggiornare o cancellare le loro
righe dall’interno di Oracle e non si può neppure indicizzarle. Dato che fanno parte delle
applicazioni di database, le si dovrà considerare come parti integranti dei processi di backup e di
recupero. Nonostante queste complicazioni, le tabelle esterne possono essere un’aggiunta davvero
potente ai piani dell’architettura del database. A partire da Oracle Database 10g, è possibile
utilizzare le tabelle esterne per scaricare dati da tabelle a file esterni attraverso il driver di accesso
ORACLE_DATAPUMP.
L’esempio seguente crea una directory di nome LIBRO_DIR e concede gli accessi READ e
WRITE allo schema PRACTICE:
Ora l’utente PRACTICE può leggere i file nella directory e:\oracle\external come se fossero
contenuti nel database. Dato che a PRACTICE è stato concesso anche il privilegio WRITE in
456 CAPITOLO 26
quella directory, l’utente PRACTICE potrà creare file di log, file di scarto e file non validi nella
directory, come se stesse eseguendo l’utility SQL*Loader (si consulti il Capitolo 21).
Il listato seguente genera due file per dei dati di esempio, uno tratto da BIBLIOTECA e uno
da BIBLIOTECA_AUTORE. Si osservi che il comando spool non può utilizzare il nome della
directory creata con create directory; si dovrà specificare il nome completo della directory del
sistema operativo.
connect practice/practice
spool e:\oracle\external\bookshelf_dump.lst
/
spool off
select Titolo||'~'||NomeAutore||'~'
from BIBLIOTECA_AUTORE
order by Titolo
spool e:\oracle\external\book_auth_dump.lst
/
spool off
Oltre ai dati, i file di output conterranno anche una singola linea iniziale con il simbolo
“SQL>/” e una linea finale che riporta “SQL> spool off”. Per semplificare gli esempi, prima di
procedere è consigliabile modificare manualmente il file a livello di sistema operativo per eliminare
queste linee di troppo.
Se un altro utente deve poter accedere ai dati contenuti nei file bookshelf_dump.lst e
book_auth_dump.lst, gli si dovrà concedere il privilegio READ nella directory LIBRO_DIR:
I file stessi dovranno anche essere leggibili da parte dell’utente Oracle a livello di sistema
operativo.
Editore VARCHAR2(20),
NomeCategoria VARCHAR2(20),
Classificazione VARCHAR2(2)
)
organization external
(type ORACLE_LOADER
default directory LIBRO_DIR
access parameters (records delimited by newline
fields terminated by "~"
(Titolo CHAR(100),
Editore CHAR(20),
NomeCategoria CHAR(20),
Classificazione CHAR(2)
))
location ('bookshelf_dump.lst')
);
Table created.
anche se nel database Oracle non saranno stati creati dei dati.
Analogamente, è possibile creare una tabella basata sul file di spool book_auth_dump.lst:
NOTA Quando si crea la tabella esterna, Oracle eseguirà solamente delle convalide
sommarie. La maggior parte degli errori non sarà visibile fino a quando non si cercherà di
interrogare la tabella. La sintassi per i parametri di accesso è molto specifica e degli errori
anche non gravi nella definizione dell’accesso, compreso l’ordine delle clausole, potrebbero
impedire l’accesso a tutte le righe.
È possibile verificare il contenuto delle tabelle esterne eseguendo una query partendo dalle
medesime e confrontandole con le tabelle di origine, come mostrato nel listato seguente:
TITOLO
-----------------------------------------
GOOD DOG, CARL
POLAR EXPRESS
RUNAWAY BUNNY
458 CAPITOLO 26
3 rows selected.
TITOLO
-------------------------------------------
GOOD DOG, CARL
POLAR EXPRESS
RUNAWAY BUNNY
3 rows selected.
COUNT(*)
----------
37
COUNT(*)
----------
37
no rows selected
desc USER_EXTERNAL_TABLES
REJECT_LIMIT VARCHAR2(40)
ACCESS_TYPE VARCHAR2(7)
ACCESS_PARAMETERS VARCHAR2(4000)
PROPERTY VARCHAR2(10)
select Default_Directory_Name,
Access_Parameters
from USER_EXTERNAL_TABLES
where Table_Name = 'BIBLIOTECA_AUTORE_EXT';
DEFAULT_DIRECTORY_NAME
------------------------------
ACCESS_PARAMETERS
------------------------------------------------
LIBRO_DIR
records delimited by newline
fields terminated by "~"
(Titolo CHAR(100),
NomeAutore CHAR(50)
)
USER_EXTERNAL_TABLES non mostra il nome del file esterno (o dei file) cui fa
riferimento la tabella. Per visualizzare questa informazione, è necessario interrogare
USER_EXTERNAL_LOCATIONS:
TABLE_NAME
------------------------------
LOCATION
---------------------------------------------
DIR DIRECTORY_NAME
--- ------------------------------
BIBLIOTECA_EXT
bookshelf_dump.lst
SYS LIBRO_DIR
BIBLIOTECA_AUTORE_EXT
book_auth_dump.lst
SYS LIBRO_DIR
Per le tabelle esterne, il driver di accesso è l’API utilizzata per trasformare i dati esterni. Per
le tabelle esterne, si utilizzi il componente type ORACLE_LOADER, come mostrato negli esempi
precedenti di questo capitolo, o ORACLE_DATAPUMP se si usa Data Pump (consultare il
Capitolo 22). Il driver ORACLE_DATAPUMP consente di scaricare i dati in una tabella esterna
e di ricaricarli in un database Oracle. È necessario specificare il driver di accesso
ORACLE_DATAPUMP se si utilizza la clausola as subquery per scaricare i dati da un database
e ricaricarli in un altro. Il driver di accesso type ORACLE_LOADER è quello predefinito.
NOTA Dato che il driver di accesso fa parte del software Oracle, solamente ai file
che sono accessibili dal database si potrà accedere come tabelle esterne. I file cui gli utenti
Oracle non possono accedere non potranno essere utilizzati come tabelle esterne.
Dopo la dichiarazione di type è possibile impostare un valore “reject limit”. Per default,
nessuna riga può essere rifiutata; qualsiasi tipo di problema con una riga qualunque comporterà
la restituzione da parte dell’istruzione select di un errore. Si crei un’altra copia dei dati di
BIBLIOTECA in un file separato, ma questa volta si dovranno lasciare nel file le linee aggiuntive
che SQL*Plus inserisce durante l’operazione spool:
spool e:\oracle\external\bookshelf_dump_2.lst
/
spool off
Ora si crei una nuova tabella che fa riferimento a questo file di spool, comunicando a Oracle
di saltare il primo record (skip 1) e di consentire un altro errore (reject limit 1). Ciò spiega il
simbolo “/” nella prima linea, e “SQL> spool off” nell’ultima linea:
COUNT(*)
----------
31
La clausola default directory specifica quale oggetto di directory utilizzare per tutti quei file
di dati che non specificano un’altra directory. Se si usano più file esterni collocati in più directory,
si potrà chiamare una di queste come directory predefinita e specificare le altre con nomi di
directory nella clausola location. Nella clausola location si dovranno usare nomi di oggetti di
directory (come LIBRO_DIR), e non il percorso della directory completo.
access parameters
La clausola access parameters comunica a Oracle come associare le righe contenute nel file alle
righe contenute nella tabella. La sua sintassi è mostrata nell’illustrazione seguente:
CHARACTERSET string
LITTLE
DATA IS ENDIAN
BIG
CHECK
BYTEORDERMARK
NOCHECK
BYTES
STRING SIZES ARE IN
CHARACTERS
LOAD WHEN condition_spec
FIXED
integer
NOBADFILE
VARIABLE
RECORDS directory object name :
NEWLINE
DELIMITED BY BADFILE filename
string
NODISCARDFILE
NOLOGFILE
READSIZE
DATE_CACHE integer
SKIP
Nella clausola access parameters per prima cosa si comunica a Oracle come creare un
record, se la sua lunghezza è fissa o variabile, e poi come sono delimitate le righe. Nel caso
dell’esempio di BIBLIOTECA_EXT, i record sono delimitati da nuove linee. Se in una linea
singola ci fossero più righe, si potrebbe usare una stringa di caratteri come separatore per le varie
462 CAPITOLO 26
righe. Visto che i dati esterni potrebbero arrivare da un database non Oracle, Oracle supporta più
set di caratteri e più dimensioni di stringa.
Come accadeva con SQL*Loader, esiste la possibilità di specificare una clausola when per
limitare le righe da selezionare. Nel listato seguente, viene creata la tabella BIBLIOTECA_EXT_3,
con una clausola when (scritta in grassetto) per limitarla ai soli libri contenuti nella categoria
ILLUSRAGAZZI.
Ecco il risultato:
SUBSTR(TITOLO,1,30) NOMECATEGORIA
------------------------------ --------------------
GOOD DOG, CARL ILLUSRAGAZZI
POLAR EXPRESS ILLUSRAGAZZI
RUNAWAY BUNNY ILLUSRAGAZZI
3 rows selected.
Se non si specificano delle posizioni per i file di log, i file non validi e i file di scarto, Oracle li
creerà nella directory predefinita con nomi generati dal sistema.
Nella clausola access parameters si dovranno specificare anche definizioni e delimitatori di
campo, come:
Per impostare i valori per i valori di colonna NULL si può ricorrere alla clausola missing field
values are null, tuttavia occorre prestare molta attenzione quando si usa questa opzione. Per
esempio, la tabella AUTORE ha dei valori NULL nella colonna Commenti. La creazione di una
tabella esterna per AUTORE_EXT è mostrata nel listato seguente:
spool e:\oracle\external\author_dump.lst
/
spool off
NOMEAUTORE
--------------------------------------------------
SOREN KIERKEGAARD
STEPHEN AMBROSE
464 CAPITOLO 26
4 rows selected.
A causa della presenza della clausola missing field values are null, la linea “SQL> spool off”
alla fine del listato è stata letta come un valore di NomeAutore, con un valore NULL per la
colonna Commenti. Ciò evidenzia il problema legato alle eccezioni di codifica nelle definizioni
di SQL*Loader: occorre essere assolutamente certi di aver capito bene i dati di origine e il modo
in cui SQL*Loader li tratterà. Nella maggior parte dei casi l’integrità dei dati verrà garantita
meglio costringendo le righe a fallire (in file non validi o di scarto) e valutando le righe fallite
separatamente dai caricamenti generali.
Per la sintassi completa disponibile per la clausola access parameters, fare riferimento alla
voce SQL*Loader nel Capitolo 48.
location
Nella clausola location si specificano i file di dati da utilizzare come dati di origine per la tabella.
Nella clausola location è possibile nominare più file se si trovano tutti in oggetti directory per i
quali l’utente possiede il privilegio READ. L’esempio seguente associa due file di spool di
BIBLIOTECA separati per illustrare la capacità di combinare più file in un’unica tabella esterna:
L’ordine dei file è importante: skip 1 si applica al primo file e non al secondo. Il secondo file,
bookshelf_dump.lst, è il file che è stato modificato in precedenza per eliminare le righe non di
dati nella prima e nell’ultima riga. Il risultato, che riproduce le righe in entrambi, è visibile nel
listato seguente:
COUNT(*)
----------
62
USO DI TABELLE ESTERNE 465
Parametri di accesso
È possibile modificare i parametri di accesso senza dover eliminare e ricreare la definizione
della tabella esterna, conservando in tal modo concessioni di privilegi, definizioni di file e così
via. Per esempio, ecco come aumentare il numero di record da saltare nella tabella
BIBLIOTECA_EXT_4:
COUNT(*)
----------
53
add column
È possibile utilizzare la clausola add column del comando alter table per aggiungere una colonna
alla tabella esterna ricorrendo alla stessa sintassi impiegata per le tabelle standard.
default directory
È possibile utilizzare la clausola default directory del comando alter table per cambiare la directory
predefinita per i file esterni cui accede la tabella. La directory dev’essere creata con il comando
create directory.
drop column
È possibile utilizzare la clausola drop column del comando alter table per eliminare una colonna
dalla tabella esterna ricorrendo alla stessa sintassi impiegata per le tabelle standard. I dati nel file
rimangono immutati.
location
È possibile cambiare i file cui accede la tabella esterna con la clausola location del comando alter
table. Si può usare questa opzione per aggiungere nuovi file all’elenco o cambiare l’ordine in cui
la tabella esterna accede ai file.
modify column
È possibile utilizzare la clausola modify column del comando alter table per modificare una
colonna della tabella esterna ricorrendo alla stessa sintassi impiegata per le tabelle standard.
parallel
È possibile utilizzare la clausola parallel del comando alter table per cambiare il grado di
parallelismo per la tabella esterna ricorrendo alla stessa sintassi impiegata per le tabelle standard.
466 CAPITOLO 26
project column
La clausola project column del comando alter table comunica al driver di accesso come convalidare
le righe nelle query successive. Se si utilizza l’opzione project column referenced, il driver di
accesso elabora solo le colonne selezionate dalla query. Se poi si interroga un gruppo di colonne
diverso della tabella esterna, i risultati potrebbero non essere coerenti con quelli della prima
query. Se si usa l’opzione project column all, il driver di accesso elabora tutte le colonne definite
sulla tabella esterna, producendo un gruppo di risultati coerente. L’opzione predefinita è project
column referenced.
reject limit
È possibile utilizzare la clausola reject limit del comando alter table per cambiare il numero
consentito di righe rifiutate per la tabella esterna. Ecco un esempio:
rename to
È possibile utilizzare la clausola rename del comando alter table per cambiare il nome della
tabella esterna ricorrendo alla stessa sintassi impiegata per le tabelle standard. Ecco un esempio:
In una tabella esterna non è possibile specificare dei vincoli. Persino il tentativo di creare un
vincolo NOT NULL o quello di una chiave esterna avrà esito negativo:
Se nell’architettura del database si utilizzano tabelle esterne, ci si dovrà accertare che i piani
di backup e recupero tengano conto di questi file oltre al resto del database. Se i file esterni
cambiano più rapidamente di quelli del database, potrebbe essere necessario eseguire dei backup
con maggior frequenza per sfruttare le capacità di recupero completo di Oracle.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 27
C
ome parte del proprio modello di coerenza in lettura, Oracle
visualizza i dati che sono stati destinati al database in seguito a transazioni confermate con un
comando commit. A partire da Oracle9i è possibile eseguire query dei dati così com’erano prima
che venisse eseguita una transazione. Se accidentalmente si eseguono un aggiornamento o una
cancellazione errati, si potrà ricorrere a questa capacità, chiamata query flashback, per visualizzare
i dati com’erano prima dell’esecuzione. I risultati della query flashback potranno servire per
ripristinare i dati.
Per consentire l’uso delle query flashback, il database deve implementare gli undo gestiti a
livello di sistema, una caratteristica introdotta con Oracle9i automatizzare la gestione dei seg-
menti di rollback; per verificare se questa caratteristica è stata abilitata nel proprio ambiente, si
consulti il DBA, il quale dovrà creare una tablespace di undo, abilitare la gestione automatica
degli annullamenti (AUM) e stabilire una finestra con il tempo di conservazione degli undo. Le
query flashback possono essere eseguite nei confronti di database remoti.
NOTA Per maggiori dettagli sulle attività del DBA necessarie a consentire le query
flashback, si rimanda al Capitolo 46.
Oracle cercherà di mantenere informazioni di undo sufficienti nella tablespace di undo allo
scopo di supportare le query flashback durante il periodo di conservazione degli undo.
L’impostazione del tempo di conservazione e la quantità di spazio disponibile nella tablespace di
undo possono influire significativamente sulla capacità di eseguire con successo una query
flashback.
NOTA Oracle usa gli undo per eseguire il rollback delle transazioni e per suppor-
tare le query flashback. Oracle usa i redo (catturati nei redo log file in linea) per applicare le
transazioni durante i recuperi del database.
Le query flashback sono strumenti importanti per i tentativi di recupero parziale. In genere,
quando si progetta un’applicazione, le query flashback non dovrebbero essere considerate come
parte del progetto a causa della loro dipendenza da elementi di sistema che esulano dal controllo
dello sviluppatore dell’applicazione (come il numero di transazioni eseguite in un certo lasso di
tempo e la dimensione della tablespace di undo). Al contrario, le si dovrebbe trattare come
un’opzione durante fasi difficili di recupero, supporto e verifica dei dati. Per esempio, potrebbe-
470 CAPITOLO 27
ro servire per creare copie di tabelle in più punti ormai passati in modo da utilizzarle per rico-
struire i dati modificati.
NOTA Per usare alcune caratteristiche delle query flashback, è necessario di-
sporre del privilegio EXECUTE nel package DBMS_FLASHBACK. La maggior parte degli utenti
non avrà bisogno di privilegi per questo package.
6 rows selected.
Come si possono ricostruire i record dei libri non ricevuti partendo dalla tabella
LIBRO_ORDINE, dato che si possiedono solo i libri ricevuti? Si potrebbe effettuare un recupero
del database utilizzando Data Pump Import (Capitolo 22) per ripristinare la tabella, oppure pro-
cedere a un recupero fisico del database per riportarlo a un punto nel tempo precedente alla
cancellazione. Tuttavia le query flashback consentono di evitare l’esecuzione di tutte queste
operazioni di recupero.
Innanzi tutto, si esegua la query sui dati vecchi partendo dal database. A partire da Oracle9i
Release 2 si possono utilizzare le clausole as of timestamp e as of scn del comando select per
specificare quanto lontano deve spingersi Oracle per il flashback dei dati.
NOTA Nella prima release di Oracle9i, la 9.0.1, questa sintassi non è supportata;
è necessario eseguire procedure contenute nel package DBMS_FLASHBACK e scrivere cicli
PL/SQL per effettuare qualunque transazione che si basi sui dati.
COUNT(*)
----------
0
USO DELLE QUERY FLASHBACK 471
COUNT(*)
----------
6
Quando si esegue una query flashback, solo lo stato dei dati subisce una modifica. Si utiliz-
zano l’ora di sistema corrente (come si può notare eseguendo la query del valore SysDate) e il
dizionario dati corrente. Se la struttura della tabella è cambiate, la query non riuscirà.
Table created.
COUNT(*)
----------
6
6 rows selected.
472 CAPITOLO 27
È poi possibile lavorare con i dati per ripristinare quelli mancanti, effettuare aggiornamenti
selettivi, inserire solo le righe cancellate erroneamente o compiere qualunque operazione neces-
saria.
La nuova tabella, LIBRO_ORDINE_OLD non presenta né indici né vincoli di integrità
referenziale. Se si avesse bisogno di unirla ad altre tabelle, potrebbe essere necessario creare
copie flashback di più tabelle per mantenere l’integrità referenziale dei dati. Occorre altresì
osservare che ciascuna query viene eseguita in momento diverso, e che le ore relative usate nella
clausola as of timestamp possono pertanto portare a risultati fuorvianti o incoerenti.
Si può lavorare direttamente con i vecchi dati, tuttavia ci si affida alla disponibilità di questi
ultimi per la transazione. In generale è più sicuro creare una tabella e memorizzarvi temporane-
amente i vecchi dati mentre si lavora con essi.
NOTA Prima di procedere con l’esempio che segue,è necessario disporre del pri-
vilegio EXECUTE per il package DBMS_FLASHBACK.
L’esempio seguente mostra questo processo come parte di una transazione sulla tabella
LIBRO_ORDINE_OLD creata e popolata nella prima parte di questo capitolo. Per prima cosa il
valore SCN corrente viene assegnato a una variabile di nome SCN_FLASH e visualizzato trami-
te il comando print di SQL*Plus:
commit;
print SCN_FLASH
SCN_FLASH
----------
529732
6 rows deleted.
commit;
Ora è possibile interrogare i dati flashback. Anche se il valore di SCN è noto, se si è ancora
nella medesima sessione si può continuare a usare il valore della variabile SCN_FLASH:
COUNT(*)
----------
0
COUNT(*)
----------
6
6 rows created.
commit;
474 CAPITOLO 27
0 rows deleted.
6 rows created.
commit;
TITOLO ORA_ROWSCN
------------------------------ ----------
SHOELESS JOE 553531
GOSPEL 553531
SOMETHING SO STRONG 553531
GALILEO'S DAUGHTER 553531
LONGITUDE 553531
ONCE REMOVED 553531
Tutte le righe facevano parte della medesima transazione, avvenuta nel momento contrasse-
gnato con SCN 553531 (il valore SCN di ciascun lettore sarà ovviamente diverso da quello di
questo esempio). Ora si attende che si verifichino altre transazioni nel database e si inserisce una
nuova riga:
1 row created.
commit;
Ora che è stata confermata un nuova modifica, è possibile vedere il valore SCN a essa asso-
ciato:
TITOLO ORA_ROWSCN
------------------------------ ----------
SHOELESS JOE 553531
GOSPEL 553531
SOMETHING SO STRONG 553531
GALILEO'S DAUGHTER 553531
LONGITUDE 553531
ONCE REMOVED 553531
INNUMERACY 553853
A che ora corrisponde questo valore SCN? È possibile utilizzare la funzione SCN_TO_
TIMESTAMP per vedere la data in cui è stata effettuata la modifica:
SCN_TO_TIMESTAMP(555853)
------------------------------------------------
20-FEB-04 03.11.28.000000000 PM
È possibile integrare le due query per vedere gli orari delle ultime transazioni per ciascuna
riga:
Per preparare quanto occorre per questi esempi, si inizi cancellando le vecchie righe da
LIBRO_ORDINE:
Per eseguire una query di versione flashback, utilizzare la clausola versions between del
comando select; si può specificare l’indicatore orario o il valore SCN. In questo esempio, il
formato per la clausola dell’indicatore orario si basa sul formato standard di Oracle (select
SysTimeStamp from DUAL per il valore corrente):
select *
from LIBRO_ORDINE
versions between timestamp
to_timestamp('20—FEB-04 16.00.20','DD-MON-YY HH24.MI.SS')
and
to_timestamp('20—FEB-04 16.06.20','DD-MON-YY HH24.MI.SS') ;
Quando si esegue la query, Oracle restituirà una riga per ciascuna versione di ogni riga
esistita tra i punti di inizio e fine specificati nella clausola versions between. Per le righe che
vengono restituite è possibile interrogare pseudocolonne aggiuntive:
USO DELLE QUERY FLASHBACK 477
PSEUDOCOLONNA DESCRIZIONE
VERSIONS_STARTSCN Il valore SCN corrispondente al momento in cui i dati per la prima volta hanno avuto i valori riflessi. Se
NULL, la riga è stata creata prima del limite inferiore della query.
VERSIONS_STARTTIME L’indicatore orario corrispondente al momento in cui i dati per la prima volta hanno avuto i valori riflessi.
Se NULL, la riga è stata creata prima del limite inferiore della query.
VERSIONS_ENDSCN Il valore SCN indicante il momento in cui la versione della riga è terminata Se NULL, la riga è attuale o è
stata eliminata.
VERSIONS_ENDTIME L’indicatore orario indicante il momento in cui la versione della riga è terminata Se NULL, la riga è attuale
o è stata eliminata.
VERSIONS_OPERATION L’operazione che ha effettuato la transazione (I per inserimento, U per aggiornamento, D per eliminazione).
L’esempio che segue illustra l’uso delle query di versione flashback. I valori
Versions_StartSCN sono NULL per le righe correnti; le vecchie righe sono state aggiornate. Gli
indicatori orari saranno diversi sulla piattaforma di ciascuno.
TITOLO VERSIONS_STARTSCN V
------------------------------ ----------------- -
ONCE REMOVED 568127 U
LONGITUDE 568127 U
GALILEO'S DAUGHTER 568127 U
SOMETHING SO STRONG 568127 U
GOSPEL 568127 U
SHOELESS JOE 568127 U
SHOELESS JOE
GOSPEL
SOMETHING SO STRONG
GALILEO'S DAUGHTER
LONGITUDE
ONCE REMOVED
La clausola versions between può essere usata nelle subquery dei comandi DML e DDL.
A partire da Oracle Database 10g, si può usare la vista del dizionario dati
FLASHBACK_TRANSACTION_QUERY per tenere traccia delle modifiche apportate da una
particolare transazione. Per una data transazione, FLASHBACK_TRANSACTION_QUERY
mostra il nome dell’utente che l’ha eseguita, l’operazione effettuata, la tabella cui è stata appli-
cata, i valori SCN e gli indicatori orari dell’inizio e della fine nonché il codice SQL necessario
per annullarla.
478 CAPITOLO 27
Flashback di tabelle
e database
A
partire da Oracle Database 10g, è possibile utilizzare i co-
mandi flashback table e flashback database per semplificare i tentativi di recupero dei dati. Il
comando flashback table automatizza il processo di ripristino di un’intera tabella al suo stato
precedente. Il comando flashback database recupera un intero database e impone alcune modi-
fiche allo stato del database e ai relativi log. I prossimi paragrafi illustrano i dettagli
dell’implementazione di queste opzioni.
Non è possibile eseguire il rollback di un’istruzione flashback table. Si può invece eseguire
un’altra istruzione flashback table e specificare un orario precedente all’ora corrente.
Privilegi richiesti
È necessario disporre del privilegio di oggetto FLASHBACK sulla tabella oppure il privilegio di
sistema FLASHBACK ANY TABLE. Si deve disporre anche dei privilegi di oggetto SELECT,
INSERT, DELETE e ALTER sulla tabella. Gli spostamenti delle righe devono essere abilitati per
tutte le tabelle nella lista di flashback. Per ripristinare una tabella a un momento precedente a
un’operazione drop table, sono sufficienti i privilegi richiesti per eliminare la tabella.
480 CAPITOLO 28
describe AUTORE
Ora supponiamo che la tabella sia stata eliminata per errore. In genere ciò accade quando un
utente munito dei privilegi necessari intende eliminare una tabella in un ambiente di sviluppo/di
prova e invece punta al database di produzione durante l’esecuzione del comando.
Table dropped.
Come si può recuperare la tabella? A partire da Oracle Database 10g, una tabella eliminata
non sparisce completamente: i suoi blocchi sono conservati nella relativa tablespace e la tabella
continua ad utilizzare le quote di spazio. È possibile visualizzare gli oggetti eliminati eseguendo
una query sulla vista del dizionario dati RECYCLEBIN. Si osservi che il formato della colonna
Object_Name può variare da una versione all’altra.
Flashback complete.
La tabella è stata ripristinata insieme alle sue righe, i suoi indici e le statistiche, come mo-
strato di seguito:
COUNT(*)
----------
31
NOTA Il comando flashback table to before drop non recupera i vincoli referenziali.
Per rimuovere le voci meno recenti dal cestino, si utilizza il comando purge. Si possono
rimuovere tutti gli oggetti eliminati, tutti gli oggetti eliminati nel database (se si agisce in qualità
di DBA), tutti gli oggetti contenuti in una tablespace specifica oppure tutti gli oggetti di un
determinato utente in una tablespace specifica. Per la sintassi completa e le opzioni del coman-
do, si rimanda alla voce relativa al comando purge nel Capitolo 48.
Per rinominare la tabella quando la si recupera, si può utilizzare la clausola rename to del
comando flashback table.
Il seguente comando update tenta di aggiornare il commento relativo alla voce Clement
Hurd. Tuttavia, la clausola where non è stata specificata; tutte le righe vengono aggiornate con il
medesimo commento e la modifica viene confermata con il comando commit.
update AUTORE
set Commenti = 'ILLUSTRATORE DI LIBRI PER L’INFANZIA';
31 rows updated.
commit;
482 CAPITOLO 28
In questo caso, si sa che quasi tutti i dati della tabella sono errati, così come si conosce la
transazione eseguita in modo non corretto. Per recuperare i dati corretti, si può ripristinare il
database a un momento precedente e successivamente applicare qualsiasi comando nuovo neces-
sario per aggiornare i dati.
Per prima cosa, ci si deve assicurare di conoscere il valore SCN corrente nel caso in cui si
debba tornare a questo punto:
commit;
print SCN_FLASH
SCN_FLASH
----------
720880
Ora si riporti la tabella a un punto nel tempo precedente all’aggiornamento. Per prima cosa,
si devono abilitare gli spostamenti di righe per la tabella:
Table altered.
Indici e statistiche
Quando una tabella viene ripristinata, lo stesso non accade alle sue statiche. Gli indici presenti
nella tabella vengono ripristinati, pertanto riflettono lo stato della tabella al punto di flashback.
Gli indici eliminati a partire dal punto di flashback non vengono ripristinati. Gli indici creati a
partire dal punto di flashback continueranno a esistere e saranno aggiornati in modo da riflettere
i dati meno recenti.
NOTA Il database deve essere stato messo in modalità flashback con un comando
alter database flashback on. Il database deve essere montato in modalità esclusiva me non
aperto durante l’esecuzione del comando.
Si può utilizzare la clausola to scn o to timestamp per impostare il punto cui riportare l’inte-
ro database. Con la clausola to before si può tornare indietro a un momento precedente un punto
critico (per esempio, una transazione che ha prodotto una conseguenza non prevista per più
tabelle). Per visualizzare i valori SCN delle transazioni che per ultime hanno agito sulle righe,
utilizzare la pseudocolonna ORA_ROWSCN.
Per utilizzare flashback database, è innanzi tutto necessario modificare il database mentre è
montato ma non aperto. Se questa operazione non è ancora stata eseguita, occorrerà chiudere il
database e abilitare un flashback durante il processo di avvio:
NOTA Prima di eseguire il comando alter database flashback on, il recupero dei
supporti deve essere stato abilitato mediante il comando alter database archivelog.
desc V$FLASHBACK_DATABASE_LOG
Si può verificare lo stato di flashback del database eseguendo una query su V$DATABASE;
la colonna Flashback_On ha valore YES se il flashback è stato abilitato per il database.
CURRENT_SCN FLA
---------------- ---
723649 YES
Tenendo aperto il database per più di un’ora, verificare che i dati flashback siano disponibili
e poi recuperarli; tutte le transazioni avvenute in quell’arco di tempo andranno perse:
shutdown;
startup mount exclusive;
flashback database to timestamp sysdate-1/24;
Il comando flashback database impone che il database sia montato in modalità esclusiva, il
che influirà sulla sua partecipazione a qualsiasi cluster RAC (fare riferimento al Capitolo 40).
Quando si esegue il comando flashback database, Oracle effettua un controllo per accertar-
si che tutti i file redo log archiviati e in linea necessari siano disponibili. In caso affermativo, i
file di dati in linea vengono ripristinati all’ora o al SCN specificato.
Se negli archive log e nell’area flashback non ci sono sufficienti dati in linea, si dovrà ricor-
rere ai metodi tradizionali di recupero del database per recuperare i dati. Per esempio, potrebbe
essere necessario utilizzare un metodo di recupero del file system seguito da un rollforward dei
dati.
Completato il flashback, è necessario aprire il database con l’opzione resetlogs per avere
l’accesso in lettura al database:
Per disattivare l’opzione di flashback del database, eseguire il comando alter database
flashback off quando il database è montato ma non aperto:
Introduzione a PL/SQL
P
L/SQL è il linguaggio procedurale (PL, Procedural Language)
di Oracle e nel contempo è un sovrainsieme del linguaggio SQL (Structured Query Language).
Il linguaggio PL/SQL può essere utilizzato per codificare le regole business mediante la creazio-
ne di stored procedure e package, per attivare eventi di database quando necessario e per aggiun-
gere una logica di programmazione all’esecuzione di comandi SQL.
I passaggi richiesti per la creazione di trigger, stored procedure e package sono descritti nei
capitoli seguenti di questa parte del libro. In questo capitolo vengono invece descritte le strutture
e la sintassi più semplici utilizzate nel linguaggio PL/SQL.
SEZIONE DESCRIZIONE
Dichiarazioni Definisce e inizializza le variabili e i cursori utilizzati nel blocco.
Comandi eseguibili Usa i comandi di controllo del flusso (come i comandi if e i cicli) per eseguire i comandi e assegnare dei
valori alle variabili dichiarate.
Gestione delle eccezioni Fornisce una gestione personalizzata delle condizioni di errore.
declare
<sezione dichiarazioni>
begin
<comandi eseguibili>
exception
<gestione delle eccezioni>
end;
Nei prossimi paragrafi di questo capitolo viene descritta ciascuna sezione del blocco PL/
SQL.
declare
pi constant NUMBER(9,7) := 3.1415927;
radius INTEGER(5);
area NUMBER(14,2);
begin
radius := 3;
area := pi*power(radius,2);
insert into AREE values (raggio, area);
end;
/
La linea end segnala la fine del blocco PL/SQL; in base allo strumento utilizzato potrebbe
essere necessario aggiungere una barra (/) per eseguire il blocco PL/SQL. Quando si esegue il
blocco PL/SQL, Oracle genera questa risposta:
Per verificare che il blocco PL/SQL sia stato completato correttamente, è possibile selezio-
nare dal database le righe che sono state inserite mediante il codice PL/SQL. La query e i risul-
tati del listato seguente riportano la riga creata dal blocco PL/SQL nella tabella AREE:
select *
from AREE;
RAGGIO AREA
---------- ----------
3 28.27
INTRODUZIONE A PL/SQL 489
L’output mostra che il blocco PL/SQL ha inserito nella tabella AREE una singola riga. È
stata creata una sola riga in quanto era stato specificato un solo valore per il raggio.
Nella prima sezione del blocco PL/SQL, mostrata nel listato seguente, vengono dichiarate
tre variabili. Qui si devono dichiarare le variabili che verranno utilizzate nella sezione dei co-
mandi eseguibili del blocco PL/SQL.
declare
pi constant NUMBER(9,7) := 3.1415927;
raggio INTEGER(5);
area NUMBER(14,2);
La prima variabile dichiarata è pi, impostata a un valore costante mediante la parola chiave
constant. Dato che è stato dichiarato come costante, il valore della variabile pi non potrà essere
modificato nella sezione dei comandi eseguibili. Il valore viene assegnato tramite l’operatore :=.
I valori costanti possono essere assegnati anche con la parola chiave default:
Le due variabili successive sono definite, ma a esse non vengono assegnati valori predefiniti:
raggio INTEGER(5);
area NUMBER(14,2);
Nella sezione delle dichiarazioni è possibile assegnare un valore iniziale a una variabile. Per
impostare un valore iniziale per una variabile, occorre far seguire alla relativa specifica del tipo
di dati l’assegnamento del valore, come mostrato nel listato seguente:
raggio INTEGER(5) := 3;
NOTA Per questo esempio, la tabella VALORI_RAGGIO contiene una sola riga
con un valore di Raggio pari a 3.
declare
pi constant NUMBER(9,7) := 3.1415927;
area NUMBER(14,2);
cursor rag_cursore is
select * from VALORI_RAGGIO;
val_rag rag_cursore%ROWTYPE;
begin
open rag_cursore;
fetch rag_cursore into val_rag;
490 CAPITOLO 29
BOOLEAN INTERVAL DAY TO SECOND NUMERIC TIMESTAMP WITH LOCAL TIME ZONE
* A partire da Oracle Database 10g, i nuovi tipi di dati BINARY_DOUBLE e BINARY_FLOAT possono migliorare le prestazioni nelle applicazioni
che trattano quantità ingenti di dati numerici, come nelle elaborazioni di dati scientifici.
TIPI COMPOSTI
RECORD TABLE VARRAY
TIPI RIFERIMENTO
REF C\URSOR REF tipo_oggetto
TIPI LOB
BFILE BLOB CLOB** NCLOB**
** È possibile effettuare conversioni implicite da CLOB a NCLOB o da NCLOB A CLOB. Tuttavia, dato che può essere un’operazione molto
dispendiosa, potrebbe essere di aiuto a livello di manutenzione sceglliere di continuare a utilizzare TO_CLOB e TO_NOCLOB.
area := pi*power(val_rag.raggio,2);
insert into AREE values (val_rag.raggio, area);
close rag_cursore;
end;
/
Nella prima parte della sezione delle dichiarazioni, vengono definite le variabili pi e area,
come nei precedenti esempi del capitolo. La variabile “raggio” non è definita; al suo posto viene
definito un cursore denominato “rag_cursore”. La definizione del cursore è costituita da un
nome per il cursore (“rag_cursore”) e da una query (select * from VALORI_RAGGIO;). Un cursore
conserva i risultati di una query affinché possano essere elaborati da altri comandi all’interno del
blocco PL/SQL:
declare
pi constant NUMBER(9,7) := 3.1415927;
area NUMBER(14,2);
INTRODUZIONE A PL/SQL 491
cursor rag_cursore is
select * from VALORI_RAGGIO;
Una dichiarazione finale crea una variabile la cui struttura viene ancorata dal gruppo di
risultati del cursore:
val_rag rag_cursore%ROWTYPE;
La variabile “val_rag” sarà in grado di fare riferimento a ciascuna colonna del gruppo di
risultati della query. In questo esempio, la query restituisce solo una singola colonna, tuttavia se
la tabella contenesse più colonne, sarebbe possibile fare riferimento a tutte queste mediante la
variabile “val_rag”.
Oltre alla dichiarazione %ROWTYPE, è possibile utilizzare la dichiarazione %TYPE per
ereditare informazioni relative al tipo di dati. Se si utilizza la dichiarazione %ROWTYPE, la
variabile eredita le informazioni sulla colonna e il tipo di dati per tutte le colonne contenute nel
gruppo di risultati del cursore. Se invece si usa la dichiarazione %TYPE, la variabile eredita
solamente la definizione della colonna utilizzata per definirla. Inoltre è possibile basare le defi-
nizioni %TYPE su cursori, come nell’esempio seguente:
cursor rag_cursore is
select * from VALORI_RAGGIO;
val_rag rag_cursore%ROWTYPE;
raggio_val_rag val_rag.Raggio%TYPE;
Nel listato precedente, la variabile “val_rag” eredita i tipi di dati del gruppo di risultati del
cursore “rag_cursore”. La variabile “val_rag_raggio” eredita il tipo di dati della colonna Rag-
gio all’interno della variabile “val_rag”.
Il vantaggio dell’ancoraggio dei tipi di dati con le definizioni %ROWTYPE e %TYPE è la
possibilità di rendere le definizioni del tipo di dati nel codice PL/SQL indipendenti dalle struttu-
re dei dati base. Se la colonna Raggio della tabella VALORI_RAGGIO viene modificata dal tipo
di dati NUMBER(5) al tipo di dati NUMBER(4,2), non sarà necessario modificare il codice PL/SQL.
Il tipo di dati assegnato alle variabili associate verrà determinato dinamicamente durante l’ese-
cuzione.
declare
pi constant NUMBER(9,7) := 3.1415927;
raggio INTEGER(5);
area NUMBER(14,2);
begin
raggio := 3;
area := pi*power(raggio,2);
insert into AREE values (raggio, area);
end;
/
492 CAPITOLO 29
begin
raggio := 3;
area := pi*power(raggio,2);
insert into AREE values (raggio, area);
end;
Dopo la parola chiave begin inizia il lavoro del blocco PL/SQL. Per prima cosa, viene asse-
gnato un valore alla variabile raggio. Il valore della variabile raggio e della costante pi vengono
utilizzati per determinare il valore della variabile area. I valori di Raggio e Area vengono quindi
inseriti nella tabella AREE.
La sezione dei comandi eseguibili del blocco PL/SQL può contenere comandi che eseguono
i cursori dichiarati nella sezione delle dichiarazioni. Nell’esempio seguente (tratto dal paragrafo
dedicato alla sezione delle dichiarazioni), la sezione dei comandi eseguibili presenta numerosi
comandi che fanno riferimento al cursore “rag_cursore”:
declare
pi constant NUMBER(9,7) := 3.1415927;
area NUMBER(14,2);
cursor rag_cursore is
select * from VALORI_RAGGIO;
val_rag rag_cursore%ROWTYPE;
begin
open rag_cursore;
fetch rag_cursore into val_rag;
area := pi*power(val_rag.raggio,2);
insert into AREE values (val_rag.raggio, area);
close rag_cursore;
end;
/
open rag_cursore;
Quando si apre il cursore rag_cursore (tramite il comando open), la query dichiarata per
questo cursore viene eseguita, e vengono identificati i record da restituire. Quindi, i record ven-
gono estratti dal cursore con il comando fetch.
Nella sezione delle dichiarazioni, la variabile val_rag viene dichiarata in modo da ancorare
i propri tipi di dati al cursore rag_cursore:
cursore rag_cursore is
select * from VALORI_RAGGIO;
val_rag rag_cursore%ROWTYPE;
Quando si estrae (con fetch) un record dal cursore per inserirlo nella variabile val_rag, è
ancora possibile indirizzare ciascun valore della colonna selezionato mediante la query del cursore.
Quando i dati del cursore non sono più necessari, è possibile chiudere il cursore (con il comando
close), come mostrato nel listato seguente.
close rag_cursore;
INTRODUZIONE A PL/SQL 493
La sezione dei comandi eseguibili può contenere logica condizionale, come i comandi if e i
cicli. Nei paragrafi successivi verranno riportati esempi per ciascuno dei tipi principali di opera-
zioni per il controllo di flusso consentiti nel linguaggio PL/SQL. Le operazioni per il controllo
del flusso possono essere utilizzate per modificare il modo in cui sono gestiti i record recuperati
tramite fetch e i comandi eseguibili.
Logica condizionale
All’interno del linguaggio PL/SQL, è possibile utilizzare i comandi if, else, elsif e case per
controllare il flusso dei comandi stessi all’interno della sezione dei comandi eseguibili. Nel
listato seguente sono riportate le sintassi delle clausole if:
if <qualche condizione>
then <qualche comando>
elsif <qualche condizione>
then <qualche comando>
else <qualche comando>
end if;
Le condizioni if possono essere nidificate le une entro le altre, come nel listato seguente:
if <qualche condizione>
then
if <qualche condizione>
then <qualche comando>
end if;
else <qualche comando>
end if;
declare
pi constant NUMBER(9,7) := 3.1415927;
area NUMBER(14,2);
cursor rag_cursore is
select * from VALORI_RAGGIO;
val_rag rag_cursore%ROWTYPE;
begin
open rag_cursore;
fetch rag_cursore into val_rag;
area := pi*power(val_rag.raggio,2);
if area >30
then
insert into AREE values (val_rag.raggio, area);
end if;
close rag_cursore;
end;
/
494 CAPITOLO 29
In questo esempio, viene utilizzata una condizione if per controllare il flusso di esecuzione
all’interno della sezione dei comandi eseguibili del blocco PL/SQL. I comandi di controllo del
flusso sono mostrati nel listato seguente:
if area >30
then
insert into AREE values (val_rag.raggio, area);
end if;
In questo esempio, i comandi di controllo del flusso iniziano una volta determinato il valore
della variabile area. Se il valore è maggiore di 30, un record verrà inserito nella tabella AREE.
Se invece il valore è minore di 30, non verrà inserito alcun record. Questo tipo di controllo del
flusso può essere utilizzato per stabilire quale tra le varie istruzioni SQL dev’essere eseguita, in
base alle condizioni specificate nelle condizioni if.
Nel listato seguente, è riportata la sintassi per il controllo di flusso che implica i comandi
SQL:
if area>30
then <qualche comando>
elsif area<10
then <qualche comando>
else <qualche comando>
end if;
Dopo la descrizioni dei tipi di cicli supportati verrà illustrato l’uso dei comandi case per il
controllo del flusso.
Cicli
È possibile utilizzare i cicli per elaborare più record all’interno di un unico blocco PL/SQL. PL/
SQL supporta tre tipi di cicli:
Cicli semplici Tutti i cicli che continuano a ripetersi fino al raggiungimento di un’istruzione exit o exit when.
Cicli WHILE Cicli che si ripetono fintanto che una condizione è soddisfatta.
Nei paragrafi che seguono sono riportati esempi per ciascun tipo di ciclo che utilizzano
come punto di partenza i blocchi PL/SQL riportati in precedenza nel capitolo. I cicli possono
elaborare più record a partire da un cursore.
Cicli semplici
Nel listato seguente, viene utilizzato un ciclo semplice per generare più righe nella tabella AREE.
Il ciclo è avviato dalla parola chiave loop, mentre la clausola exit when stabilisce quando uscire
dal ciclo. Una clausola end loop segnala la fine del ciclo.
declare
pi constant NUMBER(9,7) := 3.1415927;
raggio INTEGER(5);
INTRODUZIONE A PL/SQL 495
area NUMBER(14,2);
begin
raggio := 3;
loop
area := pi*power(raggio,2);
insert into AREE values (raggio, area);
raggio := raggio+1;
exit when area >100;
end loop;
end;
/
La sezione loop di questo esempio stabilisce il controllo del flusso per i comandi nella sezio-
ne dei comandi eseguibili del blocco PL/SQL. I passaggi all’interno del ciclo sono descritti nella
seguente versione commentata dei comandi loop:
loop
/* Calcola l’area in base al valore del raggio. */
area := pi*power(raggio,2);
/* Inserisce i valori correnti nella tabella AREE. */
insert into AREE values (raggio, area);
/* Incrementa di 1 il valore del raggio. */
raggio := raggio+1;
/* Valuta l’ultima area calcolata. Se il valore */
/* supera 100, esce. Altrimenti ripete */
/* il ciclo con il nuovo valore del raggio. */
exit when area >100;
/* Segnala la fine del ciclo. */
end loop;
Il ciclo dovrebbe generare più righe nella tabella AREE. Il primo record sarà quello generato
da un valore di Raggio pari a 3. Quando il valore area supera 100, nella tabella AREE non
verranno inseriti altri record.
Di seguito è riportato un output di esempio successivo all’esecuzione del blocco PL/SQL:
select *
from AREE
order by Raggio;
RAGGIO AREA
---------- ----------
3 28.27
4 50.27
5 78.54
6 113.1
Dato che il valore di area per un valore di Raggio pari a 6 supera 100, non vengono elaborati
ulteriori valori di Raggio e il blocco PL/SQL viene completato.
Gli attributi %FOUND, %NOTFOUND e %ISOPEN del cursore sono valori booleani e
vengono impostati a TRUE o FALSE. Poiché si tratta di attributi booleani, è possibile valutarne
le impostazioni senza associarli esplicitamente a valori TRUE o FALSE. Per esempio, il coman-
do seguente causa un’uscita quando rag_cursore %NOTFOUND è TRUE:
Nel listato seguente viene utilizzato un ciclo semplice per elaborare più righe di un cursore:
declare
pi constant NUMBER(9,7) := 3.1415927;
area NUMBER(14,2);
cursor rag_cursore is
select * from VALORI_RAGGIO;
val_rag rag_cursore%ROWTYPE;
begin
open rag_cursore;
loop
fetch rag_cursore into val_rag;
exit when rag_cursore%NOTFOUND;
area := pi*power(val_rag.raggio,2);
insert into AREE values (val_rag.raggio, area);
end loop;
close rag_cursore;
end;
/
La sezione del ciclo del blocco PL/SQL usa come input valori tratti dalla tabella
VALORI_RAGGIO. Invece di basare i criteri di uscita sul valore di Area, viene controllato
l’attributo del cursore %NOTFOUND. Se nel cursore non vengono trovate altre righe, l’attributo
%NOTFOUND diventerà TRUE e ciò causerà l’uscita dal ciclo. Di seguito è riportata la versio-
ne commentata del ciclo:
loop
/* Nel ciclo, preleva un record. */
fetch rag_cursore into val_rag;
/* Se il tentativo di prelevamento non trova */
/* altri record nel cursore, esce dal ciclo. */
exit when rag_cursore%NOTFOUND;
/* Se il tentativo restituisce un record, */
/* elabora il valore del raggio e inserisce */
/* un record nella tabella AREE. */
area := pi*power(val_rag.raggio,2);
insert into AREE values (val_rag.raggio, area);
/* Segnala la fine del ciclo. */
end loop;
INTRODUZIONE A PL/SQL 497
Quando si esegue il blocco PL/SQL precedente, tutti i record della tabella VALORI_RAGGIO
vengono elaborati dal ciclo. Finora la tabella VALORI_RAGGIO conteneva solo un record: un
valore di Raggio pari a 3.
NOTA Prima di eseguire il blocco PL/SQL per questa sezione, si aggiungano due
nuovi valori di Raggio, 4 e 10, alla tabella VALORI_RAGGIO.
Di seguito viene illustrata l’aggiunta dei nuovi record alla tabella VALORI_RAGGIO:
select *
from VALORI_RAGGIO
order by Raggio;
RAGGIO
----------
3
4
10
Una volta aggiunti i nuovi record alla tabella VALORI_RAGGIO, si esegua il blocco PL/SQL
descritto in precedenza in questo paragrafo. Di seguito è riportato l’output del blocco PL/SQL:
select *
from AREE
order by Raggio;
RAGGIO AREA
---------- ----------
3 28.27
4 50.27
10 314.16
La query sulla tabella AREE mostra come ogni record della tabella VALORI_RAGGIO sia
stato trasmesso dal cursore ed elaborato. Una volta esauriti i record da elaborare nel cursore, si
esce dal ciclo e il blocco PL/SQL viene completato.
I cicli FOR
Un ciclo semplice viene eseguito finché non viene soddisfatta una condizione exit, mentre in un
ciclo FOR le iterazioni vengono eseguite un numero specifico di volte. Di seguito è riportato un
esempio di ciclo FOR. L’inizio del ciclo FOR è indicato dalla parola chiave for, seguita dai criteri
utilizzati per stabilire quando l’elaborazione è terminata e quando si può uscire dal ciclo. Dato
che il numero di esecuzioni di un ciclo viene impostato all’avvio del medesimo, all’interno del
ciclo non è necessario un comando exit.
Nell’esempio seguente, le aree dei cerchi vengono calcolate basandosi su valori di Raggio
compresi tra 1 e 7 (inclusi).
declare
pi constant NUMBER(9,7) := 3.1415927;
498 CAPITOLO 29
raggio INTEGER(5);
area NUMBER(14,2);
begin
for raggio in 1..7 loop
area := pi*power(raggio,2);
insert into AREE values (raggio, area);
end loop;
end;
/
I passaggi richiesti per l’elaborazione del ciclo sono visualizzati nel seguente listato com-
mentato:
raggio := raggio+1;
i valori di Raggio sono già specificati. Per ciascun valore, vengono eseguiti tutti i comandi
all’interno del ciclo (questi comandi possono comprendere altra logica condizionale, come le
condizioni if). Una volta che il ciclo ha completato l’elaborazione di un valore di Raggio, vengo-
no verificati i limiti nella clausola for e si passa, a seconda dei casi, a elaborare il successivo
valore di Raggio o a completare l’esecuzione del ciclo.
Nel listato seguente è mostrato un output di esempio ricavato dall’esecuzione del ciclo FOR:
select *
from AREE
order by Raggio;
RAGGIO AREA
---------- ----------
1 3.14
2 12.57
3 28.27
4 50.27
5 78.54
6 113.1
7 153.94
7 rows selected.
INTRODUZIONE A PL/SQL 499
declare
pi constant NUMBER(9,7) := 3.1415927;
area NUMBER(14,2);
cursor rag_cursore is
select * from VALORI_RAGGIO;
begin
for val_rag in rag_cursore
loop
area := pi*power(val_rag.raggio,2);
insert into AREE values (val_rag.raggio, area);
end loop;
end;
/
apre implicitamente il cursore rag_cursore e trasmette un valore nella variabile val_rag. Quando
nel cursore non ci sono più record, si esce dal ciclo e il cursore viene chiuso. In un ciclo FOR a
cursore, il comando close non è necessario. Si osservi che la variabile val_rag non è dichiarata
esplicitamente nel blocco.
Nel listato seguente è visibile la porzione loop del blocco PL/SQL, con commenti che de-
scrivono il flusso del controllo. Il ciclo è controllato dall’esistenza di un record trasmissibile nel
cursore “rag_cursore”. Non è necessario verificare l’attributo %NOTFOUND del cursore, perché
a ciò provvede automaticamente il ciclo FOR a cursore.
Nel listato seguente è riportato un output di esempio; per questo caso la tabella
VALORI_RAGGIO dispone di tre record, con valori di Raggio pari a 3, 4 e 10.
500 CAPITOLO 29
select *
from VALORI_RAGGIO
order by Raggio;
RAGGIO
----------
3
4
10
L’esecuzione del blocco PL/SQL con il ciclo FOR a cursore genera i record seguenti nella
tabella AREE:
select *
from AREE
order by Raggio;
RAGGIO AREA
---------- ----------
3 28.27
4 50.27
10 314.16
Cicli WHILE
Un ciclo WHILE viene elaborato finché non viene soddisfatta una condizione di uscita. Invece
di specificare all’interno del ciclo la condizione di uscita tramite un comando exit, questa condi-
zione può essere specificata nel comando while che avvia il ciclo.
Nell’esempio seguente, viene creato un ciclo WHILE che consente l’elaborazione di più
valori di Raggio. Se il valore corrente della variabile Raggio soddisfa la condizione while nella
specifica del ciclo, i comandi del ciclo vengono elaborati. Quando un valore di Raggio non
soddisfa la condizione while nella specifica del ciclo, l’esecuzione di quest’ultimo termina:
declare
pi constant NUMBER(9,7) := 3.1415927;
raggio INTEGER(5);
area NUMBER(14,2);
begin
raggio := 3;
while raggio<=7
loop
area := pi*power(raggio,2);
insert into AREE values (raggio, area);
raggio := raggio+1;
end loop;
end;
/
Il ciclo WHILE è simile nella struttura a un ciclo semplice, in quanto termina basandosi sul
valore di una variabile. Di seguito sono riportati i passaggi implicati nel ciclo e i relativi com-
menti:
INTRODUZIONE A PL/SQL 501
select *
from AREE
order by Raggio;
RAGGIO AREA
---------- ----------
3 28.27
4 50.27
5 78.54
6 113.1
7 153.94
A causa del valore assegnato alla variabile “Raggio” prima del ciclo, questo deve forzata-
mente essere eseguito almeno una volta. Sarebbe opportuno controllare che gli assegnamenti
delle variabili soddisfino le condizioni utilizzate per limitare le esecuzioni del ciclo.
Istruzioni CASE
È possibile utilizzare le istruzioni case per controllare la logica di selezione nei blocchi PL/
SQL. Per esempio, queste istruzioni possono servire per assegnare dei valori ponendo delle
condizioni oppure per trasformare valori prima di inserirli. Nell’esempio seguente, le espressio-
ni case usano i valori di Raggio per decidere quali righe inserire nella tabella AREE:
declare
pi constant NUMBER(9,7) := 3.1415927;
area NUMBER(14,2);
cursor rag_cursore is
select * from VALORI_RAGGIO;
502 CAPITOLO 29
val_rag rag_cursore%ROWTYPE;
begin
open rag_cursore;
loop
fetch rag_cursore into val_rag;
exit when rag_cursore%NOTFOUND;
area := pi*power(val_rag.raggio,2);
case
when val_rag.Raggio = 3
then
insert into AREE values (val_rag.raggio, area);
when val_rag.Raggio = 4
then
insert into AREE values (val_rag.raggio, area);
when val_rag.Raggio = 10
then
insert into AREE values (0, 0);
else raise CASE_NOT_FOUND;
end case;
end loop;
close rag_cursore;
end;
/
Questo blocco crea l’output seguente. Quando il valore di Raggio è 10, la clausola case
inserisce una riga con i valori di Raggio e Area entrambi impostati a 0:
RAGGIO AREA
---------- ----------
3 28.27
4 50.27
0 0
case
when val_rag.Raggio = 3
then
insert into AREE values (val_rag.raggio, area);
Le clausole when vengono valutate in sequenza. La parola chiave else all’interno della clau-
sola case funziona in modo analogo alla parola chiave else in una clausola if-then. Se si tralascia
la parola chiave else, PL/SQL aggiunge la seguente clausola else implicita:
La clausola end case termina la clausola case. La clausola case viene utilizzata spesso per
convertire elenchi di valori nelle rispettive descrizioni, come nel caso dei nomi di categorie della
libreria. Il listato che segue illustra come i valori di NomeCategoria possano essere tradotti in
altri valori come parte di comandi SQL:
case NomeCategoria
when 'NARRADULTI' then 'Narrativa adulti'
INTRODUZIONE A PL/SQL 503
Per esempi relativi agli impieghi complessi di case, si rimanda al Capitolo 16.
declare
<sezione dichiarazioni>
begin
<comandi eseguibili>
exception
<gestione delle eccezioni>
end;
La sezione di gestione delle eccezioni di un blocco PL/SQL è facoltativa. Nessuno dei bloc-
chi PL/SQL presentati in precedenza in questo capitolo comprendeva una sezione di questo tipo.
Tuttavia, gli esempi precedenti si basavano su un gruppo molto piccolo di valori di input noti,
con elaborazione molto ridotta.
Nel listato seguente, è riportato il semplice ciclo per il calcolo dell’area di un cerchio, con
due modifiche. Nella sezione delle dichiarazioni viene dichiarata una nuova variabile di nome
una_variabile, mentre nella sezione dei comandi eseguibili viene creato un calcolo per stabilire
il valore della variabile.
declare
pi constant NUMBER(9,7) := 3.1415927;
raggio INTEGER(5);
area NUMBER(14,2);
una_variabile NUMBER(14,2);
begin
raggio := 3;
loop
504 CAPITOLO 29
una_variabile := 1/(raggio-4);
area := pi*power(raggio,2);
insert into AREE values (raggio, area);
raggio := raggio+1;
exit when area >100;
end loop;
end;
Dato che il calcolo di una_variabile richiede una divisione, è possibile incontrare una situa-
zione in cui il calcolo cerca di dividere per zero, provocando un errore. La prima volta che si
esegue il ciclo, viene elaborata la variabile raggio (con un valore iniziale pari a 3) e viene inse-
rito un record nella tabella AREE. Alla seconda esecuzione del ciclo, la variabile “Raggio” ha
valore pari a 4 e il calcolo di una_variabile incontra un errore.
declare
*
ERROR at line 1:
ORA-01476: divisor is equal to zero
ORA-06512: at line 9
A causa dell’errore, la prima riga inserita in AREE subisce un rollback e il blocco PL/SQL
termina.
L’elaborazione della condizione di errore può essere modificata aggiungendo una sezione di
gestione delle eccezioni al blocco PL/SQL, come mostrato nel listato seguente:
declare
pi constant NUMBER(9,7) := 3.1415927;
raggio INTEGER(5);
area NUMBER(14,2);
una_variabile NUMBER(14,2);
begin
raggio := 3;
loop
una_variabile := 1/(raggio-4);
area := pi*power(raggio,2);
insert into AREE values (raggio, area);
raggio := raggio+1;
exit when area >100;
end loop;
exception
when ZERO_DIVIDE
then insert into AREE values (0,0);
end;
/
exception
when ZERO_DIVIDE
then insert into AREE values (0,0);
Quando si verifica un errore, il blocco PL/SQL ricerca le eccezioni definite nella sezione di
gestione delle eccezioni. In questo caso, il blocco trova l’eccezione ZERO_DIVIDE, una delle
INTRODUZIONE A PL/SQL 505
eccezioni definite dal sistema disponibili nel linguaggio PL/SQL. Oltre alle eccezioni definite
dal sistema e a quelle definite dall’utente, è possibile utilizzare la clausola when others per
indirizzare tutte le eccezioni non definite all’interno della sezione di gestione delle eccezioni.
All’interno della sezione di gestione delle eccezioni, viene eseguito il comando relativo all’ecce-
zione corrispondente e nella tabella AREE viene inserita una riga. Di seguito è riportato l’output
del blocco PL/SQL:
select *
from AREE;
RAGGIO AREA
---------- ----------
3 28.27
0 0
L’output mostra che il primo valore di Raggio (3) è stato elaborato e che l’errore si è verifi-
cato durante la seconda esecuzione del ciclo.
NOTA Una volta incontrata un’eccezione, non è possibile tornare al normale flusso
dell’elaborazione dei comandi all’interno della sezione dei comandi eseguibili. Se si deve man-
tenere il controllo all’interno della sezione dei comandi eseguibili, occorre utilizzare delle con-
dizioni if per verificare la possibile presenza di eccezioni prima che queste vengano incontrate
dal programma, oppure creare un blocco nidificato dotato di una propria sezione locale di
gestione delle eccezioni.
Alla voce “Eccezioni” del Capitolo 48 sono elencate tutte le eccezioni definite dal sistema.
Nei Capitoli 30 e 31 sono riportati esempi di eccezioni definite dall’utente.
Per maggior dettagli sull’uso di PL/SQL dinamico, che consente la creazione dinamica dei
comandi eseguiti nel blocco PL/SQL, si rimanda al Capitolo 32.
PL/SQL supporta query complesse che utilizzano le caratteristiche più recenti del linguag-
gio SQL di Oracle. Per esempio, le query di versione flashback (Capitolo 27) e le funzioni per
espressioni regolari (Capitolo 8) sono entrambe supportate in PL/SQL dal momento in cui sono
state introdotte in Oracle Database 10g. Si rimanda ai capitoli appena indicati per maggiori
dettagli su queste nuove caratteristiche, che possono essere introdotte nel codice PL/SQL in
modo da semplificare e potenziare le proprie capacità di elaborazione.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 30
I trigger
U
n trigger definisce un’azione che il database deve intrapren-
dere quando si verifica un determinato evento correlato al database stesso. I trigger possono
essere utilizzati per migliorare l’integrità referenziale dichiarativa, per imporre regole complesse
legate all’attività o per effettuare revisioni sulle modifiche ai dati. Il codice interno a un trigger,
detto corpo del trigger, è costituito da blocchi PL/SQL (consultare il Capitolo 29).
All’utente l’esecuzione dei trigger risulta trasparente. I trigger vengono eseguiti dal database
quando tipi specifici di comandi per la manipolazione dei dati vengono eseguiti su tabelle ben
determinate. Tra questi comandi troviamo insert, update e delete. Gli aggiornamenti di colonne
specifiche possono essere utilizzati anche come eventi che attivano il trigger. Gli eventi che
attivano i trigger possono includere anche i comandi DDL e gli eventi del database (come chiusure
e connessioni).
Grazie alla loro flessibilità, i trigger possono aggiungere integrità referenziale, ma non possono
essere utilizzati in sostituzione di questa. Quando in un’applicazione si impongono regole legate
all’attività, per prima cosa è necessario affidarsi all’integrità referenziale dichiarativa disponibile
in Oracle; quindi si potranno utilizzare trigger per imporre regole che non possono essere codificate
attraverso l’integrità referenziale.
NOTA In Oracle Database 10g il ruolo RESOURCE viene fornito solo per garan-
tire la compatibilità con le versioni precedenti e non dev’essere utilizzato regolarmente.
sulle tabelle su cui essi si basano. Ciò richiede la disponibilità del privilegio ALTER per la
tabella che si desidera modificare o del privilegio di sistema ALTER ANY TABLE. Per
informazioni sulla modifica dei trigger, si rimanda al paragrafo “Attivazione e disattivazione dei
trigger” più avanti in questo capitolo.
Per creare un trigger su un evento avvenuto a livello di database, è necessario il privilegio di
sistema ADMINISTER DATABASE TRIGGER.
NOTA I privilegi necessari per le transazioni attivate con trigger non possono
derivare da ruoli. Tali privilegi devono essere concessi direttamente al creatore del trigger.
I trigger a livello di istruzione sono il tipo predefinito creato dal comando create trigger. La
sintassi dei trigger è mostrata nel paragrafo “Sintassi dei trigger”, più avanti in questo capitolo.
Trigger INSTEAD OF
È possibile utilizzare trigger INSTEAD OF per indicare a Oracle che cosa fare invece di eseguire
le azioni che hanno invocato il trigger. Per esempio, è possibile utilizzare un trigger INSTEAD
OF su una vista per reindirizzare gli inserimenti in una tabella o per aggiornare più tabelle che
facciano parte di una vista. I trigger INSTEAD OF possono essere utilizzati sia su viste oggetto
(consultare il Capitolo 33), sia su viste relazionali.
Per esempio, se una vista comporta il join di due tabelle, la possibilità di utilizzare il comando
update su record della vista è limitata. Tuttavia, con un trigger INSTEAD OF è possibile specificare
a Oracle come eseguire aggiornamenti, cancellazioni e inserimenti di record nelle tabelle base
della vista quando un utente cerca di modificare i valori attraverso la vista stessa. Il codice
contenuto nel trigger INSTEAD OF viene eseguito al posto del comando insert, update o delete
inserito.
Trigger di schema
Esiste la possibilità di creare i trigger su operazioni eseguite a livello di schema, come create
table, alter table, drop table, audit, rename, truncate e revoke. È persino possibile creare un
510 CAPITOLO 30
trigger before ddl. I trigger a livello di schema offrono principalmente due capacità: impedire
l’esecuzione di operazioni DDL e fornire ulteriore controllo della sicurezza quando si verificano
operazioni DDL.
Le opzioni sintattiche disponibili dipendono dal tipo di trigger utilizzato. Per esempio, un
trigger su un evento DML utilizzerà clausola_evento_dml, che segue questa sintassi:
Nella progettazione di un trigger è consentita una grande flessibilità. Le parole chiave before
e after indicano se il trigger dovrà essere eseguito prima o dopo la transazione che lo attiva. Con
la clausola instead of il codice del trigger verrà eseguito al posto dell’evento che ha attivato il
trigger. Le parole chiave delete, insert e update (l’ultima può comprendere un elenco di colonne)
indicano il tipo di manipolazione dei dati che costituirà un evento in grado di attivare il trigger.
Quando si fa riferimento ai valori vecchi e nuovi delle colonne, è possibile utilizzare i valori
predefiniti (“old” e “new”) o servirsi della clausola referencing per specificare altri nomi.
Con la clausola for each row si ha un trigger a livello di riga, altrimenti si ha un trigger a
livello di istruzione. La clausola when viene utilizzata per applicare ulteriori restrizioni quando
si esegue il trigger. Le restrizioni imposte nella clausola when possono comprendere verifiche
dei vecchi e nuovi valori dei dati.
Per esempio, si supponga di voler tener traccia di qualsiasi modifica al valore Valutazione
della tabella BIBLIOTECA ogni volta che i valori di valutazione vengono ridotti. Per prima
cosa, si creerà una tabella che memorizzerà i record di audit:
I TRIGGER 511
Il seguente trigger a livello di riga BEFORE UPDATE viene eseguito solo se il valore di
Valutazione viene ridotto. L’esempio seguente descrive anche l’uso della parola chiave new, che
fa riferimento al nuovo valore della colonna, e di old che fa riferimento al vecchio valore della
colonna.
La suddivisione di questo comando create trigger nei suoi componenti ne rende più semplice
la comprensione. In primo luogo viene assegnato un nome al trigger:
Il nome del trigger contiene il nome della tabella su cui agisce e il tipo del trigger stesso (per
informazioni sulle convenzioni di denominazione, si rimanda al paragrafo “Assegnazione dei
nomi ai trigger” più avanti in questo capitolo).
Questo trigger si applica alla tabella BIBLIOTECA; verrà eseguito prima che le transazioni
di aggiornamento siano state confermate con un commit nel database:
Vista la presenza della clausola for each row, il trigger verrà applicato a ciascuna riga
modificata dall’istruzione update. Se non si utilizzata questa clausola, il trigger verrà eseguito a
livello delle istruzioni.
La clausola when aggiunge ulteriori criteri alla condizione di attivazione del trigger. L’evento
che attiva il trigger non solo dovrà essere un aggiornamento della tabella BIBLIOTECA, ma
dovrà anche riflettere una riduzione del valore di Valutazione:
Il codice PL/SQL visibile nel listato seguente rappresenta il corpo del trigger. I comandi in
esso contenuti verranno eseguiti a ogni aggiornamento della tabella BIBLIOTECA che soddisfi
512 CAPITOLO 30
begin
insert into AUDIT_BIBLIOTECA
(Titolo, Editore, NomeCategoria,
Vecchia_Valutazione, Nuova_Valutazione, Data_Audit)
values
(:old.Titolo, :old.Editore, :old.NomeCategoria,
:old.Valutazione, :new.Valutazione, Sysdate);
end;
NOTA Quando nel blocco PL/SQL si fa riferimento alle parole chiave new e old,
queste sono precedute dal segno di due punti (:).
Si osservino nuovamente i componenti del trigger. Per prima cosa, il trigger riceve un nome
e viene identificato come trigger BEFORE INSERT e BEFORE UPDATE (del valore Valutazione),
da eseguirsi per ogni riga (for each row).
Quindi segue il corpo del trigger, nella prima del quale, riportata di seguito, avviene il controllo
del tipo di transazione tramite una clausola if. I tipi di transazioni validi sono INSERTING,
DELETING e UPDATING. In questo caso, il trigger verifica se il record dev’essere inserito
nella tabella BIBLIOTECA. In caso affermativo, viene eseguita la prima parte del corpo del
trigger. La parte INSERTING del corpo del trigger inserisce i nuovi valori del record nella tabella
AUDIT_BIBLIOTECA.
begin
if INSERTING then
insert into AUDIT_BIBLIOTECA
(Titolo, Editore, NomeCategoria,
Nuova_Valutazione, Data_Audit)
values
(:new.Titolo, :new.Editore, :new.NomeCategoria,
:new.Valutazione, Sysdate);
Possono quindi essere verificati altri tipi di transazioni. In questo esempio, dal momento che
il trigger è stato eseguito, la transazione dev’essere un inserimento o un aggiornamento della
colonna Valutazione. Dato che la clausola if nella prima metà del corpo del trigger verifica gli
inserimenti, e il trigger viene eseguito solo per inserimenti e aggiornamenti, le uniche condizioni
in grado di eseguire la seconda metà del corpo del trigger sono gli aggiornamenti di Valutazione.
Di conseguenza, non sono necessarie altre clausole if per determinare il tipo di evento DML.
Questa parte del corpo del trigger è identica a quella precedente: prima di essere aggiornati, i
vecchi valori nella riga vengono scritti nella tabella AUDIT_BIBLIOTECA.
Questa combinazione di tipi differenti di trigger può agevolare la coordinazione dello sviluppo
di trigger tra più sviluppatori, in quanto consolida tutti gli eventi di database che dipendono da
un’unica tabella.
514 CAPITOLO 30
Come mostra l’intestazione, questo trigger viene eseguito per ogni riga inserita nella tabella
AUDIT_BIBLIOTECA. Esso inserisce un singolo record nella tabella DUP_AUDIT_
BIBLIOTECA, nel database definito dal database link AUDIT_LINK. AUDIT_LINK può puntare
a un database che si trova su un server remoto. Se si verifica qualche problema di avvio
dell’inserimento remoto tramite il trigger, l’inserimento locale fallirà.
Per i requisiti di replica asincrona, si prenda in considerazione l’eventualità di utilizzare le
viste materializzate (consultare il Capitolo 24).
È possibile vedere le azioni di questi trigger inserendo una riga nella tabella BIBLIOTECA:
1 row created.
TITOLO
---------------------------------------------------
HARRY POTTER AND THE CHAMBER OF SECRETS
TITOLO
---------------------------------------------------
HARRY POTTER AND THE CHAMBER OF SECRETS
516 CAPITOLO 30
'SAT' or
TO_CHAR(SysDate,'DY') = 'SUN' THEN
RAISE weekend_error;
end if;
if SUBSTR(User,1,3) <> 'LIB' THEN
RAISE not_library_user;
end if;
EXCEPTION
WHEN weekend_error THEN
RAISE_APPLICATION_ERROR (-20001,
'Deletions not allowed on weekends');
WHEN not_library_user THEN
RAISE_APPLICATION_ERROR (-20002,
'Deletions only allowed by Library users');
end;
In questo trigger non compaiono clausole when, quindi il corpo del trigger verrà eseguito
per tutte le cancellazioni.
La parte successiva del trigger dichiara i nomi delle due eccezioni definite all’interno del
trigger stesso:
declare
weekend_error EXCEPTION;
not_library_user EXCEPTION;
La prima parte del corpo del trigger contiene una clausola if che utilizza la funzione TO_CHAR
sulla funzione SYSDATE. Se il giorno corrente è sabato o domenica, verrà sollevata la condizione
di errore WEEKEND_ERROR. Questa condizione di errore, detta eccezione, dev’essere definita
all’interno del corpo del trigger.
if TO_CHAR(SysDate,'DY') = 'SAT' or
TO_CHAR(SysDate,'DY') = 'SUN' THEN
RAISE weekend_error;
end if;
I TRIGGER 517
Una seconda clausola if verifica che le prime tre lettere della pseudocolonna User siano
‘LIB’. Se il nome utente non inizia con ‘LIB’, verrà sollevata l’eccezione NOT_LIBRARY_USER.
In questo esempio, viene utilizzato l’operatore <>, equivalente a != (che significa “non è uguale”).
La parte finale del corpo del trigger indica come gestire le eccezioni. Questa parte inizia con
la parola chiave exception, seguita da una clausola when per ciascuna delle eccezioni. Tutte le
eccezioni di questo trigger chiamano la procedura RAISE_APPLICATION_ERROR, che accetta
due parametri di input: il numero dell’errore (che deve essere compreso tra –20001 e –20999) e
il messaggio d’errore da visualizzare. In questo esempio, sono definiti due messaggi d’errore
diversi, uno per ciascuna delle eccezioni definite:
EXCEPTION
WHEN weekend_error THEN
RAISE_APPLICATION_ERROR (-20001,
'Deletions not allowed on weekends');
WHEN not_library_user THEN
RAISE_APPLICATION_ERROR (-20002,
'Deletions only allowed by Library users');
Quando un utente non “LIB” cerca di cancellare una riga dalla tabella BIBLIOTECA in un
giorno infrasettimanale, questo è il risultato ottenuto:
Se si tenta di cancellare una riga di sabato o domenica, verrà invece restituito l’errore ORA-
20001. Non appena si incontra l’eccezione, Oracle lascia la sezione dei comandi eseguibili del
trigger ed elabora l’eccezione. Si vedrà solo la prima eccezione incontrata.
Come mostrato in questo esempio, è possibile fare riferimento ad attributi di sistema come il
nome dell’oggetto. Gli attributi disponibili sono elencati nella Tabella 30.1.
Per proteggere gli oggetti all’interno di uno schema, si potrebbe creare un trigger che viene
eseguito ogni volta che si cerca di eseguire il comando drop table. Dovrà essere un trigger di tipo
BEFORE DROP:
begin
if ora_dict_obj_owner = 'PRACTICE'
and ora_dict_obj_name like 'BIB%'
and ora_dict_obj_type = 'TABLE'
then
RAISE_APPLICATION_ERROR (
-20002, 'Operation non permitted.');
end if;
end;
/
Si osservi che il trigger fa riferimento agli attributi dell’evento all’interno delle sue clausole
if. Il tentativo di eliminare una tabella nello schema di Practice il cui nome inizia con BIB ha
come risultato:
Questo esempio mostra un trigger semplice che verrà eseguito subito dopo un avvio del
database. L’elenco dei package nel corpo del trigger può essere modificato per includere quelli
più utilizzati dalle applicazioni.
I trigger di avvio e chiusura possono accedere agli attributi ora_instance_num,
ora_database_name, ora_login_user e ora_sysevent elencati nella Tabella 30.1. Per la sintassi
completa del comando create trigger, si rimanda al Capitolo 48.
Un secondo metodo per l’attivazione dei trigger utilizza il comando alter table con la clausola
enable all triggers. Con questo comando non è possibile attivare trigger specifici; a tale fine si
deve ricorrere al comando alter trigger. Nell’esempio seguente è descritto l’uso del comando
alter table:
Per usare il comando alter table, è necessario possedere la tabella o disporre del privilegio di
sistema ALTER ANY TABLE.
I TRIGGER 521
I trigger possono essere disattivati con gli stessi comandi di base (che richiedono gli stessi
privilegi) apportando però qualche modifica alle rispettive clausole. Per il comando alter trigger,
si utilizza la clausola disable.
alter trigger BIBLIOTECA_BEF_UPD_INS_ROW disable;
I trigger possono essere compilati a mano. Per compilare manualmente trigger già esistenti
che non sono più validi, occorre utilizzare il comando alter trigger compile. Dal momento che i
trigger dipendono da altri elementi, possono divenire non validi se un oggetto su cui si basa il
trigger viene modificato. Il comando alter trigger debug consente la generazione di informazioni
PL/SQL durante la ricompilazione del trigger.
(segue)
522 CAPITOLO 30
ora_dict_obj_owner VARCHAR(30) Proprietario dell’oggetto INSERT INTO event_table (‘object owner is’
del dizionario sul quale l’operazione || ora_dict_obj_owner');
ha avuto luogo.
ora_dict_obj_type VARCHAR(20) Tipo dell’oggetto del dizionario INSERT INTO event_table (‘This object is a ‘
sul quale l’operazione || ora_dict_obj_type);
ha avuto luogo.
(segue)
I TRIGGER 523
ora_server_error NUMBER Data una posizione (1 per la cima INSERT INTO event_table (‘top
dello stack), restituisce il numero stack error ‘ || ora_server_error(1));
dell’errore corrispondente
alla posizione sullo stack degli errori.
ora_server_error_msg VARCHAR2 Data una posizione (1 per la cima INSERT INTO event_table (‘top
(position in dello stack), restituisce il messaggio stack error message' ||
BINARY_INTEGER) dell’errore corrispondente ora_server_error_msg(1));
alla posizione sullo stack degli errori.
ora_server_error_param VARCHAR2 Data una posizione (1 per la cima -- E.g. the 2nd %s in a message
(position in binary_integer, dello stack), e un numero -- like “Expected %s, found %s”
param in binary_integer) di parametro, restituisce il valore param := ora_server_error_param(1,2);
di sostituzione "%s", "%d" e così via
corrispondente nel messaggio
di errore.
ora_sql_txt (sql_text out BINARY_INTEGER Restituisce il testo SQL dell’istruzione sql_text ora_name_list_t;
ora_name_list_t) che avvia il trigger nel parametro OUT. stmt VARCHAR2(2000);
Se l’istruzione è lunga, viene suddivisa ...
in più elementi di tabella PL/SQL. n := ora_sql_txt(sql_text);
Il valore restituito dalla funzione FOR i IN 1..n LOOP stmt :=
specifica il numero di elementi stmt || sql_text(i);
nella tabella PL/SQL. END LOOP;
INSERT INTO event_table (‘testo
dell’ìistruzione che avvia il trigger: ‘ ||
stmt);
(segue)
524 CAPITOLO 30
Procedure, funzioni
e package
I
n Oracle, è possibile memorizzare come procedure sia sofisti-
cate regole business sia la logica applicativa. Le stored procedure, gruppi di istruzioni SQL, PL/
SQL e Java, consentono di spostare il codice che impone regole legate all’attività dall’applica-
zione al database. In questo modo, il codice verrà memorizzato una sola volta per essere utilizza-
to più volte. Dato che Oracle supporta le stored procedure, il codice all’interno delle applicazio-
ni può diventare più coerente e facile da gestire.
NOTA Per dettagli su Java e il suo impiego nelle stored procedure, si rimanda ai
Capitoli 37, 38 e 39. Questo capitolo si concentrerà sulle procedure PL/SQL.
Le procedure e gli altri comandi PL/SQL possono essere raggruppati in package. Nei para-
grafi successivi verranno forniti i dettagli di implementazione e alcune raccomandazioni riguar-
danti i package, le procedure e le funzioni (procedure che possono restituire valori all’utente).
L’uso di procedure può assicurare miglioramenti delle prestazioni per due motivi.
■ L’elaborazione di regole business complesse può essere effettuata all’interno del database,
quindi mediante il server. Nelle applicazioni client-server, o a tre livelli, lo spostamento di ela-
borazioni complesse dall’applicazione (sul client) al database (sul server) può migliorare sensi-
bilmente le prestazioni.
■ Dato che il codice procedurale è memorizzato all’interno del database ed è piuttosto statico,
è anche possibile trarre vantaggio dal riutilizzo delle stesse query all’interno del database. L’area
SQL condivisa (Shared SQL Area) della System Global Area (SGA) memorizza le versioni
526 CAPITOLO 31
analizzate dei comandi eseguiti. Così una procedura, la seconda volta che viene eseguita, può
sfruttare l’analisi effettuata in precedenza, migliorando le prestazioni nell’esecuzione.
Oltre a ciò, anche lo sviluppo di applicazioni può trarre dei vantaggi. Le regole business
consolidate all’interno del database non dovranno più essere scritte in ciascuna applicazione, il
che consente risparmi di tempo durante la creazione delle applicazioni stesse e semplifica il
processo di gestione.
NUOVO_LIBRO(:new.Titolo);
La procedura NUOVO_LIBRO verrà eseguita con il nuovo valore della colonna Titolo come
input (per ulteriori informazioni sull’uso di valori vecchi e nuovi all’interno dei trigger, si ri-
manda al Capitolo 30).
Per eseguire una procedura posseduta da un altro utente, è necessario creare un sinonimo per
questa procedura, oppure fare riferimento al nome del proprietario durante l’esecuzione, come
mostrato nel listato seguente:
Quindi il proprietario di questo sinonimo non dovrebbe più fare riferimento al proprietario
della procedura per eseguirla. Sarebbe sufficiente inserire il comando:
Il comando si serve del database link REMOTE_CONNECT per accedere alla procedura
NUOVO_LIBRO in un database remoto.
Per semplificare l’individuazione della procedura da parte dell’utente, è possibile creare un
sinonimo per la procedura remota, come nell’esempio seguente:
Una volta creato il sinonimo, l’utente potrà fare riferimento alla procedura remota grazie al
nome del sinonimo. Oracle presuppone che tutte le chiamate alla procedura remota richiedano
aggiornamenti nel database remoto.
eseguire deve disporre di privilegi sulle tabelle utilizzate. A meno che si utilizzino i privilegi
dell’utente chiamante, l’utente che esegue l’oggetto procedurale non ha bisogno di privilegi
sulle tabelle di base.
NOTA I privilegi necessari per procedure, package e funzioni non possono deri-
vare da ruoli, ma devono essere concessi direttamente al proprietario della procedura, del package
o della funzione.
Con questo comando vengono creati sia l’intestazione sia il corpo della procedura.
La procedura NUOVO_LIBRO viene creata dal comando mostrato nel listato seguente:
begin
insert into BIBLIOTECA (Titolo, Editore, NomeCategoria, Valutazione)
values (aTitolo, aEditore, aNomeCategoria, NULL);
delete from LIBRO_ORDINE
where Titolo = aTitolo;
end;
530 CAPITOLO 31
TITOLO
----------------------------------------------------------------
GALILEO'S DAUGHTER
GOSPEL
LONGITUDE
ONCE REMOVED
SHOELESS JOE
SOMETHING SO STRONG
TITOLO
----------------------------------------------------------------
GALILEO'S DAUGHTER
GOSPEL
LONGITUDE
SHOELESS JOE
SOMETHING SO STRONG
TITOLO
----------------------------------------------------------------
EDITORE NOMECATEGORIA VA
-------------------- -------------------- --
ONCE REMOVED
SANCTUARY PUB SAGGIADULTI
Con questo comando vengono creati sia l’intestazione sia il corpo della funzione.
La parola chiave return specifica il tipo di dati del valore restituito dalla funzione. Questo
può essere qualunque tipo di dati PL/SQL valido (si consulti il capitolo 29). Ogni funzione deve
comprendere una clausola return, in quanto una funzione deve per definizione restituire un valo-
re all’ambiente che la chiama.
L’esempio seguente mostra una funzione di nome SPESE_RITARDO, che restituisce per
ogni persona le spese dovute a ritardi nella riconsegna dei libri, basandosi su calcoli eseguiti
sulla tabella BIBLIOTECA_PRESTITO. L’input è il nome della persona mentre l’output è il
saldo relativo alla stessa persona.
Per prima cosa, viene assegnato un nome alla funzione, quindi viene specificato l’input:
return NUMBER
is
saldo NUMBER(10,2);
532 CAPITOLO 31
Segue il blocco PL/SQL. Nell’istruzione SQL, viene calcolata la somma di tutte le tasse di
ritardo ( 0.20 al giorno una volta superati 14 giorni). La somma viene selezionata in una variabi-
le di nome saldo (definita precedentemente). La linea di comando RETURN(saldo) restituisce
quindi il valore della variabile “saldo” al programma chiamante.
begin
select SUM(((DataRestituzione_DataPrestito) -14)*0.20)
into saldo
from BIBLIOTECA_PRESTITO
where Nome = aNome;
RETURN(saldo);
end;
È possibile sostituire una funzione già esistente mediante il comando create or replace
function. Con la clausola or replace, qualsiasi privilegio EXECUTE preventivamente concesso
alla funzione verrà mantenuto.
Se la funzione dev’essere creata in uno schema diverso, si dovrà disporre del privilegio di
sistema CREATE ANY PROCEDURE. Se non è specificato uno schema, la funzione verrà cre-
ata nello schema di colui che la crea. Per creare una funzione nel proprio schema, è necessario
disporre del privilegio di sistema CREATE PROCEDURE (che fa parte del ruolo RESOURCE).
Il privilegio di creare procedure comprende anche il privilegio di creare funzioni e package.
È possibile controllare la funzione creando una variabile e impostandone il valore uguale al
valore restituito dalla funzione:
print saldo
SALDO
----------
3.8
Le procedure possono utilizzare anche dei sinonimi locali. Per esempio, si potrebbe creare
un sinonimo locale per una tabella remota, come nell’esempio seguente:
Sarà quindi possibile riscrivere la procedura per rimuovere le specifiche del database link:
La rimozione dei nomi dei database link dalle procedure consente di rimuovere dalla proce-
dura stessa anche i dettagli riguardanti la collocazione fisica della tabella. Se la collocazione
della tabella cambia, verrà modificato solo il sinonimo, mentre la procedura resterà valida.
Valori validi per la colonna Type sono VIEW, PROCEDURE, PACKAGE, FUNCTION, e
PACKAGE BODY.
Per recuperare informazioni su errori relativi a oggetti procedurali, si possono utilizzare
anche altri due livelli di viste del dizionario dati, ALL e DBA. Per informazioni su tali viste, si
rimanda al Capitolo 48.
534 CAPITOLO 31
NEW_LINE Utilizzata con PUT; segnala la fine della linea di output corrente.
PUT e PUT_LINE vengono utilizzate per generare le informazioni di debug che si desidera
visualizzare. Per esempio, se si effettua il debug di una procedura che include un ciclo (fare
riferimento al Capitolo 29), è possibile tenere traccia delle modifiche in una variabile a ogni
esecuzione successiva del ciclo. Per tenere traccia dei valori di una variabile, è possibile utilizza-
re un comando simile a quello descritto nel listato seguente. In questo esempio, viene visualizzato
il valore della colonna Saldo preceduto dalla stringa letterale ‘Dovuto:’
DBMS_OUTPUT.PUT_LINE('Dovuto:'||saldo);
PUT e PUT_LINE possono essere utilizzate anche al di fuori dei cicli, ma con l’uso del
comando return nelle funzioni si possono ottenere gli stessi risultati in modo migliore (si consul-
ti il paragrafo “Sintassi del comando create function” introdotto in precedenza nel capitolo).
Il processo per il calcolo delle spese di ritardo può essere migliorato. Si consideri la query
riportata di seguito:
select Nome,
SPESE_RITARDO(Nome)
from UTENTI_PRESTITO_LIBRI;
NOME SPESE_RITARDO(NOME)
------------------------- -------------------
DORAH TALBOT -.8
EMILY TALBOT .2
FRED FULLER 3.8
GERHARDT KENTGEN 2.8
JED HOPKINS 1.4
PAT LAVAY 2.6
ROLAND BRANDT 22.6
7 rows selected.
Questa query singola si serve della funzione personalizzata SPESE_RITARDO per calcola-
re le spese di ritardo per tutte le persone che hanno preso in prestito un libro. Non è esattamente
così: le persone ricevono dei crediti per i libri che hanno restituito in anticipo. Per aggiungere
una clausola where alla query della funzione, è possibile utilizzare il comando create or replace
function:
select Nome,
SPESE_RITARDO(Nome)
from UTENTI_PRESTITO_LIBRI;
NOME SPESE_RITARDO(NOME)
------------------------- -------------------
DORAH TALBOT .4
EMILY TALBOT .8
FRED FULLER 3.8
536 CAPITOLO 31
declare
some_custom_error EXCEPTION;
Nella parte exception del codice relativo all’oggetto procedurale, si specifica al database
come gestire le eccezioni. Questa parte inizia con la parola chiave exception, seguita da una
clausola when per ciascuna eccezione. Ogni eccezione può chiamare la procedura RAISE_
APPLICATION_ERROR, che accetta due parametri di input: il numero dell’errore (che deve
essere compreso tra –20001 e –20999) e il messaggio d’errore da visualizzare. Nell’esempio
precedente era definita una sola eccezione. Tuttavia, si possono definire più eccezioni, come
mostrato nel listato seguente; si può ricorrere alla clausola when others per gestire tutte le ecce-
zioni non specificate:
EXCEPTION
when NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20100,
‘Nessun libro in prestito.’);
when some_custom_error THEN
RAISE_APPLICATION_ERROR (-20101,
‘Some custom error message.’);
Una specifica di package è costituita dall’elenco delle funzioni, procedure, variabili, costan-
ti, cursori ed eccezioni che saranno messi a disposizione degli utenti del package.
Di seguito è riportato un comando create package di esempio. In questo esempio, viene
creato il package GESTIONE_LIBRO. La funzione SPESE_RITARDO e la procedura NUO-
VO_LIBRO presentate in precedenza sono comprese nel package.
NOTA Si può aggiungere il nome dell’oggetto procedurale alla clausola end per
agevolare la coordinazione della logica nel codice.
Il corpo di un package contiene i blocchi e le specifiche per tutti gli oggetti pubblici elencati
nelle specifiche del package. Il corpo potrà comprendere oggetti non elencati nelle specifiche.
Tali oggetti vengono detti privati e non sono disponibili per gli utenti del package. Solo gli altri
oggetti contenuti nel corpo dello stesso package possono chiamare gli oggetti privati. Il corpo di
un package può includere anche del codice che viene eseguito ogni volta che si chiama il package,
indipendentemente dalla parte del package eseguita (per un esempio, si rimanda al paragrafo
“Inizializzazione di package” più avanti in questo capitolo).
La sintassi per la creazione dei corpi dei package è la seguente:
Il nome del corpo del package dovrebbe coincidere con quello della specifica.
Continuando con l’esempio di GESTIONE_LIBRO, il corpo del package può essere creato
mediante il comando create package body riportato nel listato seguente:
saldo NUMBER(10,2);
begin
select SUM(((DataRestituzione-DataPrestito) -14)*0.20)
into saldo
from BIBLIOTECA_PRESTITO
where Nome = aNome
and (DataRestituzione-DataPrestito) > 14;
RETURN(saldo);
EXCEPTION
when NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20100,
'Nessun libro in prestito.');
end SPESE_RITARDO;
procedure NUOVO_LIBRO (aTitolo IN VARCHAR2,
aEditore IN VARCHAR2, aNomeCategoria IN VARCHAR2)
is
begin
insert into BIBLIOTECA
(Titolo, Editore, NomeCategoria, Valutazione)
values (aTitolo, aEditore, aNomeCategoria, NULL);
delete from LIBRO_ORDINE
where Titolo = aTitolo;
end NUOVO_LIBRO;
end GESTIONE_LIBRO;
NOTA Il codice che dev’essere eseguito la prima volta che si esegue un compo-
nente del package viene memorizzato in un proprio blocco PL/SQL al termine del corpo del
package. Tale codice non dispone di una propria clausola end e utilizza quella del corpo del
package.
La prima volta che un componente del package GESTIONE_LIBRO viene eseguito nella
sessione dell’utente, le variabili Nome_Utente e Data_Voce vengono popolate dalla query mo-
strata nel listato precedente. Queste due variabili potranno quindi essere utilizzate dalle funzioni
e dalle procedure all’interno del package, anche se in questo esempio non accade per motivi di
spazio.
Per eseguire una procedura o una funzione che si trova all’interno di un package, occorre
specificare il nome del package e il nome della procedura o funzione nel comando execute,
come mostrato di seguito:
ALL_SOURCE Per oggetti procedurali di proprietà dell’utente o per i quali all’utente è stato concesso l’accesso.
La selezione delle informazioni dalla vista USER_SOURCE avviene tramite una query si-
mile a quella riportata nel listato seguente. In questo esempio, viene selezionata la colonna Text,
ordinata per numero di linea. Il nome e il tipo dell’oggetto servono per definire per quale oggetto
verrà visualizzato il codice sorgente. Nell’esempio seguente, viene utilizzata la procedura
NUOVO_LIBRO descritta in precedenza nel capitolo:
select Text
from USER_SOURCE
where Name = ‘NUOVO_LIBRO’
and Type = ‘PROCEDURE’
order by Line;
TEXT
--------------------------------------------------
procedure NUOVO_LIBRO (aTitolo IN VARCHAR2,
aEditore IN VARCHAR2, aNomeCategoria IN varchar2)
as
begin
insert into BIBLIOTECA (Titolo, Editore, NomeCategoria, Valutazione)
values (aTitolo, aEditore, aNomecategoria, NULL);
delete from LIBRO_ORDINE
where Titolo = aTitolo;
end;
Come illustrato in questo esempio, la vista USER_SOURCE contiene un record per ciascu-
na linea della procedura NUOVO_LIBRO. La sequenza delle linee viene mantenuta dalla colon-
na Line, ed è proprio per questo motivo che la colonna Line dovrebbe essere utilizzata nella
clausola order by.
Valori validi per la colonna Type sono PROCEDURE, FUNCTION, PACKAGE, PACKAGE
BODY, JAVA SOURCE, TYPE e TYPE BODY.
ricompilare una procedura, occorre utilizzare il comando alter procedure, come mostrato nel
listato seguente. La clausola compile è l’unica opzione valida per questo comando.
Per ricompilare una procedura, è necessario esserne il proprietario oppure disporre del pri-
vilegio di sistema ALTER ANY PROCEDURE.
Per ricompilare una funzione, si utilizza il comando alter function con la clausola compile:
Per ricompilare una funzione, è necessario esserne il proprietario o disporre del privilegio di
sistema ALTER ANY PROCEDURE.
Quando si ricompilano i package, si può ricompilare sia la specifica sia il corpo del package
oppure scegliere di operare solo sul corpo. Per default, vengono ricompilati entrambi (corpo e
specifica). I comandi alter function o alter procedure non possono essere utilizzati per ricompilare
funzioni e procedure memorizzate all’interno di un package.
Se il codice sorgente delle procedure o funzioni all’interno del corpo del package è cambia-
to, mentre la specifica del package è rimasta immutata, è possibile ricompilare solo il corpo del
package. Nella maggior parte dei casi, è opportuno ricompilare entrambi.
Ecco la sintassi del comando alter package:
Per ricompilare un package, si utilizza il comando alter package precedente con la clausola
compile, come mostrato di seguito:
Per eliminare una procedura, è necessario esserne il proprietario oppure possedere il privile-
gio di sistema DROP ANY PROCEDURE.
Per eliminare una funzione, si utilizza il comando drop function, come mostrato di seguito:
Per eliminare una funzione, è necessario esserne il proprietario o disporre del privilegio di
sistema DROP ANY PROCEDURE.
Per eliminare il corpo di un package, si utilizza il comando drop package con la clausola
body, come nell’esempio seguente:
È
possibile utilizzare il linguaggio SQL dinamico nativo per
creare procedure di generiche ed eseguire i comandi DDL in PL/SQL. Si può ricorrere a SQL
dinamico per eseguire comandi SQL generati in fase di esecuzione invece che in fase di creazio-
ne di un programma. SQL dinamico può essere impiegato all’interno degli oggetti procedurali
memorizzati (come i package) e in blocchi PL/SQL anonimi. Per esempio, è possibile generare
procedure che creano tabelle, che utilizzano i nomi delle tabelle come parametri di input o che
accettano le clausole where come parametri di input.
create table CD
(Artista VARCHAR2(25),
Titolo VARCHAR2(25));
È possibile verificare l’avvenuta esecuzione dei comandi effettuando una query sulla tabella
nuova:
ARTISTA TITOLO
------------------------- -------------------------
NEIL FINN TRY WHISTLING THIS
Si può scrivere del codice SQL dinamico nativo con il quale i parametri di input saranno
passati ai comandi SQL:
declare
Symbol VARCHAR2(6) := 'WOND';
begin
EXECUTE IMMEDIATE 'delete from STOCK where Symbol = :symbol'
USING Symbol;
end;
/
La variabile symbol è impostata al valore ‘WOND', che successivamente verrà passato al coman-
do delete attraverso la clausola using.
Nel listato seguente, una procedura di nome DELETE_ROWS cancellerà tutte le righe dalla
tabella passata come variabile. Se si inserisce un valore where_clause durante l’esecuzione della
procedura, questo verrà aggiunto in modo dinamico al comando delete; in caso contrario tutte le
righe verranno cancellate:
execute DELETE_ROWS('STOCK');
Oltre ad invocare le istruzioni SQL, con SQL dinamico nativo si possono anche eseguire
procedure e blocchi PL/SQL.
declare
Symbol VARCHAR2(6) := 'WOND';
begin
EXECUTE IMMEDIATE 'delete from STOCK where Symbol = :symbol'
USING Symbol;
end;
/
Nel listato precedente, :symbol è una bind variable. I valori successivi di symbol potranno
essere passati nel comando EXECUTE IMMEDIATE. Dato che si utilizza una bind variable, il
comando non dovrà essere analizzato ripetutamente. Se si tiene sotto controllo il database duran-
te l’esecuzione dell’applicazione, in V$SQL si noterà la presenza di una voce per il comando. Se
si decidesse di non utilizzare variabili bind, in V$SQL si noterebbe una voce separata per ogni
esecuzione separata del comando. In altre parole, invece di visualizzare
nella library cache, si vedrebbe una voce per ogni cancellazione unica, per esempio
e così via.
Ciascun comando verrebbe analizzato separatamente e ciascuno occuperebbe un certo spa-
zio nella memoria. Pertanto, senza le bind variable la SGA potrebbe riempirsi con un gran nume-
ro di comandi molto simili; uno spreco di risorse che si suppone il database possa sfruttare e una
potenziale causa di problemi a livello di prestazioni. Gli amministratori di database possono
risolvere in parte questo problema impostando il parametro di inizializzazione
CURSOR_SHARING a SIMILAR, tuttavia si tratta di un problema che, per sua natura, andreb-
be risolto con un approccio di sviluppo appropriato.
Durante l’esecuzione della query, gli argomenti di bind sostituiscono i segnaposto corri-
spondenti nella stringa. A ogni segnaposto si deve associare una bind variable nella clausola
using o nella clausola returning into. Le bind variable possono essere numeri, caratteri o costanti
stringa.
548 CAPITOLO 32
L’esempio seguente mostra come utilizzare le bind variable all’interno di un’istruzione update
dinamica:
declare
sql_stmt VARCHAR2(200);
Symbol VARCHAR2(6) := 'ADSP';
CloseToday NUMBER(6,2);
begin
sql_stmt := 'update STOCK set CloseToday = 32 WHERE Symbol = :1
RETURNING CloseToday INTO :2';
EXECUTE IMMEDIATE sql_stmt USING Symbol RETURNING INTO CloseToday;
end;
/
La clausola returning into viene utilizzata soltanto nei comandi insert, update e delete che
contengono una clausola returning. Per ogni valore restituito dal comando, deve esistere una
variabile corrispondente nella clausola returning into.
È possibile verificare l’avvenuta esecuzione dei comandi effettuando una query sulla tabella
nuova, come mostrato nel prossimo esempio.
ARTIST TITLE
------------------------- -------------------------
NEIL FINN TRY WHISTLING THIS
Nei paragrafi seguenti verranno descritte le funzioni e le procedure principali utilizzate al-
l’interno delle istruzioni SQL dinamiche.
OPEN_CURSOR
La funzione OPEN_CURSOR del package DBMS_SQL apre un cursore e restituisce al pro-
gramma un numero di ID del cursore. Quindi, all’interno della procedura ANYSTRING, la
variabile cursor_name è definita come un tipo di dati INTEGER:
Cursor_Name INTEGER;
Nella sezione dei comandi eseguibili, la variabile cursor_name è impostata all’output otte-
nuto dall’esecuzione di OPEN_CURSOR:
Cursor_Name := DBMS_SQL.OPEN_CURSOR;
PARSE
Analizzare un’istruzione significa controllarne la sintassi e associarla a un cursore. Per analizza-
re un’istruzione, occorre utilizzare la procedura PARSE del package DBMS_SQL. Per esempio,
nella procedura ANYSTRING il comando seguente analizza il comando SQL. PARSE accetta
tre parametri: l’ID del cursore, il comando da analizzare e un flag del linguaggio.
NOTA L’esecuzione dei comandi DDL (come create table) avviene durante la loro
analisi.
BIND_VARIABLE e BIND_ARRAY
Se la procedura SQL dinamica effettua la manipolazione dei dati, si dovrà ricorrere alle bind
variable. Qualunque comando SQL dinamico che inserisca, aggiorni o cancelli record deve ri-
550 CAPITOLO 32
Dopo l’esecuzione di PARSE, occorrerà associare la bind variable :artist alla variabile
artist_name passata alla procedura. Quando un utente esegue la procedura, per la variabile
artist_name verrà specificato un valore. La procedura BIND_VARIABLE mostrata nel listato se-
guente, associa il valore artist_name alla variabile bind utilizzata dalla stringa di comandi ana-
lizzata:
È possibile ricorrere a SQL dinamico per eseguire più volte un’istruzione DML, ogni volta
con una bind variable diversa. Si può utilizzare la procedura BIND_ARRAY per associare un
array di valori, ciascuno dei quali verrà utilizzato come variabile di input una sola volta per ogni
funzione EXECUTE.
EXECUTE
Per eseguire l’istruzione SQL creata in modo dinamico, occorre la funzione EXECUTE del package
DBMS_SQL. Il listato seguente, tratto dalla procedura ANYSTRING, mostra come utilizzare la
funzione EXECUTE:
Ret := DBMS_SQL.EXECUTE(Cursor_Name);
Quando si usa la funzione EXECUTE, il valore di ID del cursore (in questo esempio si tratta
della variabile cursor_name) viene passato come input. La variabile ret contiene l’output della
funzione EXECUTE, che corrisponderà al numero di righe elaborate (se l’istruzione eseguita usa
DML).
DEFINE_COLUMN
Se il cursore effettua una query, occorre eseguire la funzione DEFINE_COLUMN una volta per
ogni colonna selezionata. Se la colonna è definita con un tipo di dati LONG, al posto della
funzione DEFINE_COLUMN occorre utilizzare la funzione DEFINE_COLUMN_LONG. Se i va-
lori vengono selezionati in un array PL/SQL, al posto di DEFINE_COLUMN conviene utilizzare
DEFINE_ARRAY.
Per esempio, si consideri la query analizzata nel comando seguente:
Prima di eseguire il cursore, occorre definire le colonne in base alla loro posizione nella
query, come mostrato nel listato seguente:
Dopo aver definito le colonne, si può utilizzare la funzione EXECUTE per eseguire il cursore.
if DBMS_SQL.FETCH_ROWS(Get_CD_Cursor)>0 then
Per il record recuperato, la procedura COLUMN_VALUE viene eseguita una sola volta per
ogni colonna selezionata:
DBMS_SQL.COLUMN_VALUE(Get_CD_Cursor, 1, Artista);
DBMS_SQL.COLUMN_VALUE(Get_CD_Cursor, 2, Titolo);
Ora che i valori sottoposti a query sono stati associati alle variabili, è possibile associare tali
valori nel cursore che inserisce i record nella tabella CD_COPY:
Ora si può procedere all’esecuzione del cursore che inserisce i valori nella tabella CD_COPY:
Ret := DBMS_SQL.EXECUTE(Insert_CD_COPY_Cursor);
La variabile ret conterrà il numero di righe inserite nella tabella CD_COPY. Se è stata invo-
cato una procedura dall’interno di un blocco PL/SQL anonimo, conviene eseguire la funzione
VARIABLE_VALUE per recuperare i valori assegnati alle sue variabili di output.
CLOSE_CURSOR
È possibile chiudere un cursore aperto eseguendo la procedura CLOSE_CURSOR del package
DBMS_SQL. L’esempio riportato nel listato seguente, tratto dalla procedura ANYSTRING,
mostra come la procedura CLOSE_CURSOR utilizzi il valore di ID del cursore come unico
parametro di input:
552 CAPITOLO 32
DBMS_SQL.CLOSE_CURSOR(Cursor_Name);
COLUMN_VALUE_LONG Restituisce tutto o una parte di un elemento del tipo di dati LONG nella query di un cursore.
DEFINE_COLUMN Definisce una colonna che dev’essere selezionata da una query di un cursore.
DEFINE_COLUMN_LONG Definisce una colonna del tipo di dati LONG che dev’essere selezionata da una query di un
cursore.
IS_OPEN Verifica se un cursore è aperto; i valori restituiti possibili sono TRUE e FALSE.
A OGGETTI
DATABASE RELAZIONALI
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 33
Implementazione di tipi,
viste oggetto e metodi
I
n questo capitolo sono riportate informazioni dettagliate sul-
l’uso dei tipi di dati astratti. Il capitolo si occupa di argomenti come l’amministrazione della
sicurezza per i tipi di dati astratti e l’indicizzazione degli attributi di questi tipi di dati. Viene
descritta anche la creazione di metodi per i tipi di dati astratti, insieme all’impiego di viste
oggetto e di trigger di tipo INSTEAD OF.
Per usare le informazioni fornite in questo capitolo, si dovrebbe avere già una certa familia-
rità con i tipi di dati (Capitolo 4), le viste (Capitolo 18), il comando grant (Capitolo 19), gli
indici (Capitolo 17) e le procedure e i trigger PL/SQL (Capitoli 29, 30 e 31). Gli elementi di
ciascuno di questi argomenti ricoprono un ruolo sostanziale nell’implementazione di un database
relazionale a oggetti.
Il comando create type del listato precedente crea un tipo di dati astratto INDIRIZZO_TY,
che può essere utilizzato quando si creano altri oggetti di database. Per esempio, il comando
create type seguente crea il tipo di dati PERSONA_TY utilizzando il tipo di dati INDIRIZZO_TY
come tipo di dati per la colonna Indirizzo:
Dato che la colonna Indirizzo del tipo di dati PERSONA_TY utilizza il tipo di dati
INDIRIZZO_TY, non contiene un solo valore, bensì quattro, ossia le quattro colonne che costi-
tuiscono il tipo di dati INDIRIZZO_TY.
Se George non è il proprietario del tipo di dati astratto INDIRIZZO_TY, Oracle risponderà
a questo comando create type con il messaggio seguente:
Gli errori di compilazione sono causati da problemi nella creazione del constructor method,
un metodo speciale creato da Oracle al momento della creazione del tipo di dati. Oracle non è in
grado di risolvere il riferimento al tipo di dati INDIRIZZO_TY, in quanto George non possiede
un tipo di dati con quel nome. George potrebbe eseguire nuovamente il comando create type
(con la clausola or replace) per fare un riferimento specifico al tipo di dati INDIRIZZO_TY di
Dora:
Per visualizzare gli errori associati alla creazione del tipo di dati, si utilizza il comando show
errors:
show errors
Errors for TYPE PERSONA_TY:
LINE/COL ERROR
-------- --------------------------------------------------------
0/0 PL/SQL: Compilation unit analysis terminated
3/11 PLS-00201: identifier ‘DORA.INDIRIZZO_TY’ must be declared
George non sarà in grado di creare il tipo di dati PERSONA_TY (che comprende il tipo di
dati INDIRIZZO_TY), a meno che Dora non gli conceda il privilegio EXECUTE sul proprio
tipo di dati. Il listato seguente mostra la concessione di tale privilegio:
IMPLEMENTAZIONE DI TIPI, VISTE OGGETTO E METODI 557
Ottenuti i privilegi richiesti, George potrà creare un tipo di dati basato sul tipo di dati
INDIRIZZO_TY di Dora, come mostrato nel listato seguente.
L’uso dei tipi di dati di un altro utente è significativo. Per esempio, durante le operazioni di
inserimento è necessario specificare il nome del proprietario di ciascun tipo di dati o utilizzare
un sinonimo. George sarà in grado di creare una tabella basata sul proprio tipo di dati
PERSONA_TY (che include il tipo di dati INDIRIZZO_TY di Dora), come nell’esempio se-
guente:
Dato che George non possiede il tipo di dati INDIRIZZO_TY, questo comando non viene
completato con successo. Durante l’operazione di inserimento viene utilizzato il constructor
method INDIRIZZO_TY, posseduto da Dora. Pertanto il comando insert dev’essere modificato
in modo da specificare Dora come proprietario del tipo di dati INDIRIZZO_TY. Nell’esempio
seguente è descritta l’istruzione insert corretta con il riferimento a Dora evidenziato in grassetto:
describe CLIENTE
Per mostrare gli attributi del tipo di dati per le tabelle che utilizzano caratteristiche relazionali
a oggetti, si può ricorrere al comando set describe depth in SQL*Plus. Si possono specificare
valori di profondità compresi tra 1 e 50:
desc CLIENTE
desc cliente
NOTA Quando si esegue una query sugli attributi di un tipo di dati astratto, è
necessario utilizzare una variabile di correlazione per la tabella, come mostrato in questo esempio.
Per impostare gli attributi di visualizzazione per gli attributi di un tipo di dati astratto in
SQL*Plus, si utilizza il comando column, specificando il nome del tipo di dati e l’attributo:
Per fare riferimento ad attributi all’interno del tipo di dati INDIRIZZO_TY, occorre specifi-
care il percorso completo attraverso le colonne correlate. Per esempio, alla colonna Via si fa
riferimento tramite Persona.Indirizzo.Via, descrivendo per esteso la sua collocazione all’interno
della struttura della tabella. Nell’esempio seguente, si fa riferimento due volte alla colonna Citta:
nell’elenco di colonne da selezionare e all’interno della clausola where. In ogni riferimento, è
richiesta una variabile di correlazione (in questo caso, C ).
select C.Persona.Nome,
C.Persona.Indirizzo.Citta
from CLIENTE C
where C.Persona.Indirizzo.Citta like 'C%';
Dato che la colonna Citta viene utilizzata con un intervallo di ricerca all’interno della clau-
sola where, l’ottimizzatore di Oracle è in grado di utilizzare un indice al momento di risolvere la
query. Se nella colonna Citta è disponibile un indice, Oracle potrà individuare rapidamente tutte
le righe i cui valori di Citta iniziano con la lettera ‘C’, come richiesto dalla query.
NOTA Per indicazioni relative alle colonne da indicizzare, si rimanda al Capitolo 43.
Per creare un indice su una colonna che faccia parte di un tipo di dati astratto, si deve speci-
ficare il percorso completo sino alla colonna come parte del comando create index. Per creare un
indice sulla colonna Citta (che fa parte della colonna Indirizzo), è possibile eseguire il comando
riportato di seguito:
NOTA Nel comando create index non si ricorre alle variabili di correlazione quan-
do si fa riferimento agli attributi di tipi di dati astratti.
Per creare tabelle basate su tipi di dati astratti, è necessario considerare come avviene l’ac-
cesso alle colonne all’interno di tali tipi di dati. Se, come avviene per la colonna Citta nell’esem-
pio precedente, alcune colonne vengono utilizzate normalmente come parte delle condizioni di
limitazione nelle query, queste colonne devono essere indicizzate. A questo riguardo, la rappre-
sentazione di più colonne in un unico tipo di dati astratto può determinare un peggioramento
delle prestazioni dell’applicazione, in quanto può mascherare l’esigenza di indicizzare colonne
specifiche all’interno del tipo di dati. Con i tipi di dati astratti, ci si abitua a trattare un gruppo di
colonne come un’unica entità, come le colonne Indirizzo o le colonne Persona. È importante
ricordare che l’ottimizzatore, in sede di valutazione dei percorsi di accesso della query, prende in
considerazione le colonne singolarmente. Inoltre, l’indicizzazione della colonna Citta in una
tabella che utilizza il tipo di dati INDIRIZZO_TY non influisce sulla colonna Citta presente in
una seconda tabella che usa il tipo di dati INDIRIZZO_TY. Per esempio, se esiste una seconda
tabella di nome FILIALE che utilizza il tipo di dati INDIRIZZO_TY, la sua colonna Citta non
verrà indicizzata, a meno che non si crei un indice per essa. La presenza di un indice sulla
colonna Citta nella tabella CLIENTE non influisce sulla colonna Citta nella tabella FILIALE.
Pertanto, uno dei vantaggi offerti dai tipi di dati astratti, la capacità di migliorare l’aderenza
agli standard per la rappresentazione di dati logici, non si estende alla rappresentazione dei dati
fisici. Ciascuna implementazione fisica dev’essere curata separatamente.
NOTA In tutti gli esempi del libro, i nomi delle viste oggetto terminano sempre
con il suffisso “OV”.
Negli esempi riportati in precedenza nel capitolo, l’ordine delle operazioni era il seguente:
1. Creazione del tipo di dati INDIRIZZO_TY.
IMPLEMENTAZIONE DI TIPI, VISTE OGGETTO E METODI 561
Per creare un’altra tabella o applicazione che memorizzi informazioni su persone e indirizzi,
si può scegliere di creare i tipi di dati INDIRIZZO_TY e PERSONA_TY. Per coerenza, questi
dovrebbero essere applicati anche alla tabella CLIENTE.
Con la tabella CLIENTE appena creata (e possibilmente popolata di dati), è possibile creare
tipi di dati astratti. In primo luogo, si crei INDIRIZZO_TY:
Ora si crei una vista oggetto basata sulla tabella CLIENTE, utilizzando i tipi di dati definiti.
Una vista oggetto inizia con il comando create view. All’interno del comando create view è
possibile specificare la query che costituirà la base della vista. Verranno utilizzati i tipi di dati
appena creati. Il codice necessario per la creazione della vista oggetto CLIENTE_OV è riportato
nel listato seguente:
Si analizzi in dettaglio questo comando. Nella prima linea, si assegna un nome alla vista
oggetto:
select Cliente_ID,
PERSONA_TY(Nome,
INDIRIZZO_TY(Via, Citta, Prov, Cap))
from CLIENTE;
Questo esempio mostra alcuni impieghi interessanti della sintassi. Quando si crea una tabel-
la su tipi di dati astratti già esistenti, i valori delle colonne vengono selezionati dalla tabella
facendo riferimento ai nomi delle colonne (come Persona e Indirizzo, negli esempi precedenti)
invece che ai loro constructor method. Per la creazione di una vista oggetto, occorre fare riferi-
mento ai nomi dei constructor method (PERSONA_TY e INDIRIZZO_TY).
Nella query che costituisce la base della vista oggetto è possibile utilizzare una clausola
where. Nell’esempio seguente, CLIENTE_OV viene modificata in modo da includere una clau-
sola where che la limita alla sola visualizzazione dei valori CLIENTE per i quali la colonna Prov
contiene un valore ‘MI’:
Quando si crea la vista oggetto CLIENTE_OV, la clausola where della query di base della
vista non fa riferimento al tipo di dati astratto. Al contrario, essa fa riferimento direttamente alla
tabella CLIENTE. La clausola where fa riferimento direttamente alla colonna Prov perché la
query si riferisce direttamente alla tabella CLIENTE, una tabella relazionale che non si basa su
tipi di dati astratti.
Per creare viste oggetto basate su tabelle relazionali, l’ordine delle operazioni è il seguente:
1. Creazione della tabella CLIENTE se non esiste ancora.
2. Creazione del tipo di dati INDIRIZZO_TY.
3. Creazione del tipo di dati PERSONA_TY, utilizzando il tipo di dati INDIRIZZO_TY.
4. Creazione della vista oggetto CLIENTE_OV, utilizzando i tipi di dati definiti.
L’uso di viste oggetto presenta due vantaggi principali. Innanzi tutto, queste consentono di
creare tipi di dati astratti che operano su tabelle già esistenti; dato che si possono utilizzare gli
stessi tipi di dati astratti in più tabelle dell’applicazione, si potrà migliorare l’aderenza dell’ap-
plicazione alla rappresentazione standard dei dati e la capacità di riutilizzare gli oggetti già
esistenti. Inoltre, dal momento che si possono definire metodi per i tipi di dati astratti, questi
metodi verranno applicati sia ai dati contenuti nelle nuove tabelle, sia ai dati delle tabelle
preesistenti.
IMPLEMENTAZIONE DI TIPI, VISTE OGGETTO E METODI 563
In secondo luogo, le viste oggetto offrono due modi diversi per inserire i dati nella tabella
base. La flessibilità nella manipolazione di dati per le viste oggetto, in grado di trattare la tabella
base sia come una tabella relazionale, sia come una tabella oggetto, rappresenta un vantaggio
significativo per gli sviluppatori di applicazioni. Nel paragrafo seguente, vengono descritte le
opzioni per la manipolazione dei dati disponibili per le viste oggetto.
Questo comando insert inserisce un singolo record nella tabella CLIENTE. Anche se sulla
tabella è stata creata una vista oggetto, è sempre possibile considerare la tabella CLIENTE come
una tabella relazionale convenzionale.
Dato che la vista oggetto è stata creata sulla tabella CLIENTE, è possibile eseguire opera-
zioni di inserimento in CLIENTE tramite i constructor method utilizzati dalla vista. Come mo-
strato in precedenza in questo capitolo, quando si inseriscono dei dati in un oggetto che utilizza
tipi di dati astratti, è necessario specificare i nomi dei constructor method all’interno del coman-
do insert. L’esempio proposto nel listato seguente descrive l’inserimento di un singolo record
nella vista oggetto CLIENTE_OV, utilizzando i constructor method CLIENTE_TY, PERSO-
NA_TY e INDIRIZZO_TY:
Dato che si possono utilizzare entrambi i metodi per inserire i valori nella vista oggetto
CLIENTE_OV, è possibile standardizzare il modo in cui l’applicazione manipola i dati. Se le
operazioni di inserimento si basano tutte su tipi di dati astratti, per queste operazioni si potrà
utilizzare lo stesso tipo di codice, indipendentemente dal fatto che i tipi di dati astratti siano stati
creati prima o dopo la tabella.
È possibile eseguire una query sulle righe appena inserite da CLIENTE o CLIENTE_OV;
ma dato che la vista contiene una clausola where, CLIENTE_OV mostrerà solamente quelle
righe che superano questa condizione di limitazione.
cerchi di modificare i valori tramite la vista. Il codice contenuto nel trigger INSTEAD OF viene
eseguito al posto del comando insert, update o delete inserito.
Per esempio, si può avere una vista che unisce tramite join la tabella BIBLIOTECA alla
tabella BIBLIOTECA_AUTORE:
È possibile selezionare dei valori da questa vista e manipolare i dati mediante la vista stessa
con i trigger INSTEAD OF. Si considerino questi record:
NOMEAUTORE EDITORE
-------------------------------------------------- ----------
W. P. KINSELLA MARINER
W. P. KINSELLA BALLANTINE
update AUTORE_EDITORE
set Editore = 'MARINER'
where NomeAutore = 'W. P. KINSELLA';
Il problema è che Oracle non è in grado di stabilire quale editore di quale record aggiornare
in BIBLIOTECA. Per eseguire l’aggiornamento tramite la vista, si dovrà ricorrere a un trigger
INSTEAD OF.
Nel listato seguente viene creato un trigger INSTEAD OF per la vista AUTORE_EDITORE:
Nella prima parte di questo trigger, si assegna un nome al trigger stesso e se ne descrive
l’uso tramite la clausola instead of. Il nome assegnato al trigger ne descrive il funzionamento: il
trigger serve per supportare i comandi update eseguiti sulla vista AUTORE_EDITORE. Si tratta
di un trigger a livello di riga; ogni riga modificata viene elaborata, come mostrato di seguito.
La sezione successiva del trigger specifica a Oracle come eseguire l’aggiornamento. Duran-
te il primo controllo all’interno del corpo del trigger, viene verificato il valore Editore. Se il
vecchio valore Editore è uguale a quello nuovo, non vengono apportate modifiche. Se i valori
non sono identici, la tabella BIBLIOTECA viene aggiornata con il nuovo valore Editore:
begin
if :old.Editore <> :new.Editore
then
update BIBLIOTECA
set Editore = :new.Editore
where Titolo = :old.Titolo;
end if;
Nella sezione successiva del trigger viene valutato il valore NomeAutore. Se questo valore è
cambiato, la tabella BIBLIOTECA viene aggiornata in modo da contenere il nuovo valore
NomeAutore:
update AUTORE_EDITORE
set Editore = 'MARINER'
where NomeAutore = 'W. P. KINSELLA';
2 rows updated.
L’avvenuto aggiornamento può essere verificato con una query sulla tabella BIBLIOTECA:
EDITORE
--------------------
MARINER
MARINER
I trigger INSTEAD OF sono molto potenti. Come illustrato in questo esempio, possono
essere utilizzati per eseguire operazioni su tabelle differenti del database, utilizzando la logica di
controllo del flusso disponibile all’interno del linguaggio PL/SQL. Quando si gestiscono le viste
oggetto, si possono utilizzare i trigger INSTEAD OF per reindirizzare DML dalle viste oggetto
alle tabelle base delle viste.
33.3 Metodi
Per la creazione di una vista oggetto sulla tabella CLIENTE sono stati definiti tipi di dati astratti
utilizzati dalla tabella stessa. Questi tipi di dati aiutano a standardizzare la rappresentazione dei
dati, ma hanno anche un altro scopo. È possibile definire metodi che si applichino ai tipi di dati,
e applicando questi ultimi a tabelle già esistenti sarà possibile applicare i metodi ai dati contenuti
nelle tabelle stesse.
Si consideri la vista oggetto CLIENTE_OV:
Questa vista applica i tipi di dati astratti PERSONA_TY e INDIRIZZO_TY ai dati contenu-
ti nella tabella CLIENTE. Se questi tipi di dati sono associati a dei metodi, questi potranno
essere applicati ai dati della tabella. Per la creazione di un tipo di dati astratto si può utilizzare il
comando create type. Per la creazione di un metodo si utilizza il comando create type body.
Il tipo di dati ANIMALE_TY può essere utilizzato come parte di una vista oggetto sulla
tabella ALLEVAMENTO utilizzata nel Capitolo 14. In questa tabella sono registrati il nome di
un discendente, il suo sesso, i suoi genitori, e la sua data di nascita.
All’interno del comando create type, la linea:
assegna un nome alla funzione che rappresenta un “membro” del tipo di dati ANIMALE_TY.
Dato che ETA restituisce un valore, si tratta di una funzione (si consulti il Capitolo 31). Per
definire la funzione ETA, occorre utilizzare il comando create type body, la cui sintassi comple-
ta è descritta nel Capitolo 48.
Si crei la funzione ETA come funzione membro all’interno del tipo di dati ANIMALE_TY.
La funzione ETA restituisce l’età degli animali in giorni:
Per codificare altre funzioni o procedure, è necessario specificarle all’interno dello stesso
comando create type body, prima della clausola finale end.
Completata la creazione della funzione ETA, questa viene associata al tipo di dati
ANIMALE_TY. Se una tabella utilizza questo tipo di dati, sarà in grado di utilizzare la funzione
ETA.
La funzione ETA può essere utilizzata all’interno di una query. Se ANIMALE_TY viene
utilizzato come tipo di dati per una colonna di nome Animale nella tabella ANIMALE, la strut-
tura della tabella può essere quella riportata di seguito:
Ora è possibile invocare la funzione ETA, che fa parte del tipo di dati ANIMALE_TY. Come
accade con gli attributi di un tipo di dati astratto, è possibile fare riferimento ai metodi membro
tramite i nomi delle colonne che utilizzano i tipi di dati (in questo caso, Animale.ETA). Il risul-
tato rifletterà la data di sistema corrente del momento in cui si esegue la query:
select A.Animale.ETA(A.Animale.DataNascita)
from ANIMALE A;
A.ANIMALE.ETA(A.ANIMALE.DATANASCITA)
------------------------------------
2694
Collettori
(tabelle nidificate
e array variabili)
I
collettori utilizzano tipi di dati astratti. Prima di usare gli array
variabili e le tabelle annidate è consigliabile formarsi una conoscenza approfondita della crea-
zione e implementazione di questi tipi di dati (Capitolo 33).
Anche se il valore Nome del vicino non cambia, viene ripetuto in ciascun record in quanto fa
parte della chiave primaria. I collettori come gli array variabili consentono di ripetere solo i
valori di colonna che cambiano, permettendo un potenziale risparmio di spazio su disco. I collet-
tori possono essere utilizzati per rappresentare in modo accurato le relazioni tra tipi di dati negli
oggetti del database. Nei paragrafi seguenti, si imparerà a creare e usare i collettori.
Per creare un array variabile (cui verrà assegnato il nome ATTREZZI_VA) non è necessario
creare prima il tipo base, in questo caso ATTREZZO_TY. Dato che l’array variabile si basa su
un’unica colonna, è possibile creare il tipo ATTREZZI_VA in un unico passaggio. Per creare
l’array variabile, si utilizza la clausola as varray() del comando create type:
Quando si esegue questo comando create type, viene creato un tipo di nome ATTREZZI_VA.
La clausola as varray(5) comunica a Oracle la creazione di un array variabile contenente un
massimo di cinque voci per record. Il nome dell’array variabile è al plurale, ATTREZZI anziché
ATTREZZO, per ricordare che questo tipo verrà utilizzato per contenere più record. Il suffisso
VA chiarisce che il tipo è proprio un array variabile. Ora questo tipo potrà servire da base per la
definizione di una colonna, come mostrato nel listato seguente:
desc PRESTITO
Si osservi che il comando set describe depth, descritto nel Capitolo 33, non influisce su
questo output. È possibile eseguire una query su informazioni simili da USER_TAB_COLUMNS:
select Column_Name,
Data_Type
from USER_TAB_COLUMNS
where Table_Name = 'PRESTITO';
COLUMN_NAME DATA_TYPE
------------------------------ -------------
NOME VARCHAR2
ATTREZZI ATTREZZI_VA
COLLETTORI (TABELLE NIDIFICATE E ARRAY VARIABILI) 571
select TypeCode,
Attributes
from USER_TYPES
where Type_Name = 'ATTREZZI_VA';
TYPECODE ATTRIBUTES
------------------------------ ----------
COLLECTION 0
Per ulteriori informazioni su ATTREZZI_VA si esegua una query sulla vista del dizionario
dati USER_COLL_TYPES, come mostrato nel listato seguente.
select Coll_Type,
Elem_Type_Owner,
Elem_Type_Name,
Upper_Bound,
Length
from USER_COLL_TYPES
where Type_Name = 'ATTREZZI_VA'
COLL_TYPE ELEM_TYPE_OWNER
------------------------------ -----------------------------
ELEM_TYPE_NAME UPPER_BOUND LENGTH
------------------------------ ----------- ----------
VARYING ARRAY
VARCHAR2 5 25
Se si basa un array variabile su un tipo di dati astratto già esistente, il proprietario del tipo di
dati viene visualizzato nella colonna Elem_Type_Owner e il nome del tipo di dati nella colonna
Elem_Type_Name. Dato che ATTREZZI_VA utilizza VARCHAR2 invece di un tipo di dati astrat-
to, il valore della colonna Elem_Type_Owner è NULL.
Questo comando insert specifica subito il valore per la colonna Nome. Dato che questa
colonna non fa parte di alcun tipo di dati astratto, viene popolata nello stesso modo in cui si
inserirebbero dei valori in una qualsiasi colonna relazionale:
La parte successiva del comando insert inserisce dei record nella colonna Attrezzi. Dato che
questa utilizza l’array variabile ATTREZZI_VA, è necessario utilizzare il constructor method
ATTREZZI_VA:
ATTREZZI_VA('MARTELLO','MAZZA','ASCIA));
Dato che si tratta di un array variabile, è possibile passare più valori al constructor method
ATTREZZI_VA. Come illustra il listato precedente, per il nome di un vicino sono elencati tre
attrezzi in un unico inserimento. Se l’array variabile si fosse basato sul tipo di dati ATTREZZO_TY,
le chiamate al tipo di dati ATTREZZO_TY sarebbero state nidificate all’interno delle chiamate
a ATTREZZI_VA:
Se si basa l’array variabile su un tipo di dati fornito da Oracle (e si utilizza una sola colonna)
invece che su un tipo di dati astratto o definito dall’utente, si semplifica il comando insert elimi-
nando le chiamate nidificate a più constructor method.
L’array variabile ATTREZZI_VA è stato definito in modo da avere sino a cinque valori. In
questo comando insert sono stati inseriti nella riga soltanto tre valori; gli altri due rimangono
così non inizializzati. Se si desidera impostare i valori non inizializzati a NULL, è sufficiente
specificarlo nel comando insert:
Se si specificano troppi valori da inserire nell’array variabile, Oracle risponde nel modo
seguente:
Non è possibile inserire dei record in una tabella che contiene un array variabile, a meno di
non conoscere la struttura e i tipi di dati all’interno dell’array. Questo esempio presuppone che
tutti i tipi di dati utilizzati dalla tabella PRESTITO fossero contenuti nello schema usato per
creare la stessa tabella PRESTITO. Se i tipi di dati sono di proprietà di un altro schema, si dovrà
concedere al creatore della tabella PRESTITO il privilegio EXECUTE su questi tipi di dati. Per
esempi sull’uso dei tipi di dati creati in altri schemi, si consulti il Capitolo 33.
ATTREZZI
------------------------------------------
ATTREZZI_VA('MARTELLO', 'MAZZA', 'ASCIA')
COLLETTORI (TABELLE NIDIFICATE E ARRAY VARIABILI) 573
Per visualizzare i dati degli array variabile su righe separate, si può ricorrere alla funzione
TABLE nella clausola from. Si consideri la query seguente e il suo output:
NAME COLUMN_NAME
------------------------- -------------------------
JED HOPKINS MARTELLO
JED HOPKINS MAZZA
JED HOPKINS ASCIA
Come funziona? La funzione TABLE accetta come input il nome dell’array variabile mentre
all’output viene assegnato l’alias N. Vengono selezionati i valori in N, creando così la seconda
colonna dell’output.
Per visualizzare i dati dell’array variabile su righe separate si può anche ricorrere a PL/SQL.
Inoltre, è possibile eseguire una query sull’array variabile per stabilirne il numero massimo di
voci per riga, chiamato LIMIT, e il numero corrente di voci per riga, chiamato COUNT. Per
recuperare i valori COUNT e LIMIT nonché i dati da un array variabile, è possibile utilizzare un
insieme di cicli FOR a cursore nidificati, come mostrato nel listato seguente:
NOTA Per la descrizione del linguaggio PL/SQL e dei cicli FOR a cursore si ri-
manda al Capitolo 29.
set serveroutput on
declare
cursor prestito_cursor is
select * from PRESTITO;
begin
for prestito_rec in prestito_cursor
loop
dbms_output.put_line('Nome Contatto: '||prestito_rec.Nome);
for i in 1..prestito_rec.Attrezzi.Count
loop
dbms_output.put_line(prestito_rec.Attrezzi(i));
end loop;
end loop;
end;
/
Lo script implementa diverse caratteristiche di PL/SQL per recuperare i dati dall’array va-
riabile. I dati vengono visualizzati tramite la procedura PUT_LINE del package DBMS_OUTPUT
(Capitolo 31). Per prima cosa è necessario abilitare la visualizzazione dell’output PL/SQL.
set serveroutput on
574 CAPITOLO 34
Nella sezione delle dichiarazioni del blocco PL/SQL viene dichiarato un cursore. La query
del cursore seleziona tutti i valori della tabella PRESTITO:
declare
cursor prestito_cursor is
select * from PRESTITO;
La sezione dei comandi eseguibili del blocco PL/SQL contiene due cicli FOR nidificati. Nel
primo ciclo viene valutato ciascun record del cursore mentre il valore di Nome viene visualizzato
tramite la procedura PUT_LINE:
begin
for prestito_rec in prestito_cursor
loop
dbms_output.put_line('Nome Contatto: '||prestito_rec.Nome);
Nella sezione successiva del blocco PL/SQL, le righe vengono valutate ulteriormente, per
recuperare i dati memorizzati nell’array variabile. Quindi viene eseguito un secondo ciclo FOR,
nidificato all’interno del primo ciclo. Il ciclo FOR interno è limitato dal numero di valori nell’array,
come definito dal metodo COUNT (il numero massimo di valori nell’array è disponibile nel
metodo LIMIT).
I valori nell’array ATTREZZI vengono visualizzati, uno per uno, dal ciclo seguente:
for i in 1..prestito_rec.Attrezzi.Count
loop
dbms_output.put_line(prestito_rec.Attrezzi(i));
La notazione
Attrezzi(i)
end loop;
end loop;
end;
Dato che questo metodo implica dei cicli nidificati all’interno di blocchi PL/SQL, la sele-
zione di dati dagli array variabili non è banale.
Si osservi la possibilità di ottenere una quantità diversa di attrezzi per ciascuna persona, un
numero compreso tra zero e cinque. Per esempio, la riga seguente inserirebbe nell’array variabi-
le una riga con una sola voce:
COLLETTORI (TABELLE NIDIFICATE E ARRAY VARIABILI) 575
Si può selezionare questo dato tramite PL/SQL, la funzione TABLE o con SQL:
NAME COLUMN_NAME
------------------------- -------------------------
JED HOPKINS MARTELLO
JED HOPKINS MAZZA
JED HOPKINS ASCIA
FRED FULLER MARTELLO
Per una maggiore flessibilità nella selezione di dati dai collettori, è consigliato l’uso di
tabelle nidificate, come descritto nel paragrafo successivo.
NOTA È possibile utilizzare la clausola modify limit del comando alter type per
cambiare il numero massimo di voci consentite in un array variabile.
Dopo gli esempi di uso delle tabelle nidificate verranno presentate alcune funzioni aggiuntive
utilizzabili con gli array variabili e le tabelle nidificate.
NOTA Per semplicità, questa versione del tipo di dati ANIMALE_TY non com-
prende alcun metodo. Per questo esempio, si dovrebbe eliminare la tabella ANIMALE nel caso
in cui esista già nel proprio schema Practice.
Il tipo di dati ANIMALE_TY contiene un record per ciascun animale: la sua genealogia, il
nome e la data di nascita. Per utilizzare questo tipo di dati come base di una tabella nidificata, è
necessario creare un nuovo tipo di dati:
576 CAPITOLO 34
La clausola as table of di questo comando create type indica a Oracle che questo tipo di dati
servirà come base per una tabella nidificata. Il nome del tipo di dati, ANIMALI_NT, ha una
radice al plurale per indicare che memorizza più righe, e presenta il suffisso ‘NT’ per indicare
che si tratta di una tabella nidificata.
Ora è possibile creare una tabella di allevatori con il tipo di dati ANIMALI_NT:
In questo comando create table viene creata la tabella ALLEVATORE. La prima colonna di
questa tabella è NomeAllevatore. La seconda colonna è Animali, la cui definizione è la tabella
nidificata ANIMALI_NT.
Quando si crea una tabella che include una tabella nidificata, è necessario specificare il
nome della tabella utilizzata per memorizzare i dati della tabella nidificata. In altre parole, i dati
della tabella nidificata non sono memorizzati “in linea” con i restanti dati della tabella. Al con-
trario, vengono memorizzati separatamente rispetto alla tabella principale. I dati nella colonna
Animali vengono memorizzati in una tabella, mentre i dati nella colonna NomeAllevatore sono
contenuti in una tabella separata. Oracle gestirà i puntatori tra le tabelle. In questo esempio, i dati
“fuori linea” della tabella nidificata vengono memorizzati in una tabella di nome
ANIMALI_NT_TAB:
Questo esempio mette in evidenza l’importanza degli standard di denominazione per i col-
lettori. Se i nomi delle colonne vengono espressi al plurale (“Animali” anziché “Animale”), e si
utilizzano coerentemente i suffissi (“TY,” “NT” e così via), è possibile stabilire la natura di un
oggetto semplicemente in base al suo nome. Inoltre, dato che le tabelle nidificate e gli array
variabili possono basarsi direttamente su tipi di dati definiti in precedenza, i nomi dei primi
possono rispecchiare i nomi di questi ultimi. Pertanto, un tipo di dati di nome ANIMALE_TY
potrebbe essere utilizzato come base per un array variabile ANIMALI_VA o una tabella nidificata
ANIMALI_NT. La tabella nidificata avrebbe una tabella fuori linea a essa associata, di nome
ANIMALI_NT_TAB. Se si è a conoscenza dell’esistenza di una tabella ANIMALI_NT_TAB e
si mantiene una certa coerenza nella denominazione dei propri oggetti, si saprà automaticamente
che questa tabella memorizza dati basati su un tipo di dati ANIMALE_TY.
Con la clausola move del comando alter table è possibile spostare la tabella nidificata. Se si
esegue il comando alter table move sulla tabella ALLEVATORE, la sua tabella nidificata non si
sposterà: per muoverla, occorre usare il nome della tabella di memorizzazione elencata nel co-
mando create table:
Successivamente, viene inserito il valore della colonna Animali. Dato che questa colonna
utilizza la tabella annidata ANIMALI_NT, viene chiamato il constructor method ANIMALI_NT:
ANIMALI_NT(
La tabella annidata ANIMALI_NT utilizza il tipo di dati ANIMALE_TY, quindi per ogni
valore inserito viene chiamato il constructor method ANIMALE_TY:
Con il comando describe si possono visualizzare i tipi di dati che costituiscono la tabella e
la sua tabella annidata. Per abilitare la visualizzazione degli attributi dei tipi di dati, si utilizza il
comando SQL*Plus set describe depth:
578 CAPITOLO 34
desc allevatore
È possibile eseguire una query su questi metadati dalle viste del dizionario dati
USER_TAB_COLUMNS, USER_TYPES, USER_COLL_TYPES e USER_TYPE_ATTRS,
come mostrato negli esempi precedenti di questo capitolo.
ANIMALI_NT però non è una tabella normale, bensì un tipo di dati. Per selezionare delle
colonne (come DataNascita) dalla tabella nidificata, è innanzi tutto necessario “rimuovere” la
tabella, per poterla sottoporre a query. Per prima cosa, si applica la funzione TABLE alla colonna
della tabella nidificata (ALLEVATORE.Animali), come mostrato nel listato seguente:
L’inserimento non fornisce un valore per la colonna NomeAllevatore, in quanto viene sem-
plicemente eseguito un inserimento della riga di una allevatore nella tabella nidificata. La fun-
zione TABLE viene utilizzata nuovamente per “rimuovere” la tabella nidificata nella colonna
Animali (per la riga di Jane) e i nuovi valori vengono inseriti. Si osservi l’uso della clausola
where all’interno della chiamata alla funzione TABLE per specificare le righe su cui si deve agire.
Si può anche aggiornare la data di nascita del cane. In origine, la data di nascita di Julio era
stata inserita come 10-JUN-01 ma alla fine si è scoperto che cadeva il 01-SEP-01. Il seguente
aggiornamento modifica il valore DataNascita per Julio nella tabella nidificata. La sua sintassi e
struttura sono molto simili agli esempi delle query mostrati in precedenza.
Si può verificare questa modifica eseguendo una query sui dati della tabella nidificata:
1 row deleted.
580 CAPITOLO 34
CARDINALITY(ANIMALI)
--------------------
3
La funzione MULTISET EXCEPT prende come input due tabelle nidificate e restituisce il
gruppo di record che si trovano nella prima tabella nidificata ma non nella seconda (in modo
analogo all’operatore minus). MULTISET INTERSECT restituisce le righe in comune a due ta-
belle nidificate. MULTISET UNION effettua una unione di due tabelle nidificate; è possibile
specificare MULTISET UNION ALL (opzione predefinita) o MULTISET UNION DISTINCT.
La funzione SET converte una tabella nidificata in un insieme eliminando i duplicati, resti-
tuendo una tabella nidificata di valori distinti:
set linesize 60
select SET(Animali) from ALLEVATORE;
Per la sintassi di queste funzioni, insieme a quella delle funzioni COLLECT, POWERMULTISET
e POWERMULTISET_BY_CARDINALITY, si rimanda al Capitolo 48.
denza nel capitolo, possono essere memorizzati in una tablespace separata). Di conseguenza, la
quantità di dati analizzati durante le query che non riguardano i dati del collettore può essere
inferiore per una tabella nidificata rispetto a un array variabile. In altre parole, durante una query
il database non avrà bisogno di leggere tutti i dati nella tabella nidificata; se si utilizza un array
variabile, il database potrà limitarsi a leggere i dati dell’array variabile per trovare ciò che cerca.
I dati fuori linea, così come impiegati dalle tabelle nidificate, possono migliorare le prestazioni
delle query.
I dati fuori linea dei collettori emulano il modo in cui i dati verrebbero memorizzati in una
normale applicazione di database relazionale. Per esempio, in un’applicazione relazionale i dati
correlati (come dipendenti e capacità) verrebbero memorizzati in tabelle separate, e queste ver-
rebbero memorizzate fisicamente in locazioni separate. Le tabelle nidificate fuori linea memo-
rizzano i propri dati separatamente dalla tabella principale, pur conservando con essa una rela-
zione. I dati fuori linea possono migliorare le prestazioni delle query distribuendo l’I/O eseguito
sulla tabella principale tra più tabelle separate.
I dati fuori linea vengono utilizzati anche per memorizzare gli oggetti di grandi dimensioni
(LOB) memorizzati internamente (a differenza dei BFILE, che sono puntatori a LOB esterni al
database). Nel prossimo capitolo si imparerà a creare e manipolare valori LOB. La combinazio-
ne di tipi di dati astratti, viste oggetto, collettori e LOB mette a disposizione fondamenta solide
per l’implementazione di un’applicazione di database relazionale a oggetti.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 35
A
l posto di LONG e LONG RAW, si possono usare i tipi di dati
LOB (BLOB, CLOB, NCLOB, e BFILE) per la memorizzazione di dati di lunghezza considere-
vole. Benché continui a consentire la creazione di colonne LONG e LONG RAW, Oracle consi-
glia di creare nuove colonne con i tipi di dati LOB e di convertire le colonne LONG e LONG
RAW esistenti rispettivamente in colonne CLOB o BLOB. Se si utilizza uno di questi tipi di dati
per memorizzare oggetti di grandi dimensioni (LOB), si potranno sfruttare anche le nuove pos-
sibilità di visualizzazione e manipolazione dei dati. Per eseguire ricerche di testo sui dati CLOB,
si può usare anche Oracle Text (consultare il Capitolo 25).
In questo capitolo, viene descritto l’uso dei tipi di dati LOB e la manipolazione di dati, che
non dovranno nemmeno essere memorizzati all’interno del database.
BFILE File binario. Dati binari di sola lettura memorizzati al di fuori del database, la cui lunghezza è limitata dal
sistema operativo.
NCLOB Una colonna CLOB che supporta un set di caratteri a più byte.
Per ogni tabella si possono creare più LOB. Per esempio, si supponga di voler creare una
tabella PROPOSTA per tenere traccia delle proposte formali inoltrate. I record delle proposte
possono essere costituiti da una serie di file creati con elaboratori di testo e fogli di calcolo
utilizzati per documentare e prezzare il lavoro proposto. La tabella PROPOSTA contiene tipi di
dati VARCHAR2 (per colonne come quella relativa al nome del destinatario della proposta) e
tipi di dati LOB (contenenti i file creati con l’elaboratore di testo e il foglio di calcolo).
584 CAPITOLO 35
NOTA Non è possibile creare più colonne LONG o LONG RAW in una singola
tabella.
Dato che si possono sottoporre più proposte allo stesso destinatario, è necessario assegnare
a ciascuna proposta un numero ID_Proposta. La tabella PROPOSTA memorizza il destinatario,
il nome e una breve descrizione della proposta. Quindi, per sfruttare i tipi di dati LOB disponibili
in Oracle, la tabella PROPOSTA include tre colonne:
Budget BLOB contenente un foglio di calcolo che descrive i calcoli di costi e ricavi del lavoro proposto.
Lettera_Present File binario (BFILE) memorizzato all’esterno del database, che contiene la lettera di presentazione allega-
ta alla proposta.
In ogni riga della tabella PROPOSTA verranno memorizzati fino a tre valori LOB. Oracle
sfrutterà le normali capacità del database per supportare l’integrità dei dati e della corrisponden-
za tra le voci Proposta e Budget, ma non per supportare i valori Lettera_Present. Dato che la
colonna Lettera_Present utilizza il tipo di dati BFILE, i suoi dati vengono memorizzati all’ester-
no del database. Al suo interno, il database memorizza solo un valore di locator che gli permette
di individuare il file esterno, riducendo in tal modo i requisiti di spazio e di gestione per il
database. Oracle non garantisce l’integrità dei dati per i file BFILE memorizzati all’esterno del
database. Inoltre, Oracle non conferma l’esistenza di questi file quando si inserisce un record
con un tipo di dati BFILE. La corrispondenza e l’integrità dei dati sono gestite solamente per i
LOB memorizzati internamente.
I dati per le colonne LOB potrebbero essere memorizzati fisicamente a parte rispetto alla
tabella PROPOSTA. All’interno della tabella PROPOSTA, Oracle memorizza valori di locator
che puntano alle posizioni dei dati. Per i tipi di dati BFILE, il puntatore del locator punta a un file
esterno; per i tipi di dati BLOB e CLOB, esso punta a una locazione separata per i dati, creata dal
database per conservare i dati LOB. La posizione dei dati LOB può essere in linea con il resto
della riga PROPOSTA oppure questi potrebbero essere memorizzati fuori linea. Per default, i
dati LOB vengono memorizzati in linea se la loro lunghezza è inferiore a circa 4000 byte.
La memorizzazione fuori linea dei dati consente al database di evitare l’analisi dei dati LOB
ogniqualvolta venga effettuata la lettura di più righe del database. I dati LOB vengono letti solo
quando è necessario: negli altri casi vengono letti solo i valori dei relativi puntatori di locator. Si
possono specificare parametri di memorizzazione (tablespace e dimensionamento) per l’area
utilizzata per contenere i dati LOB, come descritto nel prossimo paragrafo.
USO DI DATI LOB 585
Dal momento che sono presenti tre colonne LOB, il comando create table dev’essere modi-
ficato in modo da comprendere le specifiche di memorizzazione per i dati LOB fuori linea (se si
intende memorizzarli fuori linea). Due delle colonne LOB, Testo_Proposta e Budget, memoriz-
zano i dati all’interno del database. Nel listato seguente è riportata la versione aggiornata del
comando create table, che specifica la clausola di memorizzazione dei LOB:
Le ultime quattro linee del comando create table specificano a Oracle in che modo memo-
rizzare i dati LOB fuori linea. Le istruzioni sono le seguenti:
La clausola lob specifica a Oracle che il gruppo di comandi successivo si riferisce alle spe-
cifiche di memorizzazione fuori linea per le colonne LOB della tabella. Le due colonne LOB
586 CAPITOLO 35
(Testo_Proposta e Budget) sono elencate esplicitamente. Quando i valori delle due colonne sono
memorizzati fuori linea, vengono registrati in un segmento, come specificato dalla clausola lob:
NOTA Se la colonna LOB fosse una sola, si potrebbe specificare un nome per il
segmento LOB. Il nome del segmento verrebbe riportato subito dopo la clausola store as nel
comando specificato precedentemente.
(tablespace Proposta_Lobs
Dato che i segmenti sono adibiti alla memorizzazione di dati LOB, sono disponibili molti
altri parametri, specificati all’interno della clausola lob:
Il parametro di memorizzazione di LOB chunk indica a Oracle quanto spazio allocare du-
rante ogni manipolazione di valori LOB. La dimensione predefinita per chunk è di 1KB e può
raggiungere un massimo di 32KB.
Il parametro pctversion rappresenta la percentuale massima di spazio di memorizzazione
complessivo di LOB utilizzato per la creazione di nuove versioni del LOB. Per default, le versio-
ni precedenti dei dati LOB non vengono sovrascritte fino a che non viene utilizzato il 10 per
cento dello spazio di memorizzazione di LOB disponibile.
Gli ultimi due parametri relativi allo spazio di memorizzazione di LOB indicano a Oracle
come gestire i dati LOB durante le letture e le scritture:
nocache logging);
Il parametro nocache nella clausola di memorizzazione lob specifica che i valori LOB non
vengono conservati in memoria per consentire un accesso più rapido durante le query.
L’impostazione di memorizzazione predefinita di lob è nocache; il suo opposto è cache.
Il parametro logging specifica che tutte le operazioni effettuate sui dati LOB verranno regi-
strate nei file redo log del database. Al contrario di logging, nologging impedisce che le operazio-
ni vengano registrate nei file redo log, migliorando le prestazioni durante le operazioni di crea-
zione delle tabelle. Inoltre, è possibile specificare i parametri tablespace e storage per un indice
LOB. Per la sintassi completa degli indici LOB, si consulti la voce del comando create table nel
Capitolo 48.
Se si specifica cache e si omette la clausola nologging/logging, la registrazione viene imple-
mentata automaticamente perché non è possibile specificare cache nologging. Se cache non è
specificata e si omette la clausola nologging/logging, il valore relativo alla registrazione viene
ottenuto dalla tablespace in cui è memorizzato il valore LOB.
Ora che la tabella è stata creata, si può iniziare a inserirvi dei record. Nel prossimo paragrafo
viene descritto l’inserimento dei valori LOB nella tabella PROPOSTA e l’uso del package
DBMS_LOB per la manipolazione dei valori.
USO DI DATI LOB 587
Per puntare a una combinazione di directory e nome file, occorre utilizzare la procedura
BFILENAME. Prima di specificare un valore per la directory nella funzione BFILENAME, un
utente con il ruolo DBA o il privilegio di sistema CREATE ANY DIRECTORY dovrà creare la
directory. Per creare una directory si utilizza il comando create directory, come nell’esempio
seguente:
Quando si inseriscono voci BFILE, si fa riferimento al nome della directory logica, come
‘dir_proposta’, non al nome della directory fisica nel sistema operativo. Gli utenti con autorità di
DBA sono in grado di concedere agli utenti l’accesso READ ai nomi di directory. Per ulteriori
informazioni, fare riferimento alla voce del comando create directory nel Capitolo 48.
Ora è possibile inserire un secondo record PROPOSTA con un valore per Lettera_Present.
In questo listato, nella tabella PROPOSTA viene inserita una seconda proposta: ricostruire
una recinzione. Le funzioni EMPTY_CLOB() ed EMPTY_BLOB() vengono utilizzate per inserire
valori locator vuoti nella tabella. La funzione BFILENAME indica a Oracle dove si trova esatta-
mente la lettera di presentazione, ovvero nella directory ‘dir_proposta’ e con il nome P2.DOC.
In BFILENAME il primo parametro è sempre il nome della directory, mentre il secondo parame-
tro è il nome del file contenuto nella directory.
NOTA Non è necessario che il file P2.DOC esista per poter inserire correttamente
questo record.
Quando si seleziona il valore da una colonna LOB, Oracle usa il valore del locator per
individuare i dati associati ai dati LOB. Non è mai necessario conoscere o specificare i valori del
locator. Inoltre, come viene spiegato nei paragrafi successivi, i valori LOB consentono operazio-
ni impossibili con i tipi di dati LONG.
Questo comando insert ordina a Oracle di trovare il record PROPOSTA con valore
ID_Proposta pari a 1. Si prendano i valori delle colonne Testo_Proposta, Budget e Lettera_Present
e i valori letterali specificati (3, ‘SALTA GATES’ e così via) e si inserisca un nuovo record nella
tabella PROPOSTA. Si osservi che le colonne LOB inserite verranno impostate a valori di locator
vuoti. La possibilità di eseguire inserimenti basandosi su query rappresenta un vantaggio signi-
ficativo derivante dall’uso dei tipi di dati LOB. Questo tipo di inserimento non può essere utiliz-
zato se una colonna LONG fa parte della query.
NOTA Se si usa insert as select per inserire i valori LOB, è possibile che più
valori BFILE puntino allo stesso file esterno. Potrebbe essere necessario aggiornare i nuovi
valori in modo che puntino ai file esterni corretti. Oracle non gestisce l’integrità dei dati per i
file esterni.
update PROPOSTA
set Testo_Proposta = ‘Questo è il nuovo testo della proposta.'
where ID_Proposta = 3;
Si può anche aggiornare la colonna Lettera_Present in modo che punti alla lettera di presen-
tazione corretta. Per puntare al file corretto, si utilizza la funzione BFILENAME:
update PROPOSTA
set Lettera_Present = BFILENAME(‘dir_proposta', ‘P3.DOC')
where ID_Proposta = 3;
È anche possibile aggiornare i valori NULL delle colonne BFILE senza doverle impostare
prima a valori di locator vuoti. Se è stato inserito un record con un valore NULL per Budget (una
colonna BLOB), non è possibile aggiornare il valore della colonna Budget se non si è prima
provveduto a impostare il suo valore pari a quello restituito da EMPTY_BLOB(), mediante un
comando update. Una volta impostato tale valore al valore restituito da EMPTY_BLOB() e sta-
bilito un valore di locator vuoto, si potrà aggiornare il valore della colonna Budget.
TESTO_PROPOSTA
---------------------------------------------------------------------
Questo è il testo di una proposta per mantenere un giardino organico.
INITCAP(TESTO_PROPOSTA)
-----------------------------------------------------------
Questo È Il Nuovo Testo Della Proposta.
INSTR(TESTO_PROPOSTA,'NEW',1,1)
------------------------------
0
0
13
La funzione SUBSTR può essere utilizzata per restituire i primi dieci caratteri del testo:
select SUBSTR(Testo_Proposta,1,10) from PROPOSTA
where ID_Proposta = 3;
SUBSTR(TESTO_PROPOSTA,1,10)
------------------------------------------------------------------
Questo è i
Tuttavia alle colonne CLOB non è possibile applicare le funzioni NVL e DECODE:
select NVL(Testo_Proposta, “NULL”) from PROPOSTA;
*
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected CLOB got CHAR
NOTA Con i tipi di dati LOB è anche possibile utilizzare le funzioni per espressio-
ni regolari (Capitolo 8).
CONVERTCLOB, procedura Legge dati carattere da un’istanza CLOB o NCLOB di origine, converte i dati carattere nel carat-
tere specificato, scrive i dati convertiti in un’istanza BLOB di destinazione in formato binario e
restituisce i nuovi offset.
COPY, procedura Copia tutto il LOB di origine, o parte di esso, nel LOB di destinazione.
CREATETEMPORARY, procedura Crea un BLOB o CLOB temporaneo e il suo indice corrispondente nella tablespace temporanea
predefinita dell’utente.
FILEISOPEN, funzione Verifica se il file è stato aperto utilizzando i locator BFILE di input.
FREETEMPORARY, procedura Libera il BLOB o CLOB temporaneo nella tablespace temporanea predefinita dell’utente.
GETCHUNKSIZE, funzione Restituisce la quantità di spazio utilizzata nel chunk del LOB per memorizzare il valore del LOB.
GET_STORAGE_LIMIT, funzione Restituisce il limite di memorizzazione per i LOB nella configurazione del database.
INSTR, funzione Restituisce la posizione corrispondente della ennesima occorrenza del pattern nel LOB.
ISOPEN, funzione Verifica se il LOB è già stato aperto utilizzando il locator di input.
OPEN, procedura Apre un LOB (interno, esterno o temporaneo) nella modalità indicata.
SUBSTR, funzione Restituisce parte del valore del LOB a partire dall’offset specificato.
TRIM, procedura Taglia il valore del LOB alla lunghezza inferiore specificata.
Negli esempi seguenti, la colonna CLOB Testo_Proposta viene utilizzata per mostrare l’ef-
fetto delle procedure e delle funzioni principali.
READ
La procedura READ legge una parte di un valore LOB. Nell’esempio relativo alla tabella PRO-
POSTA, il testo di Testo_Proposta per la prima riga è
select Testo_Proposta
from PROPOSTA
where ID_Proposta = 1;
TESTO_PROPOSTA
---------------------------------------------------------------------- Questo è il testo di
una proposta per mantenere un giardino organico.
Questa descrizione è piuttosto breve e avrebbe potuto essere memorizzata in una colonna di
tipo VARCHAR2. Dato che questa descrizione è memorizzata in una colonna CLOB, la sua
lunghezza massima è comunque molto maggiore di quanto sarebbe stata se memorizzata in una
colonna VARCHAR2; infatti può espandersi fino a 8 TB. Per i prossimi esempi, si utilizzerà
questa breve stringa a scopi dimostrativi; le stesse funzioni e operazioni possono essere eseguite
su stringhe CLOB più lunghe.
La procedura READ prevede quattro parametri, che devono essere specificati nell’ordine
riportato di seguito:
1. Il locator del LOB (per un BLOB, CLOB o un BFILE).
2. Numero di byte o caratteri da leggere.
3. Offset (punto di inizio della lettura) dall’inizio del valore LOB.
4. I dati di output ricavati dalla procedura READ.
Se si raggiunge la fine del valore LOB prima che sia stato letto il numero di byte specificato,
la procedura READ restituisce un errore.
La procedura READ richiede come input il locator LOB, e per questo motivo viene eseguita
all’interno di blocchi PL/SQL. Si dovrà selezionare il valore del locator LOB, usarlo come input
per la procedura READ quindi visualizzare il testo letto tramite il package DBMS_OUTPUT.
Una nota sul package DBMS_OUTPUT
Come si è ricordato nel Capitolo 31, il package DBMS_OUTPUT può essere utilizzato per
visualizzare i valori di variabili all’interno di un blocco PL/SQL. La procedura PUT_LINE al-
l’interno di DBMS_ OUTPUT visualizza il risultato specificato su una linea. Prima di utilizzare
il package DBMS_OUTPUT, sarebbe opportuno eseguire il comando set serveroutput on. Nel
paragrafo successivo, si imparerà a creare il blocco PL/SQL che leggerà i dati da un LOB.
Esempio di impiego della procedura READ
Per utilizzare la procedura READ è necessario conoscere il valore del locator del LOB che si
desidera leggere. Il valore del locator dev’essere selezionato dalla tabella che contiene il LOB.
Poiché il valore del locator dev’essere fornito come input alla procedura READ, è necessario
utilizzare le variabili PL/SQL per contenerlo. La procedura READ, a sua volta, inserisce il pro-
prio output in una variabile PL/SQL. Il package DBMS_OUTPUT consente di visualizzare il
valore di output. La struttura del blocco PL/SQL impiegato in questo esempio è la seguente:
declare
variabile che contiene il valore del locator
variabile che contiene la quantità (numero di caratteri/byte da leggere)
USO DI DATI LOB 593
NOTA Per ulteriori informazioni sui blocchi PL/SQL e i loro componenti, si ri-
manda al Capitolo 29.
Per la tabella PROPOSTA, la selezione dei primi dieci caratteri della colonna Testo_Proposta
assume l’aspetto seguente:
declare
var_locator CLOB;
var_quantita INTEGER;
var_offset INTEGER;
var_output VARCHAR2(10);
begin
var_quantita := 10;
var_offset := 1;
select Testo_Proposta into var_locator
from PROPOSTA
where ID_Proposta = 1;
DBMS_LOB.READ(var_locator, var_quantita, var_offset, var_output);
DBMS_OUTPUT.PUT_LINE(‘Inizio del testo della proposta: ‘ || var_output);
end;
/
L’output visualizza i primi dieci caratteri del valore Testo_Proposta, a partire dal primo carattere
del valore LOB.
Il blocco PL/SQL dell’esempio precedente dichiara in primo luogo le variabili da utilizzare:
declare
var_locator CLOB;
var_quantita INTEGER;
var_offset INTEGER;
var_output VARCHAR2(10);
begin
var_quantita := 10;
var_offset := 1;
594 CAPITOLO 35
Dopodiché il valore del locator è stato selezionato dalla tabella e memorizzato in una varia-
bile di nome var_locator:
Come risultato dell’esecuzione della procedura READ, la variabile var_output viene popo-
lata con i dati letti. La procedura PUT_LINE visualizza questi dati:
Per la parte restante del capitolo verrà utilizzato questo formato per i blocchi PL/SQL. Fa-
coltativamente, i valori delle variabili potranno essere impostati mentre queste vengono dichia-
rate.
Per selezionare una parte diversa dell’oggetto CLOB Proposta_Testo, si modifichino le va-
riabili di quantità e di offset. Se si modifica il numero di caratteri letti, è necessario modificare
anche la dimensione della variabile di output. Nell’esempio seguente vengono letti 12 caratteri
da Testo_Proposta, partendo dal decimo carattere:
declare
var_locator CLOB;
var_quantita INTEGER;
var_offset INTEGER;
var_output VARCHAR2(12);
begin
var_quantita := 12;
var_offset := 10;
select Testo_Proposta into var_locator
from PROPOSTA
where ID_Proposta = 1;
DBMS_LOB.READ(var_locator, var_quantita, var_offset, var_output);
DBMS_OUTPUT.PUT_LINE(‘Parte del testo della proposta: ‘ || var_output);
end;
/
Se Testo_Proposta fosse stata creata come una colonna VARCHAR2, sarebbe stato possibile
selezionare questi dati con la funzione SUBSTR. Tuttavia, la lunghezza massima della colonna
sarebbe stata limitata a 4.000 caratteri. Si osservi inoltre che la colonna LOB è in grado di
contenere dati binari (tipi di dati BLOB) e che la procedura READ può essere utilizzata per
selezionare dati dagli oggetti BLOB nello stesso modo in cui si selezionano dati da oggetti
CLOB. Per gli oggetti BLOB, è necessario dichiarare il buffer di output per utilizzare il tipo di
dati RAW. In PL/SQL, i tipi di dati RAW e VARCHAR2 (utilizzati per le variabili di output delle
letture CLOB e BLOB) hanno una lunghezza massima pari a 32767 caratteri.
USO DI DATI LOB 595
SUBSTR
La funzione SUBSTR all’interno del package DBMS_LOB esegue la funzione SQL SUBSTR su
un valore LOB. Questa funzione prevede tre parametri di input, che devono essere specificati in
questo ordine:
1. Locator LOB.
2. Numero di byte o caratteri da leggere.
3. Offset (punto di inizio della lettura) dall’inizio del valore LOB.
Dato che SUBSTR è una funzione, non restituisce direttamente un valore per la variabile di
output come avviene con READ. Per la procedura READ era stata dichiarata una variabile di
output, quindi la si era popolata all’interno della chiamata alla procedura stessa. Il blocco PL/
SQL utilizzato per la procedura READ è riportato nel listato seguente, con le linee relative alla
variabile di output evidenziate in grassetto:
declare
var_locator CLOB;
var_quantita INTEGER;
var_offset INTEGER;
var_output VARCHAR2(12);
begin
var_quantita := 12;
var_offset := 10;
select Testo_Proposta into var_locator
from PROPOSTA
where ID_Proposta = 1;
DBMS_LOB.READ(var_locator, var_quantita, var_offset, var_output);
DBMS_OUTPUT.PUT_LINE(‘Parte del testo della proposta: ‘ || var_output);
end;
/
Dato che SUBSTR è una funzione, la variabile di output dev’essere riempita in modo diver-
so. Il formato è:
L’istruzione PL/SQL precedente ricorre alla funzione SUBSTR del package DBMS_LOB
per selezionare 12 caratteri dalla colonna LOB Testo_Proposta, a partire dal decimo. Il blocco
PL/SQL completo è il seguente:
declare
var_locator CLOB;
var_quantita INTEGER;
var_offset INTEGER;
var_output VARCHAR2(12);
begin
var_quantita := 12;
var_offset := 10;
select Testo_Proposta into var_locator
from PROPOSTA
where ID_Proposta = 1;
596 CAPITOLO 35
select SUBSTR(Testo_Proposta,10,12)
from PROPOSTA
where ID_Proposta = 1;
Sono solo due le differenze tra l’esempio di SUBSTR e quello della procedura READ: il
nome della chiamata alla funzione e la modalità di assegnamento di un valore alla variabile di
output. Come nell’esempio della procedura READ, per la visualizzazione dei risultati viene
utilizzata la procedura PUT_LINE del package DBMS_OUTPUT.
In generale, la funzione SUBSTR dovrebbe essere utilizzata quando si desidera selezionare
solo una parte specifica del valore LOB. La funzione READ può servire per selezionare solo una
parte di una stringa di testo (come negli esempi precedenti), tuttavia viene utilizzata più spesso
all’interno di un ciclo. Per esempio, si supponga che il valore LOB sia maggiore della massima
variabile RAW o VARCHAR2 consentita in PL/SQL (32.767 caratteri). In questo caso, si po-
trebbe utilizzare la procedura READ all’interno di un ciclo per leggere tutti i dati dal valore
LOB. Per ulteriori informazioni sulle varie opzioni di ciclo disponibili in PL/SQL, si rimanda al
Capitolo 29.
Per la funzione SUBSTR, le eccezioni possibili sono UNOPENED_FILE, NOEXIST_
DIRECTORY, NOPRIV_DIRECTORY, INVALID_DIRECTORY e INVALID_OPERATION.
INSTR
La funzione INSTR all’interno del package DBMS_LOB esegue la funzione SQL INSTR su un
valore LOB.
La funzione INSTR prevede quattro parametri di input che devono essere specificati in que-
sto ordine:
1. Locator LOB.
2. Sequenza da verificare (byte RAW per i BLOB, stringhe di caratteri per i CLOB).
3. Offset (punto di inizio della lettura) dall’inizio del valore LOB.
4. Occorrenza della sequenza all’interno del valore LOB.
La funzione INSTR all’interno di DBMS_LOB cerca nel LOB una sequenza specifica di
byte o caratteri. La variabile relativa all’occorrenza consente di specificare quale occorrenza
della sequenza debba essere restituita all’interno del valore cercato. L’output della funzione
INSTR è la posizione iniziale della sequenza all’interno della stringa esaminata. Per esempio, in
SQL,
significa che all’interno della stringa ‘ABCABC’ viene cercato il carattere ‘A’, partendo dalla
prima posizione della stringa e cercando la prima occorrenza. ‘A’ viene trovata alla prima posi-
USO DI DATI LOB 597
zione della stringa esaminata. Iniziando la ricerca dalla seconda posizione della stringa, il risul-
tato sarebbe stato il seguente:
Dato che questa funzione INSTR inizia dalla seconda posizione, la prima ‘A’ non fa parte del
valore analizzato. Al contrario, la prima ‘A’ trovata è quella in quarta posizione.
Se si modifica l’ultimo parametro nella funzione SQL INSTR per cercare la seconda occor-
renza della stringa ‘A’, partendo dalla seconda posizione, non viene trovato nulla:
Se la funzione SQL INSTR non riesce a trovare l’occorrenza corrispondente della sequenza,
viene restituito 0. La funzione INSTR del package DBMS_LOB opera nello stesso modo.
Dato che INSTR è una funzione, la sua variabile di output dovrà essere assegnata nello
stesso modo in cui è stata assegnata la variabile di output della funzione SUBSTR. Nel listato
seguente, viene analizzato il valore CLOB Testo_Proposta alla ricerca della stringa ‘pr’. Per
contenere l’output della funzione INSTR viene dichiarata la variabile var_posizione.
declare
var_locator CLOB;
var_sequenza VARCHAR2(2);
var_offset INTEGER;
var_occor INTEGER;
var_posizione INTEGER;
begin
var_sequenza := ‘pr';
var_offset := 1;
var_occor := 1;
select Testo_Proposta into var_locator
from PROPOSTA
where ID_Proposta = 1;
var_posizione := DBMS_LOB.INSTR(var_locator, var_sequenza,
var_offset, var_occor);
DBMS_OUTPUT.PUT_LINE(‘Trovata stringa alla posizione: ‘ || var_posizione);
end;
/
L’output è il seguente:
L’output mostra che la stringa cercata ‘pr’ è stata trovata all’interno di Testo_Proposta, a
partire dal ventitreesimo carattere del valore LOB. Dato che Oracle supporta le funzioni di strin-
ga SQL sulle colonne CLOB, questa funzione di chiamata equivale alla query seguente:
GETLENGTH
La funzione GETLENGTH del package DBMS_LOB restituisce la lunghezza del valore LOB.
Come funzionamento, DBMS_LOB.GETLENGTH è simile alla funzione SQL LENGTH, ma
viene utilizzata solo per i valori LOB.
La funzione GETLENGTH del package DBMS_LOB possiede solo un parametro di input:
il valore del locator per il LOB. Nel listato seguente, vengono dichiarate delle variabili per
contenere il valore del locator e il valore di output. La funzione GETLENGTH viene quindi
eseguita e il risultato visualizzato tramite la procedura PUT_LINE:
declare
var_locator CLOB;
var_lunghezza INTEGER;
begin
select Testo_Proposta into var_locator
from PROPOSTA
where ID_Proposta = 1;
var_lunghezza := DBMS_LOB.GETLENGTH(var_locator);
DBMS_OUTPUT.PUT_LINE(‘Lunghezza di LOB: ‘ || var_lunghezza);
end;
/
Lunghezza di LOB: 61
select LENGTH(Testo_Proposta)
from PROPOSTA
where ID_Proposta = 1;
COMPARE
La funzione COMPARE del package DBMS_LOB confronta due valori LOB. Se i due valori
LOB sono identici, la funzione COMPARE restituisce 0; altrimenti restituisce un valore intero
diverso da zero (in genere 1 o –1). Per eseguire la funzione COMPARE, il package DBMS_LOB
esegue essenzialmente due funzioni READ e confronta i risultati. Pertanto, per ciascuno dei
valori LOB da confrontare si dovrà fornire un valore del locator e uno di offset; il numero di
caratteri o byte da confrontare è lo stesso per entrambi i valori LOB. Si possono confrontare
soltanto valori LOB dello stesso tipo di dati.
La funzione COMPARE prevede cinque parametri di input, che devono essere specificati in
questo ordine:
1. Locator LOB per il primo LOB.
2. Locator LOB per il secondo LOB.
3. Variabile di quantità (ovvero, il numero di byte o caratteri da confrontare).
4. Offset (punto di inizio della lettura) dall’inizio del primo valore LOB.
5. Offset (punto di inizio della lettura) dall’inizio del secondo valore LOB.
Dato che i due LOB messi a confronto possono avere valori di offset differenti, è possibile
confrontare la prima parte di un valore LOB con la seconda parte di un valore LOB differente.
USO DI DATI LOB 599
L’esempio del listato seguente confronta i primi 25 caratteri dei valori Testo_Proposta tratti da
due voci: il record ID_Proposta 1 e il record ID_Proposta 3:
declare
prima_var_locator CLOB;
seconda_var_locator CLOB;
var_quantita INTEGER;
prima_var_offset INTEGER;
seconda_var_offset INTEGER;
var_output INTEGER;
begin
var_quantita := 25;
prima_var_offset := 1;
seconda_var_offset := 1;
select Testo_Proposta into prima_var_locator
from PROPOSTA
where ID_Proposta = 1;
select Testo_Proposta into seconda_var_locator
from PROPOSTA
where ID_Proposta = 3;
var_output := DBMS_LOB.COMPARE(prima_var_locator, seconda_var_locator,
var_quantita, prima_var_offset, seconda_var_offset);
DBMS_OUTPUT.PUT_LINE(‘Valore del confronto (0 se uguali): '||
var_output);
end;
/
Ecco l’output:
declare
prima_var_locator CLOB;
seconda_var_locator CLOB;
var_quantita INTEGER;
prima_var_offset INTEGER;
seconda_var_offset INTEGER;
var_output INTEGER;
begin
var_quantita := 5;
prima_var_offset := 1;
seconda_var_offset := 1;
select Testo_Proposta into prima_var_locator
from PROPOSTA
where ID_Proposta = 1;
select Testo_Proposta into seconda_var_locator
from PROPOSTA
where ID_Proposta = 3;
var_output := DBMS_LOB.COMPARE(prima_var_locator, seconda_var_locator,
600 CAPITOLO 35
WRITE
La procedura WRITE del package DBMS_LOB consente di scrivere dati in posizioni specifiche
del LOB. Per esempio, si possono scrivere dati binari in una sezione di un BLOB, sovrascrivendo
i dati preesistenti in tale posizione. Con la procedura WRITE è possibile scrivere dati carattere
nei campi CLOB. Questa procedura prevede quattro parametri di input, che devono essere spe-
cificati in questo ordine:
1. Locator LOB per il LOB.
2. Variabile di quantità (ovvero il numero di byte o caratteri da scrivere).
3. Offset (punto iniziale di scrittura) dall’inizio del valore LOB.
4. Variabile buffer assegnata alla stringa di caratteri o ai dati binari da aggiungere.
Dato che la procedura WRITE aggiorna il valore LOB, per prima cosa si dovrebbe bloccare
la riga tramite un comando select for update, come mostrato nei passaggi scritti in grassetto nel
listato seguente. In questo esempio viene selezionato e bloccato un record. Quindi, il testo ‘AG-
GIUNGI NUOVO TESTO’ viene scritto all’interno del valore LOB, sostituendo i dati a partire
dalla posizione 10 (come definito dalla variabile di offset).
declare
var_locator CLOB;
var_quantita INTEGER;
var_offset INTEGER;
var_buffer VARCHAR2(12);
begin
var_quantita := 12;
var_offset := 10;
var_buffer := ‘AGGIUNGI NUOVO TESTO';
select Testo_Proposta into var_locator
from PROPOSTA
where ID_Proposta = 3
for update;
DBMS_LOB.WRITE(var_locator, var_quantita, var_offset, var_buffer);
commit;
end;
/
Dato che la procedura WRITE modifica i dati, occorre aggiungere un comando commit
prima della clausola end del blocco PL/SQL.
USO DI DATI LOB 601
Per la procedura WRITE non viene fornito alcun output. Per visualizzare i dati modificati, è
necessario chiamare la procedura READ (all’interno dello stesso blocco PL/SQL, se lo si desi-
dera) oppure selezionare nuovamente il valore LOB dalla tabella:
select Testo_Proposta
from PROPOSTA
where ID_Proposta = 3;
TESTO_PROPOSTA
-----------------------------------------------------------
Questo è AGGIUNGI TESTOa proposta.
APPEND
La procedura APPEND del package DBMS_LOB aggiunge i dati di un LOB a un secondo LOB.
Dato che questa operazione corrisponde all’aggiornamento di un valore LOB, il record da ag-
giornare dovrebbe essere bloccato prima di eseguire la procedura APPEND.
La procedura APPEND accetta solo due parametri: il valore del locator per il LOB di desti-
nazione e il valore del locator per il LOB sorgente. Se ambedue i parametri sono NULL, la
procedura APPEND restituisce un errore.
Nell’esempio seguente vengono definite due variabili per il locator. La prima variabile del
locator, “var_locator_dest”, rappresenta il locator del LOB cui aggiungere i dati; la seconda,
“var_locatore_sorg”, rappresenta il locator dei dati di origine da aggiungere al LOB di destina-
zione. Quest’ultimo, dovendo essere aggiornato, viene bloccato tramite un comando select for
update. Nell’esempio seguente, il valore Testo_Proposta per il record ID_Proposta 1 viene ag-
giunto al valore Testo_Proposta per il record ID_Proposta 3:
declare
var_locator_dest CLOB;
var_locator_sorg CLOB;
begin
select Testo_Proposta into var_locator_dest
from PROPOSTA
where ID_Proposta = 3
for update;
select Testo_Proposta into var_locator_sorg
from PROPOSTA
where ID_Proposta = 1;
DBMS_LOB.APPEND(var_locator_dest, var_locator_sorg);
commit;
end;
/
select Testo_Proposta
from PROPOSTA
where ID_Proposta = 3;
TESTO_PROPOSTA
------------------------------------------------------------------------
Questo è AGGIUNGI TESTOa proposta.Questo è il testo di una proposta per
mantenere un giard
Cosa è successo al resto del testo? Per default, durante le query vengono visualizzati soltan-
to 80 caratteri dei valori LONG e LOB. Per visualizzare il testo restante, occorre utilizzare il
comando set long:
select Testo_Proposta
from PROPOSTA
where ID_Proposta = 3;
TESTO_PROPOSTA
------------------------------------------------------------------------
Questo è AGGIUNGI TESTOa proposta.Questo è il testo di una proposta per
mantenere un giardino organico
In questo esempio, vengono visualizzati i primi 1000 caratteri del valore LOB. Per sapere
quanto è lungo il LOB, occorre utilizzare la funzione GETLENGTH nel modo descritto in prece-
denza nel capitolo.
Oltre a consentire di aggiungere valori CLOB, la procedura APPEND consente anche di
aggiungere valori BLOB. Per aggiungere dati di tipo BLOB, è necessario conoscere il formato
dei dati stessi e l’effetto dell’aggiunta di nuovi dati sulla fine del valore BLOB. Per i valori
BLOB la procedura APPEND può essere utile nel caso di applicazioni in cui l’oggetto BLOB
contiene solo tipi di dati RAW (come quelli utilizzati da applicazioni di trasmissione digitale dei
dati) invece di dati binari formattati (come file di fogli di calcolo formattati da un programma).
Per i dati CLOB, si potrebbe riscrivere il tutto con un’istruzione update, impostando il
valore Testo_Proposta uguale alla concatenazione di più valori.
VALUE_ERROR è l’unica eccezione definita per la procedura APPEND.
ERASE
Per cancellare i caratteri o i byte in qualsiasi punto di un LOB, è possibile ricorrere alla procedu-
ra ERASE del package DBMS_LOB. Questa stessa procedura può essere utilizzata anche per
cancellare l’intero valore LOB, oppure si può specificare quale parte del LOB cancellare. Come
funzionamento, la procedura ERASE è simile alla procedura WRITE. Se si eliminano dei dati in
un valore BLOB, questi vengono sostituiti da caratteri di riempimento a zero byte. Se si elimina-
no dei dati in un valore CLOB, al loro posto vengono inseriti degli spazi.
Dato che la procedura comporta l’aggiornamento di un valore LOB, è necessario seguire le
procedure standard per gli aggiornamenti LOB: blocco della riga e commit al termine della
procedura.
Nel blocco PL/SQL seguente viene cancellata una parte di Testo_Proposta per il record con
ID_Proposta 3. I caratteri cancellati partiranno da un offset pari a 10 e continueranno per 17
caratteri. I parametri della procedura ERASE sono, nell’ordine:
1. Locator LOB per il LOB.
USO DI DATI LOB 603
declare
var_locator CLOB;
var_quantita INTEGER;
var_offset INTEGER;
begin
var_quantita := 17;
var_offset := 10;
select TestoProposta into var_locator
from PROPOSTA
where ID_Proposta = 3
for update;
DBMS_LOB.ERASE(var_locator, var_quantita, var_offset);
commit;
end;
/
4. Per visualizzare la modifica al record è sufficiente eseguire una query del valore
Testo_Proposta:
select Testo_Proposta
from PROPOSTA
where ID_Proposta = 3;
TESTO_PROPOSTA
----------------------------------------------------------------------
Questo è t esto.Questo è il testo di una proposta per
mantenere un giardino organico.
NOTA Lo spazio precedentemente occupato dai dati cancellati viene riempito con
spazi vuoti. La posizione dei dati restanti del LOB non cambia.
Per i dati CLOB è possibile riscrivere questa operazione con un’istruzione update, impo-
stando un nuovo valore per Testo_Proposta con la concatenazione dei risultati di SUBSTR e una
stringa vuota.
Per la funzione ERASE le eccezioni possibili sono VALUE_ERROR e INVALID_ARGVAL.
TRIM
La procedura TRIM del package DBMS_LOB consente di ridurre la dimensione di un valore
LOB eliminando caratteri o byte dalle estremità del valore (come la funzione SQL RTRIM). Per
eseguire la procedura TRIM è necessario specificare il valore del locator per il LOB e la nuova
lunghezza del LOB.
Nel listato seguente, vengono rimossi i primi dieci caratteri di Testo_Proposta per il record
ID_Proposta 3. Dato che la procedura TRIM modifica i dati, occorre aggiungere un comando
commit prima della clausola end del blocco PL/SQL.
declare
var_locator CLOB;
nuova_var_lung INTEGER;
begin
nuova_var_lung := 10;
604 CAPITOLO 35
Per la procedura TRIM non viene fornito alcun output. Per visualizzare i dati modificati
occorre selezionare nuovamente il valore LOB dalla tabella:
select Testo_Proposta
from PROPOSTA
where ID_Proposta = 3;
TESTO_PROPOSTA
------------------------------------------------------------------
Questo è i
L’output di esempio mostra i risultati della procedura TRIM successiva alla procedura ERASE
eseguita nel paragrafo precedente. Per i dati CLOB, il tutto può essere riscritto come una sempli-
ce istruzione update:
update PROPOSTA
set Testo_Proposta = SUBSTR(Testo_Proposta,1,10)
where ID_Proposta = 3;
COPY
La procedura COPY del package DBMS_LOB consente di copiare i dati da una posizione di un
LOB in un secondo LOB. A differenza di quanto avviene con la procedura APPEND, non è
necessario copiare l’intero testo di un valore LOB in un altro. Durante la procedura COPY, è
possibile specificare l’offset di lettura e quello di scrittura. I cinque parametri della procedura
COPY sono, nell’ordine:
1. Locator del LOB di destinazione.
2. Locator del LOB sorgente.
3. Variabile di quantità (ovvero, il numero di caratteri o byte da copiare).
4. Offset di inizio della scrittura all’interno del valore LOB di destinazione.
5. Offset di inizio della lettura all’interno del valore LOB di destinazione.
La procedura COPY combina le capacità delle procedure READ e WRITE. Come avviene
per l’operazione WRITE, la procedura COPY modifica il valore LOB. Per questo motivo, sareb-
be opportuno bloccare innanzi tutto il record; inoltre il blocco PL/SQL deve contenere un co-
mando commit. Nell’esempio seguente, i primi 61 caratteri del record ID_Proposta 1 vengono
copiati nel record ID_Proposta 3. Dato che il LOB di destinazione utilizza un offset pari a 1, i
dati copiati sovrascrivono i dati già presenti nel LOB di destinazione.
declare
var_locator_dest CLOB;
var_locator_sorg CLOB;
USO DI DATI LOB 605
var_quantita INTEGER;
var_offset_dest INTEGER;
var_offset_sorg INTEGER;
begin
var_quantita := 61;
var_offset_dest := 1;
var_offset_sorg := 1;
select Testo_Proposta into var_locator_dest
from PROPOSTA
where ID_Proposta = 3
for update;
select Testo_Proposta into var_locator_sorg
from PROPOSTA
where ID_Proposta = 1;
DBMS_LOB.COPY(var_locator_dest, var_locator_sorg,
var_quantita, var_offset_dest, var_offset_sorg);
commit;
end;
/
La procedura COPY non visualizza output. Per visualizzare i dati modificati occorre sele-
zionare nuovamente il valore LOB dalla tabella:
select Testo_Proposta
from PROPOSTA
where ID_Proposta = 3;
TESTO_PROPOSTA
---------------------------------------------------------------------
Questo è il testo di una proposta per mantenere un giardino organico.
zione completa di tutte le demo fornite, si rimanda alla Application Developer's Guide—Large
Objects.
L’approccio mostrato in questo esempio richiama quello della funzione COMPARE illustra-
to in precedenza. Dato che stiamo lavorando con dei BFILE, ci sono due sezioni aggiuntive: le
chiamate a DBMS_LOB.OPEN per aprire i file e le chiamate a DBMS_LOB.CLOSE per chiu-
dere i file una volta completata la funzione COMPARE.
La lettura dei dati dai BFILE segue i passaggi descritti in precedenza per la funzione READ,
con l’aggiunta delle chiamate per aprire e chiudere il file. Il processo READ viene illustrato
tramite il file dimostrativo fread.sql fornito da Oracle nella sottodirectory /rdbms/demo/logs/
plsql:
Se nel blocco PL/SQL si utilizza una sezione di gestione delle eccezioni, sarà necessario
includere chiamate alla procedura FILECLOSE all’interno delle eccezioni dichiarate. Per ulte-
riori informazioni sulla gestione delle eccezioni all’interno dei blocchi PL/SQL, si rimanda al
Capitolo 29.
Per spostare i dati da un file esterno in un tipo di dati BLOB, è possibile creare un tipo di dati
BFILE in una tabella e implementare la funzione BFILENAME per creare un locator LOB che
punta al file esterno. La funzione BFILENAME accetta due parametri: il nome della directory e il
nome del file. Ecco un esempio:
Concetti avanzati
di orientamento agli oggetti
N
ei capitoli precedenti tutte le caratteristiche di programma-
zione a oggetti di Oracle descritte condividono due caratteristiche: la qualità di oggetti incorpo-
rati e la qualità di oggetti colonna. Un oggetto incorporato è completamente contenuto all’inter-
no di un altro oggetto. Per esempio, una tabella nidificata è contenuta da un’altra tabella, quindi
è un oggetto incorporato. Anche se i dati di una tabella nidificata vengono memorizzati
separatamente dalla tabella principale, è possibile accedervi solo attraverso la tabella principale.
Un oggetto colonna viene rappresentato da una colonna di una tabella. Per esempio, un array
variabile è rappresentato da una colonna di una tabella, quindi è un oggetto colonna.
Per sfruttare a pieno le caratteristiche della programmazione a oggetti, un database deve
supportare anche oggetti riga, ossia oggetti rappresentati come righe invece che come colonne.
Gli oggetti riga non sono oggetti incorporati, bensì oggetti referenziali, accessibili tramite riferi-
menti da altri oggetti. In questo capitolo viene spiegato come creare e fare riferimento a oggetti
riga.
Le strutture a oggetti potrebbero non essere adatte a molte applicazioni: ci si potrebbe trova-
re limitati in base al toolset, alle interfacce o alle relazioni esistenti all’interno del database. In
questo capitolo si vedrà come Oracle ha implementato gli oggetti riga e come utilizzare le viste
oggetto per mettere in comunicazione le architetture a oggetti e quelle relazionali. Oltre agli
oggetti riga, viene trattata anche l’applicazione degli oggetti al linguaggio PL/SQL, ovvero la
creazione di oggetti PL/SQL.
memorizzazione per la tabella che memorizzerà i dati LOB. Oracle crea dei locator LOB che
puntano dalla tabella principale alle righe della tabella LOB se i dati LOB sono memorizzati
fuori linea. Quando si crea una tabella nidificata, è necessario specificare il nome della tabella in
cui i record della tabella nidificata vengono memorizzati. Oracle crea puntatori dalla tabella
principale ai record nelle tabelle nidificate. In questo modo, la tabella principale e la sua tabella
nidificata incorporata sono correlate.
Negli oggetti riga, gli oggetti vengono rappresentati come righe e non come colonne. I dati
non sono incorporati nella tabella principale, che invece contiene un riferimento a un’altra tabel-
la. Le tabelle nidificate, in quanto memorizzate separatamente dalla tabella principale, mettono
a disposizione uno strumento utile per comprendere gli oggetti riga. Che cosa accade se i dati
della tabella nidificata non sono incorporati all’interno della tabella principale e ciascuna delle
righe di questa tabella è un oggetto riga? La tabella principale definirà riferimenti ai dati correlati.
Le caratteristiche relazionali a oggetti di Oracle descritte nei primi capitoli si basavano su
oggetti colonna. In questo capitolo, l’obiettivo è puntato sulle capacità di OOP avanzate, basate
sugli oggetti riga. Gli oggetti riga vengono utilizzati per creare riferimenti tra righe di tabelle
differenti.
NOTA Per mantenere l’esempio semplice, il tipo di dati ANIMALE_TY viene creato
senza alcuna funzione membro.
Per creare una tabella oggetto del tipo di dati ANIMALE_TY si esegua il comando create
table riportato di seguito:
Table created.
Si osservi che il comando ha una sintassi inusuale, in quanto crea la tabella “di” (of) un tipo
di dati astratto. La tabella così ottenuta può apparire inizialmente come una normale tabella
relazionale:
describe ANIMALE
CONCETTI AVANZATI DI ORIENTAMENTO AGLI OGGETTI 611
Le colonne della tabella ANIMALE sono associate agli attributi del tipo di dati
ANIMALE_TY. Esistono però differenze significative nel modo in cui si può utilizzare la tabel-
la, in quanto si tratta di una tabella oggetto. Come si è notato in precedenza nel paragrafo,
ciascuna riga all’interno della tabella oggetto ha un valore OID, ed è possibile fare riferimento
alle righe come a oggetti.
NOTA Per un’analisi dettagliata dei constructor method, si rimanda al Capitolo 33.
Nel listato seguente vengono inserite tre righe nella tabella oggetto ANIMALE. In ogni
comando viene chiamato il constructor method ANIMALE_TY.
Se il tipo di dati astratto su cui è basata la tabella oggetto si basa a sua volta su un secondo
tipo di dati astratto, potrebbe essere necessario annidare le chiamate a più constructor method
all’interno del comando insert (per esempi di tipi di dati astratti nidificati si rimanda al Capitolo
33).
NOTA Se una tabella oggetto si basa su un tipo di dati che non contiene tipi di
dati nidificati, è possibile inserire dei record nella tabella oggetto utilizzando per il comando
insert la normale sintassi delle tabelle relazionali.
Quando si inserisce una riga in una tabella oggetto, Oracle assegna alla riga un valore OID.
La disponibilità di un OID consente di utilizzare la riga come un oggetto cui è possibile fare
riferimento. I valori OID non vengono riutilizzati.
Quando si esegue una selezione da una tabella che contiene un tipo di dati astratto, si fa
riferimento alle colonne del tipo di dati astratto come a parti delle colonne della tabella. In altre
parole, se si utilizza il tipo di dati ANIMALE_TY come base per una colonna di nome Animale,
si potranno selezionare i nomi degli animali selezionando Animale.Nome dalla tabella.
Una tabella oggetto si basa su un tipo di dati e non ha altre colonne. Per questo motivo, non
è necessario fare riferimento al tipo di dati quando si accede alle colonne. Per selezionare i nomi
dalla tabella ANIMALE, è necessario eseguire una query diretta sugli attributi del tipo di dati:
select Nome
from ANIMALE;
NOME
-------------------------
FRANCES
BENJI
LYLE
È possibile fare riferimento alle colonne all’interno della clausola where come se ANIMA-
LE fosse una tabella relazionale:
select Nome
from ANIMALE
where Famiglia = 'COCCODRILLO';
NOME
-------------------------
LYLE
Se il tipo di dati ANIMALE_TY utilizzasse un altro tipo di dati astratto per una delle sue
colonne, si dovrebbe fare riferimento alla colonna di questo tipo durante tutti gli inserimenti,
aggiornamenti e cancellazioni.
update ANIMALE
set DataNascita = '01-MAY-00'
where Nome = 'LYLE';
1 row updated.
Si osservi che durante l’aggiornamento si fa riferimento alle colonne della tabella oggetto
come se ANIMALE fosse una tabella relazionale. Durante una cancellazione, è possibile utiliz-
zare gli stessi mezzi per fare riferimento alle colonne della tabella oggetto nella clausola where:
1 row deleted.
D’altra parte, tenere un coccodrillo insieme ai muli e ai cani non era una buona idea.
La funzione REF
La funzione REF consente di fare riferimento a oggetti riga già esistenti. Per esempio, la tabella
ANIMALE (dopo la cancellazione di una riga, descritta nel paragrafo precedente) ha due oggetti
riga, a ciascuno dei quali è stato assegnato un valore OID. È possibile visualizzare gli OID
assegnati a ciascuna riga tramite la funzione REF, come mostrato di seguito:
select REF(A)
from ANIMALE A
where Nome = 'FRANCES';
REF(A)
---------------------------------------------------
0000280209F525172CC0F84F8ABABF0F0F46ECB7209A233BD5F
FD34A7E82D8C0C5CFB88FC0010002270000
NOTA Il valore REF(A) ottenuto sarà diverso da quello illustrato qui. In questo
listato il valore REF(A) è racchiuso in un wrapper di più linee.
Nel listato precedente, alla tabella ANIMALE è stato assegnato l’alias “A”, che è stato uti-
lizzato come input per la funzione REF. L’output mostra il valore OID dell’oggetto riga che ha
soddisfatto la condizione di limitazione della query.
NOTA La funzione REF accetta come input l’alias assegnato alla tabella oggetto.
Anche le altre funzioni, descritte più avanti in questo capitolo, accettano gli alias come input,
quindi si consiglia di familiarizzare con la sintassi descritta.
Dato che la funzione REF è in grado di fare riferimento solo a oggetti riga, non è possibile
servirsene per fare riferimento a oggetti colonna. Questi ultimi comprendono tipi di dati astratti,
LOB e collettori.
Come si può vedere, la funzione REF di per sé non fornisce alcuna informazione utile. È
necessario utilizzare un’altra funzione, DEREF, che converte l’output di REF in valori. Sarà
quindi possibile utilizzare REF e DEREF per fare riferimento a valori di oggetti riga, come
descritto nel prossimo paragrafo.
Per comprendere come DEREF e REF lavorino insieme, si consideri una tabella correlata
alla tabella ANIMALE. La tabella PASTORE terrà traccia delle persone che si prendono cura
degli animali. Questa tabella conterrà una colonna per il nome del pastore (NomePastore) e un
riferimento alla tabella oggetto ANIMALE (AnimaleCurato), come mostrato nel listato seguen-
te:
describe PASTORE
Per visualizzare tutti i dettagli, si utilizzi un valore maggiore per la profondità di descrizione:
desc PASTORE
Nome Null? Type
------------------------------- -------- ----
NOMEPASTORE VARCHAR2(25)
ANIMALECURATO REF OF ANIMALE_TY
FAMIGLA VARCHAR2(25)
NOME VARCHAR2(25)
DATANASCITA DATE
Si osservi attentamente il comando insert. Per prima cosa, il valore NomePastore viene
selezionato come valore letterale:
REF(A)
from ANIMALE A
where Nome = 'BENJI';
Cosa è accaduto? Per prima cosa, viene eseguita una query sulla tabella oggetto ANIMALE,
e la funzione REF restituisce il valore OID per l’oggetto riga selezionato. Questo valore viene
poi memorizzato nella tabella PASTORE come puntatore a questo oggetto riga nella tabella
oggetto ANIMALE.
La tabella PASTORE contiene informazioni sugli animali? No: PASTORE contiene il nome
del pastore e un riferimento a un oggetto riga nella tabella ANIMALE. Per visualizzare il valore
OID di riferimento, si esegua una query su PASTORE:
NOMEPASTORE
-------------------------
ANIMALECURATO
---------------------------------------------------
CATHERINE WEILZ
00002202088817DC34109A4A929C632C0FAF1F78EF9A233BD5F
FD34A7E82D8C0C5CFB88FC0
select DEREF(K.AnimaleCurato)
from PASTORE K
where NomePastore = 'CATHERINE WEILZ';
NOTA Il parametro per la funzione DEREF è il nome della colonna REF, non il
nome della tabella.
La funzione VALUE
La funzione DEREF è stata applicata a una tabella relazionale, in questo caso la tabella PASTO-
RE. Questa funzione restituisce il valore del riferimento che va dalla tabella relazionale alla
tabella oggetto.
Che ne è delle query dalla tabella oggetto? È possibile effettuare selezioni da ANIMALE?
Anche se ANIMALE è una tabella oggetto, è possibile effettuare delle selezioni da questa
tabella, come se si trattasse di una tabella relazionale. Ciò è coerente con gli esempi di inserimenti
e cancellazioni descritti in precedenza nel capitolo. Si tratta tuttavia di un’operazione diversa da
quella mostrata per mezzo di DEREF. La funzione DEREF visualizzava la struttura completa del
tipo di dati astratto utilizzato dalla tabella oggetto ANIMALE:
select DEREF(K.AnimaleCurato)
from PASTORE K
where NomePastore = 'CATHERINE WEILZ';
Per visualizzare le stesse strutture mediante una query sulla tabella oggetto ANIMALE,
occorre utilizzare la funzione VALUE. Come si può vedere nel listato seguente, la funzione VALUE
visualizza i dati nello stesso formato utilizzato da DEREF. Il parametro per la funzione VALUE è
l’alias della tabella.
select VALUE(A)
from ANIMALE A
where Nome = 'BENJI';
La funzione VALUE si rivela utile per l’esecuzione del debug di riferimenti e all’interno di
PL/SQL, come descritto nel paragrafo “PL/SQL a oggetti”, più avanti in questo capitolo. Dato
che questa funzione consente di eseguire query sui valori formattati direttamente dalla tabella
oggetto, questi valori possono essere selezionati senza utilizzare la query DEREF della colonna
AnimaleCurato di PASTORE.
Il record di PASTORE che fa riferimento a questo record ANIMALE avrà un REF non
valido. Se si inserisce una nuova riga ANIMALE per l’animale di nome ‘BENJI,’ questa non
verrà riconosciuta come parte dello stesso riferimento stabilito in precedenza. La spiegazione è
la seguente: la prima volta che è stata inserita una riga ‘BENJI’, Oracle ha generato un valore
OID per l’oggetto riga, ed è proprio a questo valore che faceva riferimento la colonna PASTO-
RE. Quando l’oggetto riga è stato cancellato, insieme a esso è scomparso anche il valore OID, e
Oracle non riutilizza i numeri di OID. Di conseguenza, quando viene inserito il nuovo record
BENJI, gli viene assegnato un nuovo valore OID, mentre il record di PASTORE punta ancora al
vecchio valore.
Si tratta di una differenza fondamentale tra i sistemi relazionali e i sistemi a oggetti. In un
sistema relazionale, il join di due tabelle dipende solo dai dati correnti. In un sistema orientato
agli oggetti, il join avviene tra oggetti: il fatto che due oggetti abbiano gli stessi dati non signifi-
ca che questi oggetti siano uguali.
Dato che la tabella CLIENTE è stata creata senza utilizzare i tipi di dati INDIRIZZO_TY e
PERSONA_TY, si dovrà ricorrere alle viste oggetto per accedere ai dati di CLIENTE tramite
accessi basati su oggetti (come i metodi). È possibile creare una vista oggetto che specifica i tipi
di dati astratti che si applicano alla tabella CLIENTE. Nel listato seguente viene creata la vista
oggetto CLIENTE_OV:
sfrutterà le relazioni chiave primaria/chiave esterna già esistenti per simulare valori OID da
utilizzare mediante REF tra le tabelle. Sarà così possibile accedere alle tabelle sia come a tabelle
relazionali sia come a oggetti. Quando le tabelle vengono trattate come oggetti, si potrà ricorrere
ai REF per eseguire automaticamente join delle tabelle (per alcuni esempi, si rimanda al paragra-
fo “Uso della funzione DEREF” più indietro nel capitolo).
La tabella CLIENTE ha una chiave primaria ID_Cliente. Si crei una tabella piccola che
contenga un riferimento di chiave esterna alla colonna ID_Cliente. Nel listato seguente, viene
creata la tabella CLIENTE_CHIAMATA. La chiave primaria della tabella CLIENTE_CHIAMA-
TA è la combinazione di ID_Cliente e Numero_Chiamata. La colonna ID_Cliente di CLIEN-
TE_CHIAMATA è una chiave esterna nei confronti di CLIENTE: non è possibile registrare una
chiamata per un cliente che non dispone già di un record in CLIENTE. All’interno della tabella
CLIENTE_CHIAMATA viene creato un singolo attributo non chiave, Data_Chiamata.
Ora si crei una vista oggetto basata sul tipo CLIENTE_TY, mentre si assegnano i valori OID
ai record di CLIENTE:
La prima parte di questo comando create view assegna alla vista il nome (CLIENTE_OV) e
indica a Oracle che la struttura della vista è basata sul tipo di dati CLIENTE_TY:
La parte successiva del comando create view indica al database come dovranno essere co-
struiti i valori OID per le righe di CLIENTE. La clausola with object identifier è seguita dalla
colonna da utilizzare per l’OID, in questo caso il valore ID_Cliente. Questo consente di indiriz-
zare le righe all’interno della tabella CLIENTE come se fossero oggetti riga cui è possibile fare
riferimento all’interno di una tabella oggetto.
La parte finale del comando create view fornisce la query su cui si baserà l’accesso ai dati
della vista. Le colonne della query devono coincidere con le colonne nel tipo di dati base della
vista:
Le righe di CLIENTE sono ora accessibili come oggetti riga tramite la vista CLIENTE_OV.
I valori OID creati per le righe di CLIENTE_OV sono detti pkOID poiché si basano sui valori
della chiave primaria della tabella CLIENTE. Alle tabelle relazionali è possibile accedere come
a oggetti riga, se per queste tabelle si creano viste oggetto opportune.
Fatta eccezione per l’operazione MAKE_REF, questo comando create view ha un aspetto del
tutto normale. L’operazione MAKE_REF è riportata in questa linea:
La funzione MAKE_REF accetta come argomenti il nome della vista oggetto cui si fa riferi-
mento e il nome della colonna (o delle colonne) che formano la chiave esterna nella tabella
locale. In questo caso, la colonna ID_Cliente della tabella CLIENTE_CHIAMATA fa riferimen-
to alla colonna utilizzata come base per la generazione di OID nella vista oggetto CLIENTE_OV.
Quindi a MAKE_REF vengono passati due parametri: CLIENTE_OV e ID_Cliente. Al risultato
dell’operazione MAKE_ REF viene assegnato l’alias di colonna Cliente_ID. Dato che il coman-
do descritto crea una vista, al risultato dell’operazione si deve assegnare un alias di colonna.
Qual è il compito di MAKE_REF ? MAKE_REF crea riferimenti (chiamati pkREF in quanto
basati su chiavi primarie) dalla vista CLIENTE_CHIAMATA_OV alla vista CLIENTE_OV. Ora
è possibile eseguire una query sulle due viste come se CLIENTE_OV fosse una tabella oggetto
e CLIENTE_CHIAMATA_OV una tabella che contiene un tipo di dati REF che fa riferimento a
CLIENTE_OV.
select DEREF(CCOV.ID_Cliente)
from CLIENTE_CHIAMATA_OV CCOV
where Data_Chiamata = TRUNC(SysDate);
stabilire dei valori pkOID nella tabella che rappresenta la chiave primaria nella relazione e uti-
lizzare MAKE_REF per generare riferimenti nella tabella che rappresenta la chiave esterna nella
relazione. Quindi si potranno utilizzare i dati come se questi fossero memorizzati in tabelle
oggetto.
set serveroutput on
declare
Cliente1 CLIENTE_TY;
begin
select VALUE(COV) into Cliente1
from CLIENTE_OV COV
where ID_Cliente = 123;
DBMS_OUTPUT.PUT_LINE(Cliente1.Nome);
DBMS_OUTPUT.PUT_LINE(Cliente1.Via);
end;
/
SIGMUND
47 HAFFNER RD
Nella prima parte del blocco PL/SQL viene dichiarata una variabile con il tipo di dati
CLIENTE_TY:
declare
Cliente1 CLIENTE_TY;
Il valore della variabile “Cliente1” viene selezionato dalla vista oggetto CLIENTE_OV
(creata nel paragrafo precedente del capitolo). La funzione VALUE viene utilizzata per recupera-
re i dati nella struttura del tipo di dati astratto. Dal momento che i dati verranno selezionati nel
formato del tipo di dati astratto, si dovrà utilizzare la vista oggetto CLIENTE_OV creata sulla
tabella CLIENTE.
begin
select VALUE(COV) into Cliente1
from CLIENTE_OV COV
where ID_Cliente = 123;
CONCETTI AVANZATI DI ORIENTAMENTO AGLI OGGETTI 623
DBMS_OUTPUT.PUT_LINE(Cliente1.Nome);
DBMS_OUTPUT.PUT_LINE(Cliente1.Via);
end;
declare
NuovoCliente CLIENTE_TY;
begin
NuovoCliente :=
CLIENTE_TY(345,'NuovoCliente','ViaVal', 'Citta','ST',00000);
insert into CLIENTE_OV
values (NuovoCliente);
end;
/
CLIENTE_ID NOME
----------- -------------------------
123 SIGMUND
234 EVELYN
345 NuovoCliente
Oltre a chiamare i constructor method, si possono chiamare anche i metodi creati sui tipi di
dati astratti. Se si prevede di confrontare i valori delle variabili che utilizzano i tipi di dati astrat-
ti, è necessario definire mappe o metodi di ordinamento per i tipi di dati. Questa capacità consen-
te di estendere ulteriormente PL/SQL a oggetti: si definiscono i tipi di dati e le funzioni al livello
del database, e questi potranno essere chiamati dall’interno di qualsiasi programma PL/SQL.
PL/SQL a oggetti rappresenta un miglioramento significativo rispetto a PL/SQL tradizionale.
624 CAPITOLO 36
JAVA IN ORACLE
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 37
Un’introduzione a Java
Q
uesto capitolo analizza il modo in cui Java si relaziona alle
applicazioni di database di Oracle. Oltre alle applicazioni Oracle, esistono numerosi impieghi di
Java, così come esistono molte caratteristiche di questo linguaggio che la maggior parte dei
programmatori Oracle ignorerà. Lo scopo di questo capitolo è fornire agli sviluppatori che han-
no già una certa familiarità con SQL e PL/SQL una visione delle strutture del linguaggio Java.
Questo libro non esamina in dettaglio Java (esistono molti volumi concepiti appositamente per
questo scopo); cerca invece di essere un breve riassunto dei componenti del linguaggio Java che
gli sviluppatori Oracle utilizzano con maggior frequenza.
Anche se in molti casi PL/SQL e Java sono in correlazione l’uno con l’altro, esistono diffe-
renze significative per quanto concerne la terminologia e l’impiego. Questo non dovrebbe rap-
presentare una sorpresa, poiché questi due linguaggi di programmazione sono stati sviluppati
separatamente. Inoltre le capacità a oggetti di PL/SQL non erano previste nella sua implemen-
tazione iniziale, mentre Java è nato come linguaggio a oggetti. Per usare Java in modo efficiente,
è necessario adottare un approccio differente da quello che potrebbe essere stato impiegato pre-
cedentemente con PL/SQL.
Nel Capitolo 29 sono stati introdotti il controllo del flusso e le strutture del linguaggio PL/
SQL. Questo capitolo rispecchia quell’approccio: verranno introdotte le strutture impiegate da
Java e i metodi base di controllo del flusso messi a disposizione. Quando applicabili, si introdur-
ranno anche le strutture PL/SQL corrispondenti. La lettura di questo capitolo presuppone una
conoscenza di PL/SQL (Capitolo 29), package, funzioni e procedure (Capitolo 31), tipi di dati
astratti e metodi (Capitolo 33).
declare
<sezione dichiarazioni>
begin
<comandi eseguibili>
628 CAPITOLO 37
exception
<gestione delle eccezioni>
end;
In Java, il termine blocco indica un sottoinsieme di codice molto più piccolo. In Java, un
blocco è una collezione di istruzioni racchiuse tra parentesi graffe, { e }. Per esempio, lo
pseudocodice che segue contiene due blocchi Java:
if (alcune condizioni) {
blocco di codice da elaborare se la condizione viene soddisfatta
}
else {
blocco di codice da elaborare se la condizione non viene soddisfatta
}
In PL/SQL, quest’intera sezione di codice sarebbe semplicemente una parte di un blocco più
ampio; in Java invece contiene due blocchi separati. In questo capitolo, tutti i riferimenti a “bloc-
chi” indicheranno blocchi Java, a meno che non venga specificato diversamente.
Una procedura PL/SQL è racchiusa da begin ed end, mentre un metodo Java è racchiuso tra
le parentesi graffe di apertura e chiusura. Queste parentesi graffe vengono anche impiegate per
isolare in un ambito i singoli blocchi di codice o come indicatori dell’apertura e chiusura dei
segmenti condizionali.
Un’altra differenza importante tra PL/SQL e Java si trova nella dichiarazione delle variabili.
In un blocco PL/SQL, le variabili vanno definite prima dell’inizio della sezione dei comandi
eseguibili. In un programma Java, le variabili possono essere definite nei punti in cui il program-
ma stesso le richiede. Un programma Java non possiede una sezione di dichiarazioni paragonabile
a quella utilizzata nei blocchi PL/SQL.
Nel corso di questo capitolo, si noteranno molte altre differenze tra PL/SQL e Java. L’im-
portante è ricordare che Java non sostituisce PL/SQL all’interno delle applicazioni e che è pos-
sibile continuare a utilizzare PL/SQL per le applicazioni Oracle. Per quanto riguarda le opera-
zioni di recupero dati, è consigliabile effettuare un test delle prestazioni di PL/SQL e Java prima
di decidere quale soluzione tecnica adottare.
37.2 Introduzione
Per utilizzare gli esempi di questo paragrafo occorre procurarsi una copia del Java Development
Kit (JDK), che può essere scaricato gratuitamente dal sito http://java.sun.com/. JDK dev’essere
installato sul server sul quale verranno eseguiti i programmi Java. Al momento della redazione di
questo libro la release di produzione più recente era JDK 1.4; moltissimi sviluppatori però utiliz-
zano ancora JDK 1.3.1. Come minimo, si dovrebbe utilizzare JDK 1.2.2.
NOTA JDK viene installato come parte dell’installazione di Oracle Database 10g.
Occorre accertarsi di installare sia il software del kernel del database sia quello fornito sul
Companion CD.
37.3 Dichiarazioni
In Java è possibile dichiarare le variabili in base alle esigenze. Una variabile ha un nome e un
tipo di dato, e serve per memorizzare il valore di un dato durante l’esecuzione del programma.
UN’INTRODUZIONE A JAVA 629
int Intero.
Una variabile ha anche un ambito, che le consente di avere un accesso pubblico o privato, analo-
gamente alle procedure, che nei package possono avere delle variabili private.
Ecco alcuni esempi di dichiarazioni di variabili Java:
Per convenzione, le variabili Java incominciano sempre con una lettera minuscola, come
mostrato in questo esempio, dove i tipi di dati sono CHAR e BOOLEAN, e ad ogni variabile
viene assegnato un valore iniziale. Si osservi che in Java il carattere di assegnamento è =, mentre
in PL/SQL può essere := o =>. Ogni dichiarazione termina con un segno di due punti.
Nella Tabella 37.1 sono elencati i tipi di dati primitivi disponibili in Java.
Oltre ai tipi di dati primitivi elencati nella Tabella 37.1, è possibile utilizzare i tipi di dati
riferimento basati sul contenuto delle variabili. Si potrebbe osservare che per le stringhe di caratteri
a lunghezza variabile non esistono tipi di dati primitivi: infatti Java mette a disposizione una
classe String proprio per questo scopo. Le classi verranno analizzate più avanti in questo capitolo.
OPERATORE DESCRIZIONE
* Moltiplicazione
/ Divisione
+ Addizione
– Sottrazione
% Modulo
630 CAPITOLO 37
Per semplificare la codifica, oltre a questi operatori è possibile utilizzare gli operatori unari
di Java. Per esempio, tramite l’operatore ++ è possibile incrementare il valore delle variabili,
come illustrato qui:
aLoopCounter = aLoopCounter++;
aLoopCounter++
Se l’operatore ++ viene inserito prima del nome della variabile, allora si tratta di un operato-
re di incremento prefisso invece che di un operatore di incremento suffisso:
aLoopCounter = aLoopCounter--;
Inoltre, è possibile combinare l’assegnamento dei valori con un’operazione. Per esempio,
invece di scrivere:
aNumberVariable = aNumberVariable * 2;
si può scrivere:
aNumberVariable *= 2;
Logica condizionale
Con le espressioni e le istruzioni è possibile valutare le variabili. A tal fine si potrebbero usare
una o più delle classi fondamentali che fanno parte di Java. Un elenco completo di questi metodi
va ben oltre lo scopo di questo libro; si faccia riferimento al sito di documentazione su Java di
Sun, oppure a uno dei numerosi manuali su Java che trattano l’argomento.
NOTA Il numero di classi fornite in genere cambia enormemente con ogni release
di Java.
if (Character.isUpperCase(aCharVariable)) {
alcuni comandi da eseguire
}
if (espressione) {
istruzione
}
Si noti l’assenza di una clausola then. Se l’espressione valutata è vera, il blocco seguente
verrà eseguito automaticamente. Si osservi inoltre la mancanza di una clausola end if. I blocchi
Java vengono terminati semplicemente dalla parentesi graffa di chiusura dell’istruzione.
È anche possibile che delle clausole else valutino condizioni differenti, come mostrato nel
listato seguente:
if (espressione) {
istruzione
}
else {
istruzione
}
Se si devono verificare più condizioni, è possibile utilizzare la clausola else if per valutarle
una alla volta, terminando con una clausola else. Il listato seguente illustra come usare le clauso-
le else if:
if (aCharVariable == 'V') {
istruzione
}
else if (aCharVariable == 'J') {
istruzione
}
else {
istruzione
}
632 CAPITOLO 37
NOTA PL/SQL supporta l’uso delle clausole elsif per scegliere tra alternative.
Una singola clausola if può avere più clausole elsif.
Oltre a supportare le clausole if per la logica condizionale, Java presenta una clausola switch.
Utilizzata insieme alla sua clausola break e alle etichette delle istruzioni, la clausola switch è in
grado di avvicinarsi alla funzionalità delle clausole goto (che Java non supporta). Per prima
cosa, si analizzi un semplice esempio di uso di switch. Con l’istruzione case, è possibile valutare
più valori della variabile aMonth. In base al valore di aMonth, viene visualizzato il nome del
mese e l’elaborazione lascia il blocco switch tramite break.
int aMonth=2;
switch (aMonth) {
case 1:
System.out.println("Gennaio);
break;
case 2:
System.out.println("Febbraio");
break;
case 3:
System.out.println("Marzo");
break;
default:
System.out.println("Fuori dall’intervallo");
break;
}
Questo tipo di codice è molto più complesso da scrivere rispetto a un semplice TO_CHAR,
tuttavia mostra l’impiego di switch. L’operatore switch accetta la variabile aMonth come proprio
input e poi ne valuta il valore. Se questo valore corrisponde a un valore di case, verrà chiamato
il metodo per visualizzare il nome del mese, mentre il controllo dell’elaborazione lascerà il
blocco switch tramite break. Se questo valore non corrisponde a una delle clausole case, verrà
eseguita l’opzione default.
Dove va a finire il controllo? Per default, passa alla sezione successiva del programma.
Tuttavia esiste la possibilità di creare etichette per le sezioni di codice e passare i nomi di queste
etichette alla clausola break. Il listato seguente mostra un esempio di un’etichetta e di una clau-
sola break:
somelabel:
if (aCharVariable == 'V') {
istruzione
}
else {
istruzione
}
int aMonth=2;
switch (aMonth) {
case 1:
System.out.println("Gennaio");
break somelabel;
case 2:
System.out.println("Febbraio");
break someotherlabel;
UN’INTRODUZIONE A JAVA 633
case 3:
System.out.println("Marzo");
break somethirdlabel;
default:
System.out.println("Fuori dall’intervallo");
break;
}
In questo esempio, viene valutata prima la clausola if e poi la clausola switch. Si noti che la
variabile aMonth viene dichiarata solo quando è necessaria. Per questo esempio, alla variabile
aMonth viene assegnato un valore pari a 2: in questo modo il programma visualizzerà la parola
“Febbraio” e passerà poi alla sezione di codice identificata dall’etichetta someotherlabel. Se il
valore di aMonth fosse stato 1, la clausola if posizionata all’inizio del listato di codice sarebbe
stata eseguita nuovamente.
Java supporta anche un operatore ternario, ossia un operatore che accetta tre operandi e la
cui funzione è simile a quella di DECODE. L’operatore ternario funziona come una combinazio-
ne if-else in linea e valuta un’espressione. Se l’espressione è vera, verrà restituito il secondo
operando, altrimenti verrà restituito il terzo. La sintassi è simile alla seguente:
(aCharVariable == 'V')
Se è vera, viene restituito “OK”; in caso contrario, viene restituito “Non valido”.
L’operatore ternario può essere utilizzato per simulare l’uso di una funzione GREATEST:
In questo esempio, viene valutata l’espressione (a > b), in cui a e b sono i nomi delle varia-
bili. Se quest’espressione è vera, verrà restituito il valore di a; in caso contrario verrà restituito il
valore di b.
NOTA Java ha un metodo “greatest” per i valori numerici, ossia il metodo Max
contenuto nella classe java.lang.Math. L’esempio ternario riportato nel listato precedente può
essere riscritto double greatest = Math.max(a, b);.
Con le operazioni AND e OR è possibile combinare più controlli logici. In Java, un’opera-
zione AND è rappresentata dall’operatore &&:
Per motivi legati alle prestazioni, le operazioni && e || vengono eseguite solo se necessarie;
la seconda espressione non viene valutata se la prima stabilisce già il risultato. Per quanto riguar-
da l’operatore AND, se il primo valore è falso, la valutazione terminerà in quel punto e il valore
booleano falso verrà restituito. Per quanto concerne l’operatore OR, se la prima espressione è
falsa, la seconda verrà comunque valutata perché è sufficiente che una sola delle condizioni di
verifica sia vera per consentire la restituzione del valore booleano vero. Se il primo valore del-
l’operatore OR fosse vero, non sarebbe necessario valutare le espressioni successive e il valore
vero verrebbe restituito.
Gli operatori & e | prendono il nome di AND e OR bit per bit: non si tratta di operatori a corto
circuito come && e ||. Verranno valutate sempre tutte le espressioni. Questa funzionalità può
essere particolarmente utile quando si verificano i valori di restituzione delle chiamate ai metodi
ed è necessario assicurasi che i metodi siano stati eseguiti.
Cicli
Java supporta tre tipi principali di cicli: i cicli WHILE, DO-WHILE e FOR. In questo paragrafo,
verranno presentati esempi per ogni tipo di ciclo. Dato che Java non è stato concepito come
estensione di SQL, esso non supporta i cicli FOR a cursore, come avviene in PL/SQL.
while (espressione) {
istruzione
istruzione
}
Il ciclo WHILE esegue ripetutamente il blocco di istruzioni (la sezione racchiusa tra le
parentesi graffe { and }) fino a quando espressione non è più vera:
int aNumberVariable = 3;
while (aNumberVariable < 7) {
qualche_istruzione di_elaborazione
aNumberVariable++;
}
NOTA Per esempi sull’elaborazione del ciclo WHILE, fare riferimento al para-
grafo “Classi” più avanti in questo capitolo.
Questo esempio potrebbe anche essere scritto sotto forma di ciclo DO-WHILE:
int aNumberVariable = 3;
do {
qualche_istruzione di_elaborazione
UN’INTRODUZIONE A JAVA 635
aNumberVariable++;
} while (aNumberVariable < 7);
In un ciclo DO-WHILE, il valore dell’espressione non viene valutato fino a quando il blocco
non è stato elaborato almeno una volta.
I cicli FOR
Un ciclo FOR può essere utilizzato per eseguire ripetutamente un blocco di codice. In un ciclo
FOR, si specificano un valore iniziale, un valore finale e un incremento per il contatore del ciclo.
Il contatore del ciclo verrà incrementato del valore specificato ogni volta che si esegue il ciclo
fino a quando non si raggiunge il valore finale. Ecco la sintassi di un ciclo FOR:
L’esempio di WHILE riportato nel paragrafo precedente può essere riscritto con una clauso-
la for, come mostrato nel listato seguente:
La versione della clausola for impiegata per questo esempio è molto più breve della versione
while. In questo esempio, la variabile aNumberVariable viene dichiarata e inizializzata all’inter-
no del ciclo FOR. Il blocco verrà eseguito fino a quando il valore della variabile non raggiunge
7. Per ogni passaggio nel ciclo, il valore della variabile viene aumentato di 1 attraverso l’opera-
tore unario ++.
All’interno di un ciclo, è possibile ricorrere alla clausola continue per passare a un’altra
istruzione contenuta nel ciclo. Se si utilizza la clausola continue da sola, il flusso del processo
salterà alla fine del corpo del ciclo e valuterà il test finale del ciclo. Se invece si utilizza continue
insieme a un’etichetta (come mostrato in precedenza nel paragrafo relativo alla clausola switch)
l’elaborazione riprenderà dall’iterazione successiva del ciclo con etichetta.
Cursori e cicli
In PL/SQL i cicli FOR a cursore possono servire per iterare attraverso i risultati di una query. I
cicli WHILE e FOR di Java possono essere utilizzati per simulare la funzionalità di un ciclo
FOR a cursore PL/SQL. Gli esempi forniti con Oracle mostrano come raggiungere questo risul-
tato. Oracle fornisce dei file di esempio sul disco aggiuntivo fornito insieme al CD di installazio-
ne del software Oracle. Questo disco aggiuntivo utilizza Oracle Universal Installer per caricare i
driver software e i file dimostrativi, compresi quelli a supporto dello sviluppo di JDBC. In segui-
to all’installazione del disco aggiuntivo, gli esempi JDBC saranno in un file di nome demo.zip
situato nella sottodirectory /jdbc/demo della home directory del software Oracle; una volta
scompattati, i file cui si fa riferimento in questo capitolo si troveranno nella sottodirectory /jdbc/
demo/samples/generic. Il dimostrativo SelectEmployee.java impartisce i comandi seguenti:
Questo esempio presuppone che una connessione al database sia già stata stabilita. La prima
linea dell’esempio crea una variabile di nome stmt, che si basa su una variabile di connessione
chiamata conn (che non è stata riportata in questo listato parziale). La seconda linea dell’esem-
pio crea una variabile di nome rset, basata sul gruppo di risultati che verrà restituito dalla query
su stmt. Dopo un commento (che ha come prefisso //), una clausola while recupera ogni linea nel
gruppo dei risultati. Se l’operazione FETCH recupera una linea dal gruppo dei risultati, verrà
visualizzato ENAME da quella linea EMP; altrimenti il ciclo terminerà.
Dal punto di vista della programmazione, è necessario essere precisi nei dati restituiti (come
nell’esempio precedente), specificando i nomi delle colonne da restituire.
I dimostrativi di JDBC (Java Database Connectivity, fare riferimento al Capitolo 38) messi
a disposizione da Oracle mostrano alcuni esempi di query che richiedono chiamate di procedure,
LOB (Large Object) e il linguaggio DML (Data Manipulation Language). Nella maggior parte
dei casi, il codice Java si comporterà in modo simile agli esempi precedenti: si scriva il codice
per il controllo del flusso del processo in Java e gli si passi un’istruzione da eseguire. In base al
risultato di quest’istruzione, grazie alle clausole while, for, if, break, continue e switch, come
mostrato in precedenza, è possibile decidere l’esecuzione di azioni differenti.
try {
istruzioni
}
catch ( ) {
istruzioni
}
catch ( ) {
istruzioni
}
finally {
istruzioni
}
try {
Statement stmt = conn.createStatement ();
catch (SQLException e) {
}
Qui viene creata una variabile di nome stmt per eseguire un comando drop table. Se l’esecu-
zione fallisce, per esempio nel caso in cui la tabella non esista, come verrà elaborato questo
errore? La clausola catch comunica a Java di gestirlo tramite un oggetto di eccezione chiamato
SQLException, un componente standard dell’implementazione SQL di Java. Come mostrato
nell’esempio, la clausola catch accetta due parametri (un oggetto di eccezione e il nome di una
variabile) ed è facoltativamente seguita da un blocco di istruzioni da eseguire.
Il blocco try può contenere più istruzioni, oppure si possono creare blocchi try separati per
ogni istruzione. Generalmente è più facile controllare la gestione delle eccezioni se si consolida-
no i blocchi catch, pertanto il consolidamento dei blocchi try aiuterà a gestire il codice mentre
cambia e cresce in dimensioni. La clausola when others in PL/SQL è sostanzialmente equivalen-
te a catch (Throwable th) in Java.
Il blocco finally ripulisce lo stato della sezione di codice corrente prima di passare il control-
lo a qualsiasi parte successiva del programma. In fase di esecuzione, il contenuto del blocco
finally viene eseguito sempre, a prescindere dal risultato del blocco try. Per esempio, si potrebbe
usare il blocco finally per chiudere una connessione al database.
Parole riservate
Le parole riservate contenute in Java sono elencate nella Tabella 37.2. Non è possibile utilizzare
queste parole come nomi di classi, metodi o variabili.
37.5 Classi
Nei paragrafi precedenti di questo capitolo sono state introdotte le strutture sintattiche di base
per Java. In questo paragrafo si imparerà a utilizzare questa sintassi per creare e usare gli oggetti.
Nel listato seguente viene proposto un semplice programma utilizzato per visualizzare la parola
“Oracle”:
Questo esempio crea una classe chiamata HelloOracle, all’interno della quale viene creato
un metodo pubblico di nome main. Il metodo main visualizza la parola “Oracle”. Ciò è molto più
complesso di:
tuttavia la versione Java possiede delle soluzioni che invece mancano nella versione SQL.
HelloOracle è una classe e, in quanto tale, i suoi metodi possono essere chiamati dall’interno di
altre classi. HelloOracle potrebbe poi avere più metodi, anche se in questo esempio possiede
main.
La dichiarazione del metodo main contiene un certo numero di parole chiave (public static
void main) da imparare:
public La definizione della classe come public consente a tutte le altre classi di chiamare questo metodo.
static Dichiara che si tratta di un metodo di classe; static serve per dichiarare i metodi di classe. Un’opzione
aggiuntiva è la parola chiave final per quei metodi e variabili i cui valori sono immutabili (analoga all’op-
zione constant di PL/SQL).
void Specifica il tipo di dato del valore di restituzione dalla procedura. Dato che questa procedura non restitu-
isce valori, il suo tipo è void.
In questo esempio, si attribuisce il nome main al metodo perché questo semplificherà l’ese-
cuzione del metodo della classe. Una volta creata la classe, la si potrà compilare e caricare.
NOTA Per compilare ed eseguire una classe Java, è necessario possedere sul pro-
prio server il JDK. Gli esempi seguenti partono dal presupposto che i file binari che fanno parte
di quel kit si trovino in una directory che verrà cercata automaticamente tramite la variabile
ambientale PATH, e che la directory contenente i file .class sia inclusa nella variabile ambienta-
le CLASSPATH. I programmi cui si fa riferimento in questa sede, (javac e java) si trovano nella
sottodirectory /bin della directory del software JDK.
Per prima cosa, si salvi il programma sotto forma di file di solo testo, di nome
HelloOracle.java. Quindi, lo si compili:
javac HelloOracle.java
Sul server, verrà creato un nuovo file, chiamato HelloOracle.class. Quindi, si potrà eseguire
la classe:
UN’INTRODUZIONE A JAVA 639
java HelloOracle
Oracle
Come mostrato nell’esempio di HelloOracle, per prima cosa alla classe viene assegnato un
nome, insieme ad altri attributi facoltativi che riguardano la sua ereditarietà di attributi di altre
classi. Nel corpo della classe vengono definiti tutti i metodi e le variabili della classe stessa.
Come avviene per i tipi di dati astratti in Oracle, anche alle classi Java sono associati dei metodi
che manipolano i dati a esse correlati.
Si analizzi un esempio più complesso. Il listato seguente è un programma Java che calcola
l’area di un cerchio, avendo come input il valore del raggio (per la versione PL/SQL, si faccia
riferimento al Capitolo 29):
// AreaOfCircle.java
//
public class AreaOfCircle {
public static void main(String[] args) {
try {
int input = Integer.parseInt(args[0]);
double result=area(input);
System.out.println(result);
}
catch (ArrayIndexOutOfBoundsException oob) {
System.out.println("Non è stato fornito il raggio del cerchio.");
System.out.println("Utilizzo: java AreaOfCircle 10");
}
catch (NumberFormatException nfe) {
System.out.println("Inserire un numero valido per il raggio.");
System.out.println("Utilizzo: java AreaOfCircle 10");
}
} /// main
NOTA Si controlli di aver inserito una parentesi graffa di chiusura, }, per ogni
blocco. Negli esempi proposti in questo capitolo, le parentesi di chiusura si trovano sempre su
linee a parte per semplificare il debug e l’elaborazione degli eventuali errori relativi al controllo
del flusso.
Innanzi tutto si osservi che la classe e il nome del file devono corrispondere. In questo caso,
la classe prende il nome di AreaOfCircle, pertanto questo testo verrà memorizzato in un file di
nome AreaOfCircle.java. La classe ha due metodi, chiamati main e area. Quando si esegue la
classe, il metodo main viene eseguito automaticamente. Il metodo main accetta la stringa fornita
come input e la analizza come un intero nella variabile input:
int input=Integer.parseInt(args[0]);
640 CAPITOLO 37
Sono almeno due le eccezioni possibili che potrebbero essere lanciate durante l’esecuzione
di questo codice. La prima eccezione gestita, ArrayIndexOutOfBoundsException, si verifica nel
momento in cui si cerca di far riferimento a una posizione in un array che non esiste. Dato che il
codice fa esplicitamente riferimento alla prima posizione dell’array, chiamata args (args[0]), se
non si passano dati al programma, verrà lanciata un’eccezione. L’altro possibile errore, Number
For matException , si verificherebbe se si passasse un valore non numerico. Per esempio, se si
eseguisse il programma inserendo “java AreaOfCircle XYZ” al posto di “java AreaOfCircle
123”, verrebbe lanciata l’eccezione NumberFormatException, in quanto XYZ non è un numero
valido. Entrambe le eccezioni sono gestite dalle due istruzioni catch che forniscono all’utente
informazioni utili relative alla causa dell’errore:
Quindi una variabile di nome result viene dichiarata e impostata al valore restituito dalla
chiamata ad area(input),:
double result=area(input);
Per elaborare questa direttiva, viene eseguito il metodo area, utilizzando il valore della va-
riabile input come input. Ecco il metodo area:
Nella sua definizione, il metodo area specifica che accetterà una variabile, un tipo intero di
nome rad. Questo valore della variabile (passato dalla variabile input nel metodo main) verrà poi
elaborato e una variabile di nome areacircle verrà calcolata e restituita a main. In main, verrà
visualizzato questo valore:
double result=area(input);
System.out.println(result);
javac AreaOfCircle.java
java AreaOfCircle 10
Ecco l’output:
314.15927
Si provi ad ampliare questo esempio in modo che includa anche l’elaborazione di un ciclo
WHILE. In questo esempio, il metodo area verrà chiamato ripetutamente fino a quando il valore
di input risultante non supererà un determinato valore:
UN’INTRODUZIONE A JAVA 641
// AreaOfCircleWhile.java
//
public class AreaOfCircleWhile {
public static void main(String[] args) {
try {
int input=Integer.parseInt(args[0]);
while (input < 7) {
double result=area(input);
System.out.println(result);
input++;
}
}
catch (ArrayIndexOutOfBoundsException oob) {
System.out.println("Non è stato fornito il raggio del cerchio.");
System.out.println("Utilizzo: java AreaOfCircle 10");
}
catch (NumberFormatException nfe) {
System.out.println("Inserire un numero valido per il raggio.");
System.out.println("Utilizzo: java AreaOfCircle 10");
}
} /// main
public static double area (int rad) {
double pi=3.1415927;
double areacircle=pi*rad*rad;
return areacircle;
} /// area
} /// AreaOfCircleWhile
In questo listato, il metodo area e i blocchi per la gestione delle eccezioni sono rimasti
immutati rispetto all’esempio precedente. La modifica riguarda il metodo main:
int input=Integer.parseInt(args[0]);
while (input < 7) {
double result=area(input);
System.out.println(result);
input++;
}
Finché il valore di input è minore di 7, verrà elaborato. Dopo aver calcolato e visualizzato
l’area per quel determinato valore del raggio, il valore di input viene incrementato:
input++;
Poi il ciclo valutato nuovamente. Nel listato seguente viene mostrato dell’output di esem-
pio:
javac AreaOfCircleWhile.java
java AreaOfCircleWhile 4
50.2654832
78.5398175
113.0973372
L’output mostra i calcoli dell’area per valori del raggio di input pari a 4, 5 e 6.
Questo esempio non è completo come un programma finito: per esempio, potrebbe essere
necessaria una maggiore gestione delle eccezioni per gestire i valori non interi; tuttavia è la
642 CAPITOLO 37
struttura l’elemento più importante che si deve ricavare da questo esempio. Oltre ai metodi mo-
strati in questo esempio, si potrebbe generare un costruttore per la classe AreaOfCircleWhile.
Tutte le classi Java possiedono dei costruttori (Capitolo 31) per inizializzare nuovi oggetti che si
basano sulla classe. Il nome del costruttore è lo stesso di quello della classe. Se si crea una classe
priva di costruttori, Java creerà un costruttore predefinito al momento dell’esecuzione. Come per
i metodi, il corpo del costruttore è in grado di contenere dichiarazioni di variabili locali, cicli e
blocchi di istruzioni. Il costruttore inizializza queste variabili per la classe.
Nei prossimi capitoli si imparerà a implementare Java in Oracle sia nelle stored procedure
sia tramite JDBC. Questi capitoli richiedono la conoscenza base di Java, fornita in questo capi-
tolo. Per ulteriori informazioni sul linguaggio Java, fare riferimento al sito Web di Sun
Microsystems e ai numerosi libri dedicati a Java.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 38
Programmazione JDBC
38.1 Introduzione
38.2 Uso delle classi JDBC
J
ava Database Connectivity (JDBC) si basa su Java e sui prin-
cipi fondamentali di programmazione descritti in precedenza in questo libro. Le discussioni e gli
esempi di questo capitolo suppongono una certa familiarità con la sintassi e le strutture Java
descritte nel Capitolo 37. Questo capitolo non analizza tutti gli aspetti di JDBC, concentrandosi
principalmente sulla configurazione e l’utilizzo di base.
JDBC può servire per eseguire istruzioni SQL dinamiche in programmi Java. Oracle forni-
sce dei file di esempio sul disco aggiuntivo fornito insieme al CD di installazione del software
Oracle. Questo disco aggiuntivo utilizza Oracle Universal Installer per caricare i driver software
e i file dimostrativi, compresi quelli a supporto dello sviluppo di JDBC. In seguito all’installa-
zione del disco aggiuntivo, gli esempi JDBC saranno in un file di nome demo.zip situato nella
sottodirectory /jdbc/demo della home directory del software Oracle; una volta scompattati, i file
cui si fa riferimento in questo capitolo si troveranno nella directory /jdbc/demo/samples/generic.
Il listato che segue è tratto dal file dimostrativo SelectExample.java. Il file SelectExample.java
esegue i comandi seguenti dopo aver stabilito una connessione al database:
// Create a Statement
Statement stmt = conn.createStatement ();
Quando si esegue un’istruzione SQL tramite JDBC, in questo caso select First_Name,
Last_Name from EMPLOYEES, l’istruzione SQL non viene sottoposta a controllo per verificare
eventuali errori fino a quando non viene eseguita. Il programma JDBC, che contiene il comando
SQL, verrà compilato anche se l’istruzione SQL non è valida.
38.1 Introduzione
Per utilizzare gli esempi di questo paragrafo occorre procurarsi una copia del Java Development
Kit (JDK), che viene installata durante il processo di installazione dell’Oracle Database
Companion CD.
644 CAPITOLO 38
A questo punto occorre creare una variabile di ambiente di nome CLASSPATH, se non ne
esiste già una (per la configurazione iniziale di Java non ne esisterà nessuna). Questa variabile
deve avere due voci, separate da un punto e virgola. La prima voce dev’essere un punto, che
denota la directory corrente. La seconda dev’essere la directory del file classes12.zip:
.;E:\oracle\ora10\jdbc\lib\classes12.zip
Se CLASSPATH non è impostata in modo corretto, quando si eseguirà una classe compilata
si otterrà un errore NoClassDefFoundError.
La variabile di ambiente PATH dovrebbe essere già impostata; si aggiunga quindi la voce
seguente al suo valore:
;E:\oracle\ora10\jdbc\lib\classes12.zip
javac JdbcCheckup.java
java JdbcCheckup
/*
* This sample can be used to check the JDBC installation.
* Just run it and provide the connect information. It will select
* "Hello World" from the database.
*
* note: jdk1.2 or later version is recommended.
*/
import oracle.jdbc.pool.OracleDataSource;
class JdbcCheckup
{
public static void main (String args [])
throws SQLException, IOException
{
// Prompt the user for connect information
System.out.println ("Please enter information to test connection to the
database");
String user;
String password;
String database;
if (slash_index != -1)
{
password = user.substring (slash_index + 1);
user = user.substring (0, slash_index);
}
else
password = readEntry ("password: ");
database = readEntry ("database (a TNSNAME entry, name-value pairs): ");
System.out.println ("Connecting...");
Connection conn = ods.getConnection();
System.out.println ("connected.");
// Create a statement
Statement stmt = conn.createStatement ();
buffer.append ((char)c);
c = System.in.read ();
}
return buffer.toString ().trim ();
}
catch (IOException e)
{
return "";
}
}
}
Partendo dall’inizio, per prima cosa questo script importa le classi java.sql fornite da Sun
Microsystems:
import java.sql.*;
import oracle.jdbc.pool.OracleDataSource;
Quando vengono richieste delle informazioni, la variabile user viene popolata tramite una
chiamata alla funzione readEntry:
La funzione readEntry verrà definita più avanti nella classe, nella sezione che inizia con:
Una volta inseriti i dati di connessione, verrà creato un oggetto di connessione per mantene-
re lo stato della sessione del database basato sulla definizione di OracleDataSource. La chiamata
a getConnection nel listato seguente avvia la connessione:
conn.setAutoCommit(false);
La classe crea quindi un’istruzione, esegue una query prestabilita e infine visualizza l’output:
648 CAPITOLO 38
// Create a statement
Statement stmt = conn.createStatement ();
import oracle.jdbc.pool.OracleDataSource;
class JdbcCircle {
// Connessione al database
// Si può inserire un nome di database dopo il segno @ nell’URL di connessione.
System.out.println ("connesso.");
// Crea un’istruzione
Statement stmt = conn.createStatement ();
// RetrieveRadius
ResultSet rset =stmt.executeQuery("select Raggio from VALORI_RAGGIO");
// Chiude resultSet
rset.close();
// Chiude l’istruzione
stmt.close();
// Chiude la connessione
conn.close();
}
try {
buffer.append ((char)c);
c = System.in.read ();
}
return buffer.toString ().trim ();
}
catch (IOException e) {
return "";
}
}
}
// RetrieveRadius
ResultSet rset =stmt.executeQuery("select Raggio from VALORI_RAGGIO");
Come sottolineato nel Capitolo 37, in Java è possibile ricorrere a un ciclo WHILE per avvi-
cinarsi alla funzionalità di un ciclo FOR a cursore PL/SQL. La parte seguente della sezione
RetrieveRadius utilizza il metodo getInt per recuperare il valore Raggio intero dal gruppo dei
risultati. Se il valore fosse stato una stringa, sarebbe stato impiegato il metodo getString.
La variabile radInput, assegnata nel listato precedente, ora può essere utilizzata come input
nel calcolo dell’area. Il calcolo dell’area viene eseguito tramite una funzione di utilità (fare
riferimento al listato JdbcCircle completo) basata sugli esempi di codice presentati nel Capitolo 37.
Ora si conosce il valore del raggio (la variabile radInput) e il valore dell’area (la variabile
result) da usare quando si popola la tabella AREE. Si crei l’istruzione insert per eseguire l’inse-
rimento. Innanzi tutto, si utilizzino le funzioni di concatenazione di stringhe in Java per concatenare
il testo con i valori delle variabili. Si presti attenzione a non inserire un punto e virgola alla fine
della stringa di comandi generata.
javac JdbcCircle.java
java JdbcCircle
Quando richiesto, fornire un nome utente e una password per il proprietario delle tabelle
VALORI_RAGGIO e AREE. Una volta completato il programma, controllare la tabella AREE:
RAGGIO AREA
--------- ---------
3 28.27
4 50.27
10 314.16
Questo esempio si basa su un calcolo semplice, l’area di un cerchio, tuttavia illustra i con-
cetti chiave nello sviluppo JDBC: connessione al database, recupero dei dati, implementazione
di un ciclo FOR a cursore, assegnamento delle variabili, creazione di un’istruzione SQL dinami-
ca ed esecuzione di DML.
JDBC permette di utilizzare funzionalità di programmazione molto avanzate, come caching
delle istruzioni, caching della connessione, failover della connessione, transazioni distribuite,
supporto per dati LOB e altro ancora. Per ulteriori dettagli sull’uso di JDBC si consulti la Oracle
Database JDBC Developer's Guide and Reference.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 39
È
possibile scrivere stored procedure, trigger, metodi del tipo
di oggetto e funzioni che chiamano le classi Java. In questo capitolo verrà introdotto un gruppo
di procedure Java di esempio insieme ai comandi che servono a eseguire una procedura. Per
apprendere il più possibile da questo capitolo, si dovrebbero conoscere già le strutture Java
(Capitolo 37) e i vari impieghi delle classi Java e di JDBC (Capitolo 38). Inoltre, si dovrebbe
avere già una certa familiarità con la sintassi di base e l’uso delle stored procedure (fare riferi-
mento al capitolo 31).
Per concentrarsi sulle operazioni di accesso al database delle classi Java, l’esempio di que-
sto capitolo sarà breve. La classe seguente, chiamata BookshelfDML, contiene dei metodi per
inserire e eliminare i record dalla tabella BIBLIOTECA. In questo esempio, tutti i valori richie-
sti vengono forniti durante l’inserimento. Il listato seguente mostra il file BookshelfDML.java:
import java.sql.*;
import java.io.*;
import oracle.jdbc.*;
try {
Connection conn =
DriverManager.getConnection("jdbc:default:connection:");
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, valutazione);
pstmt.setString(2, titolo);
pstmt.executeUpdate();
pstmt.close();
} catch (SQLException e) {System.err.println(e.getMessage());}
}
Le quattro variabili vengono definite con setString (per gli interi si sarebbe utilizzato setInt):
pstmt.setString(1, titolo);
pstmt.setString(2, editore);
pstmt.setString(3, nomecategoria);
pstmt.setString(4, valutazione);
Si osservi che i nomi delle variabili distinguono tra maiuscole e minuscole, pertanto devono
corrispondere esattamente ai nomi dichiarati precedentemente.
Il metodo delete possiede una struttura molto simile. La sua istruzione SQL è
Si osservi che nessuna delle parti della classe stabilisce una connessione al database, contra-
riamente a quanto accadeva negli esempi del Capitolo 38. La connessione impiegata per invoca-
re questa classe fornirà il contesto di connessione per i metodi della classe.
È possibile verificare la corretta compilazione della classe elaborandola tramite il compila-
tore Java. Questo passaggio comunque non convalida il codice SQL:
STORED PROCEDURE JAVA 655
javac BookshelfDML.java
Questo passaggio dovrebbe essere completato senza errori. Se durante questa fase di compi-
lazione si verificano degli errori, occorre controllare la configurazione dell’ambiente (Capitolo
38) e il file della classe.
Le opzioni disponibili per l’utility loadjava sono mostrate nella Tabella 39.1.
Per esempio, per caricare il file BookshelfDML.java nello schema Practice in un’istanza
chiamata “orcl”, si può ricorrere al comando seguente:
Si dovrebbe vedere una serie di commenti relativi al caricamento della classe nel database.
Nel caso in cui vengano riportati degli errori, il caricamento non sarà completato.
NOTA Il nome della classe non dovrebbe corrispondere al nome di nessuno degli
oggetti già esistenti nello schema.
Ora, la classe BookshelfDML è stata caricata nel database. Durante il caricamento, Oracle
darà vita a più tabelle e oggetti Java nello schema.
NOTA È possibile caricare manualmente i file Java dalle colonne BFILE o LOB
locali tramite i comandi create java [source | class | resource ].
Se si esegue il database su un server autonomo e non è stato definito un nome di servizio per
il database, sarà necessario indicare una specifica di connessione completa per la chiamata al
programma loadjava. Il formato sarà il seguente:
andresolve Compila i file sorgente e risolve ciascun file di classe mentre viene caricato.
definer Specifica che i metodi delle classi caricate verranno eseguiti con i privilegi del loro definitore, non del
loro chiamante. Per default, i metodi vengono eseguiti con i privilegi del loro chiamante.
encoding Imposta (o reimposta) l’opzione -encoding nella tabella del database JAVA$OPTIONS sul valore specificato.
force Forza il caricamento dei file di classe Java a prescindere dal fatto che siano stati caricati in precedenza.
Per default, i file di classe caricati in precedenza vengono rifiutati.
grant Assegna il privilegio EXECUTE sulle classi caricate agli utenti e ai ruoli elencati.
nousage Sopprime il messaggio di utilizzo dato se nessuna opzione viene specificata o se viene specificata
l’opzione -help.
noserverside Modifica il comportamento dello strumento loadjava sul lato server in modo che utilizzi un driver JDBC
per l’accesso agli oggetti.
noverify Provoca il caricamento delle classi senza verifica del bytecode. Occorre disporre del privilegio
oracle.aurora.security.JServerPermission(Verifier) per eseguire questa opzione. Inoltre questa opzione
dev’essere utilizzata in combinazione con –r.
oci8 Indirizza loadjava a comunicare con il database utilizzando il driver JDBC OCI. Questa opzione (predefinita)
e -thin sono reciprocamente esclusive.
resolve Risolve tutti i riferimenti esterni nelle classi caricate e compilate. Se questa opzione non è specificata, i
file vengono caricati ma non compilati o risolti fino alla fase di esecuzione.
resolver Lega gli oggetti dello schema della classe appena creata a uno specificatore di resolver definito dal-
l’utente.
tableschema Crea le tabelle interne loadjava in questo schema specificato invece che nello schema di destinazione
del file Java.
thin Indirizza loadjava a comunicare con il database utilizzando il driver JDBC thin. Questa opzione e –oci8 si
escludono a vicenda.
unresolvedok Quando combinata con -resolve, ignora gli errori non risolti.
user Specifica un utente, una password e una stringa di connessione al database per il caricamento.
Questa breve procedura ha quattro parametri, corrispondenti alle quattro colonne della ta-
bella BIBLIOTECA. La sua clausola language java comunica a Oracle che la procedura sta
chiamando un metodo Java. Il nome del metodo è specificato nella clausola name (si verifichi la
coerenza con l’uso delle lettere maiuscole). Quindi vengono specificati i formati per la chiamata
al metodo Java.
Una procedura separata eliminerà i record della tabella BIBLIOTECA tramite una chiamata
al metodo:
Ora, ci si deve spostare in SQL*Plus e utilizzare il comando call per eseguire le classi Java.
call InsertBookshelfViaJava('TEST','TESTPub','SAGGIADULTI','2');
Call completed.
begin
InsertBookshelfViaJava('TEST','TESTPub','SAGGIADULTI','2');
end;
/
Il comando call passerà i valori delle colonne come parametri alla stored procedure denomi-
nata InsertBookshelfViaJava. Li formatterà secondo le specifiche contenute nella clausola name
e li passerà al metodo AreasDML.insert. Questo metodo utilizzerà la connessione corrente per
eseguire i propri comandi, e la riga verrà inserita. La maggior parte di queste librerie e classi non
sarà ancora stata caricata nel database. I passaggi da eseguire sono molti, quindi la prima volta
che si esegue la stored procedure Java le prestazioni ne risentiranno, mentre le esecuzioni suc-
cessive saranno molto più veloci. È possibile verificare l’esito eseguendo una query sulla tabella
BIBLIOTECA:
begin
UpdateBookshelfViaJava('3','TEST');
end;
/
begin
DeleteBookshelfViaJava('TEST');
end;
/
no rows selected
set serveroutput on
call DBMS_JAVA.SET_OUTPUT(10000);
Quando l’accesso avviene tramite questa API, gli argomenti delle procedure non possono
essere OUT o IN OUT. I valori restituiti devono tutti far parte del risultato della funzione. Occor-
re osservare che la chiamata al metodo utilizzerà i diritti del chiamante. Per maggior dettagli
sull’API si rimanda alle guide per sviluppatori Java fornire con il software Oracle.
Se il codice richiede molti cicli e manipolazioni di dati, Java potrebbe offrire prestazioni
migliori di PL/SQL. Gli svantaggi derivati dall’uso di Java per la creazione di oggetti Java e
l’interazione dell’intestazione PL/SQL verranno controbilanciati dalle migliori prestazioni che
Java raggiunge durante il lavoro effettivo. Occorre osservare che il linguaggio PL/SQL nativo
compilato disponibile in Oracle Database 10g dovrebbe fornire una valida alternativa a Java dal
punto di vista delle prestazioni.
In linea di massima, PL/SQL e SQL gestiscono meglio le azioni che richiedono la selezione
dei dati dal database e la loro manipolazione. Java potrebbe invece eseguire più rapidamente i
calcoli sui dati selezionati. Durante la progettazione dell’applicazione, occorre accertarsi di uti-
lizzare lo strumento giusto per la funzione adatta in modo da evitare inutili cali di prestazioni.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Parte settima
ORACLE E I CLUSTER:
IL GRID COMPUTING
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 40
Oracle Real
Application Clusters
I
n un ambiente Oracle Real Application Clusters (RAC) più istan-
ze accedono a un unico database. In genere tali istanze vengono create su server separati, colle-
gati tramite una connessione ad alta velocità con accesso a un’area del disco condivisa. I file del
database risiedono in un insieme condiviso di dischi e ogni istanza ha i propri file di controllo e
redo log in linea, anch’essi memorizzati sui dischi condivisi.
Un utente può essere istruito a connettersi al database attraverso una delle istanze a esso
associate; se un’istanza fallisce, è possibile ristabilire in modo dinamico la connessione al database
attraverso un’altra istanza disponibile nel cluster. RAC fornisce pertanto una soluzione ad alta
disponibilità (che tiene conto del fallimento di server e istanze) e una soluzione potente e scalabile
(aumentando la memoria e i processori a disposizione dei processi di connessione).
Questo capitolo offre una panoramica sull’installazione e le gestione di RAC. Molti dettagli
dipendono dal sistema operativo in uso, ma il flusso del processo di configurazione è uguale per
le diverse piattaforme. Questo capitolo concentrerà la propria attenzione sui processi comuni e
sulle funzionalità introdotte in Oracle Database 10g per migliorare la gestione e l’implementazione
di RAC.
NOTA Si deve scegliere una connessione supportata da Oracle. Per l’ultima ma-
trice di certificazione, fare riferimento al sito Web di Metalink (http://metalink.oracle.com).
664 CAPITOLO 40
NOTA RAC funziona sia con il clusterware del fornitore sia con quello di Oracle.
Anche se gli utenti con versioni precedenti di RAC possono aver installato una soluzione fornita
da terzi, questo capitolo sulla soluzione offerta da Oracle.
NOTA RAC è disponibile sia con la Standard Edition sia con la Enterprise Edition
di Oracle Database 10g.
Entrambe le fasi del processo d’installazione utilizzano OUI; per maggiori dettagli su que-
sto strumento, si rimanda al Capitolo 2. Dopo aver completato la prima fase (installazione di
CRS), si può procedere con la seconda: installare il software di Oracle Database 10g con RAC in
una home directory di Oracle diversa da quella utilizzata nella prima fase. Si consiglia inoltre di
utilizzare il programma di installazione per creare e configurare i servizi per l’ambiente RAC.
Completata l’installazione del software, OUI avvia Database Configuration Assistant per com-
pletare la configurazione dell’ambiente e creare il database RAC.
Spazio di memorizzazione
A partire da Oracle Database 10g, è possibile utilizzare la gestione automatica dello spazio di
memorizzazione (ASM, Automatic Storage Management) per creare gruppi di dischi e semplifi-
carne la gestione. Come descritto nel Capitolo 46, gli amministratori di database possono ag-
giungere dischi nuovi ai gruppi di dischi; Oracle provvederà a gestire il contenuto e la distribu-
zione dei file tra i dischi interessati.
ORACLE REAL APPLICATION CLUSTERS 665
Si può ricorrere a ASM per offrire ridondanza dall’interno di Oracle, se manca la ridondanza
hardware. Quando si definisce il gruppo di dischi, si può specificare anche un gruppo di riserva;
Oracle utilizzerà il gruppo di riserva come una versione ridondante del gruppo primario di dischi
contenuto nel gruppo. I programmi di installazione di Oracle si riferiscono alla ridondanza basa-
ta sul software come ridondanza “normale”. Si possono specificare più gruppi di riserva per
avere un’ulteriore protezione ridondante (a costo di altro spazio). Se la funzione di mirroring
hardware è disponibile, si può utilizzare la ridondanza esterna (basata sul file system).
Molti ambienti RAC sfruttano una combinazione di unità raw e software di gestione logica
dei volumi. La gestione logica dei volumi (Logical Volume Management, LVM) fornisce alle
unità raw un’interfaccia per la gestione dei file system.
È possibile utilizzare gruppi di dischi ASM per ridurre ulteriormente la complessità gestionale
del database RAC: Oracle gestisce i file e i file system. È possibile amministrare manualmente i
file e i gruppi di dischi, oppure ricorrere alle opzioni Grid Control di Oracle Enterprise Manager
(OEM) (fare riferimento al Capitolo 41).
Parametri di inizializzazione
Durante la procedura di configurazione delle istanze, è necessario impostare i valori per i para-
metri di inizializzazione del database, conservati nel file dei parametri del server. Le installazio-
ni di RAC dovrebbero ricorrere al file dei parametri del server per gestire il gruppo di parametri
condivisi dalle istanze.
I parametri di inizializzazione elencati nella Tabella 40.1 devono avere il medesimo valore
per tutte le istanze contenute nel cluster RAC, insieme alle relative descrizioni provenienti da
Oracle.
Nella Tabella 40.2 sono elencati i parametri di inizializzazione che devono avere valori unici
per ogni istanza contenuta nel cluster RAC, insieme alle relative descrizioni tratte da Oracle.
PARAMETRO DESCRIZIONE
CLUSTER_DATABASE_INSTANCES Imposta il numero di istanze nell’ambiente RAC.
DISPATCHERS Imposta DISPATCHERS per abilitare una configurazione di server condivisi (in cui
più processi utente si connettono a un dispatcher).
Tabella 40.1 Parametri di inizializzazione con gli stessi valori nelle diverse istanze di RAC.
PARAMETRO DESCRIZIONE
ACTIVE_INSTANCE_COUNT Consente di designare come primaria un’istanza in un ambiente a due istanze; l’altra sarà l’istanza se-
condaria. Questo parametro non ha funzionalità in un cluster con più di due istanze. Quando si imposta
questo parametro a 1, la prima istanza che si avvia diventa quella primaria e accetta le connessioni dei
client. La seconda istanza si avvia come istanza secondaria e può accettare le connessioni dei client
solo in caso di fallimento della prima. In questo caso, l’istanza secondaria diventa primaria.
CLUSTER_DATABASE Flag vero/falso che specifica se Real Application Clusters è o meno abilitato. Impostato a TRUE.
DB_BLOCK_SIZE Specifica la dimensione (in byte) dei blocchi del database Oracle.
DB_DOMAIN Specifica la collocazione logica del database nella struttura della rete. Il valore è costituito dai compo-
nenti di estensione di un nome di database globale, costituiti da identificatori validi separati da punti.
DB_FILES Specifica il numero massimo di file di database che è possibile aprire per questo database. Il valore
massimo valido è il numero massimo di file, soggetto ai limiti imposti dal sistema operativo, che verran-
no mai specificati per il database, compresi i file da aggiungere con il comando add datafile. Se si
aumenta il valore di DB_FILES, è necessario arrestare e riavviare tutte le istanze che accedono al database
prima che il nuovo valore entri in vigore. Se si dispone di un primario e di uno standby, devono avere lo
stesso valore per questo parametro.
DB_NAME Specifica un identiticatore di database al massimo di otto caratteri. Questo parametro dev’essere speci-
ficato e deve corrispondere al nome specificato nel comando create database.
DB_RECOVERY_FILE_DEST Specifica la posizione predefinita dell’area di recupero flashback. Quest’ultima contiene delle copie
multiplex dei control file e dei redo log in linea correnti, oltre che dei redo log archiviati, dei log di
flashback e dei backup di RMAN. Non è consentito specificare questo parametro senza anche specifica-
re il parametro di inizializzazione DB_RECOVERY_FILE_DEST_SIZE.
DB_RECOVERY_FILE_ Specifica (in byte) il limite fisico sullo spazio totale utilizzabile da parte dei file di recupero del database
DEST_SIZE di destinazione creati nell’area di recupero flashback.
DB_UNIQUE_NAME Specifica un nome unico globale per il database. Tutti i DB_UNIQUE_NAME dei database devono essere
unici nell’impresa.
MAX_COMMIT_ Questo parametro di inizializzazione non dovrebbe essere modificato se non in un insieme ristretto di
PROPAGATION_DELAY circostanze specifiche del cluster database. Questo parametro specifica il tempo massimo consentito
prima che il System Change Number (SCN) contenuto nella SGA di un’istanza sia aggiornato dal proces-
so di scrittura del log (LGWR, Log Writer Process). Esso determina se il valore SCN locale dev’essere
aggiornato dal valore di lock quando si ottiene il valore SCN di snapshot per una query. Le unità sono in
centesimi di secondo. In circostanze decisamente inusuali che implicano degli aggiornamenti rapidi e
delle query degli stessi dati da parte di diverse istanze, il valore SCN potrebbe non essere aggiornato nei
tempi corretti. L’impostazione del parametro a zero provoca l’aggiornamento immediato del SCN dopo
un commit. Il valore predefinito (700 centesimi di second, o sette secondi) è un limite superiore che
consente di mantenere attivo il meccanismo a elevate prestazioni esistente preferito.
SPFILE Nomi del file dei parametri del server corrente (SPFILE) in uso. Questo parametro può essere definito in
un PFILE sul lato client per indicare il nome del file dei parametri del server da utilizzare. Quando il server
utilizza il file dei parametri del server predefinito, il valore di SPFILE viene impostato internamente dal
server.
TRACE_ENABLED Flag vero falso che controlla il tracciamento della cronologia delle esecuzioni, o percorso del codice, di
Oracle. Quando questo parametro è impostato a TRUE, Oracle registra le informazioni nei file di log
quando si verificano degli errori. Oracle registra queste informazioni per tutte le istanze, anche se solo
una istanza termina.
UNDO_MANAGEMENT Specifica quale modalità di gestione dello spazio di undo il sistema dovrebbe utilizzare. Quando è impo-
stata a AUTO, l’istanza si avvia in modalità di gestione degli undo automatica. Nella modalità di gestione
degli undo manuale, lo spazio di undo viene allocato esternamente come segmenti di rollback.
ORACLE REAL APPLICATION CLUSTERS 667
Tabella 40.2 Parametri di inizializzazione con valori distinti nelle varie istanze RAC.
PARAMETRO DESCRIZIONE
INSTANCE_NUMBER Specifica un numero univoco che mette in corrispondenza l’istanza con un gruppo come per ciascun
oggetto di database creato con il parametro di memorizzazione FREELIST GROUPS.
ROLLBACK_SEGMENTS Alloca uno o più segmenti di rollback in base al nome di questa istanza. Quando UNDO_MANAGEMENT
è impostata AUTO, ROLLBACK_SEGMENTS viene ignorata.
THREAD Se viene specificato, questo parametro deve avere dei valori unici su tutte le circostanze. Il parametro
THREAD specifica il numero del redo thread da usare. È possibile specificare qualunque numero di
thread di redo disponibile; a patto che il numero di thread siaabiltato ma non usato.
UNDO_TABLESPACE Specifica la tablespace di undo da utilizzare all’avvio di una istanza. Se questo parametto viene specifi-
cato quando l’istanza è in modalità mauale di gestione degli undo, si verificherà un errore e l’avvio non
riuscirà.
listener. Come con qualsiasi altro database non RAC, si può utilizzare SQL*Plus per eseguire i
comandi shutdown e startup. Per i database RAC si può anche usare l’utility SRVCTL, come
mostrato negli esempi di questo paragrafo.
A prescindere dallo strumento usato per arrestare o avviare l’istanza, ai cluster RAC si devo-
no applicare le regole seguenti:
■ La chiusura di un’istanza non interferisce con il funzionamento di altre istanze in esecuzione.
■ La chiusura di un database montato in modalità condivisa richiede la chiusura di ogni istan-
za presente nel cluster RAC.
■ Dopo un comando shutdown normal o shutdown immediate, non è necessario recuperare le
istanze. Se per un’istanza RAC si utilizza shutdown abort, un’istanza ancora in esecuzione effet-
tua il recupero dell’istanza chiusa. Se l’istanza interrotta era anche l’ultima in esecuzione, la
prima istanza ad avviarsi eseguirà il recupero.
■ Se si utilizza shutdown transactional con l’opzione local, tutte le transazioni nell’istanza
dovranno essere confermate o annullate prima della chiusura. Le transazioni presenti nelle altre
istanze non influiscono sul comando shutdown transactional locale. Se non si specifica la clau-
sola local, shutdown transactional aspetterà che tutte le transazioni presenti su tutte le istanze
avviate prima del comando shutdown siano state completate.
Si possono utilizzare i comandi SQL*Plus per arrestare e avviare uno alla volta i database
RAC fino all’avvio dell’intero ambiente. Per ulteriori dettagli sui comandi startup e shutdown,
si rimanda al Capitolo 46. Con il comando startup mount è possibile avviare un’istanza nel nodo
locale.
L’utility SRVCTL può essere impiegata per gestire più istanze in un unico comando. La
sintassi per avviare le istanze è la seguente:
La parola chiave dopo srvctl start specifica il servizio da avviare: istanza, database, servizio,
nodeapps o asm. Si osservi che è possibile passare più istanze come parti del valore del parame-
tro elenco_nomi_istanze (attraverso un elenco separato da virgole). Le opzioni_avvio sono open,
mount e nomount. Il parametro stringa_connessione consente di passare una stringa di connes-
sione mentre ci si connette al database. Il parametro q, se specificato, comunica a SRVCTL di
668 CAPITOLO 40
richiedere informazioni sulla connessione dell’utente mentre SRVCTL è in esecuzione; per default,
SRVCTL si connette al database locale come SYSDBA.
Il comando seguente avvia e apre un database locale di nome MYDB:
Per le istanze ASM, occorre specificare il nome del nodo (-n), il nome dell’istanza (-i) e le
opzioni di avvio (-o), come nell’esempio seguente:
NOTA Per visualizzare le istanze che fanno parte del cluster, si può utilizzare OEM
o SQL*Plus. Da SQL*Plus si esegua una query sulla vista V$ACTIVE_INSTANCES. La vista
visualizzerà una riga per ogni istanza, mostrando il numero dell’istanza, il nome host e il nome
dell’istanza.
db.us.acme.com=
(description= (load_balance=on) (failover=on)
(address_list=
(address=(protocol=tcp)(host=db1-server)(port=1521))
(address=(protocol=tcp)(host=db2-server)(port=1521)))
(connect_data= (service_name=db.us.acme.com)))
ORACLE REAL APPLICATION CLUSTERS 669
srvctl disable {database|instance|service|asm} Disabilita l’oggetto denominato e impedisce che si avvii automa-
ticamente.
srvctl relocate service Riloca i nomi dei servizi denominati da un’istanza con nome a
un’altra istanza con nome.
srvctl start {database|instance|service|nodeapps|asm} Avvia le applicazioni abilitate a CRS, le applicazioni non in ese-
cuzione per il database, tutte le istanze con nome o quelle deno-
minate, tutti i nomi dei servizi o di quelli con nome o le parametro
a livello di nodo..
srvctl stop {database|instance|service|nodeapps|asm} Interrompe le applicazioni CRS per il database le applicazioni non
in esecuzione per il database, tutte le istanze con nome o quelle
denominate, tutti i nomi dei servizi o di quelli con nome o le para-
metro a livello di nodo..
srvctl unsetenv {database|instance|service|nodeapps} Togli l’impostazione dei valori di ambiente nel file di configura-
zione.
L’utente può connettersi all’istanza tramite il nome del servizio db.us.acme.com (per esem-
pio, attraverso un sessione SQL*Plus remota) ed eseguire le query. Mentre l’utente è connesso,
è possibile chiudere l’host db1-server. Se l’utente cerca di eseguire un’altra query, mentre si
trova nella stessa sessione, la sessione verrà ristabilita in modo trasparente mediante l’host db2-
server e la query verrà eseguita.
La voce del file listener.ora relativa al database conterrà voci simili a quelle del listato se-
guente:
listeners_db.us.acme.com=
(address=(protocol=tcp)(host=db1-server)(port=1521)) (address=(protocol=tcp)(host=db2-
server)(port=1521))
670 CAPITOLO 40
Se l’utente ha modificato le variabili ambientali all’interno della sessione (con alter session),
o ha impostato variabili specifiche della sessione, potrebbe essere necessario ristabilire questi
valori nella sessione appena connessa.
Servizi
Come descritto in precedenza nel capitolo, è possibile creare e gestire i servizi all’interno del
cluster RAC. Si possono destinare servizi da eseguire su una o più istanze; i servizi integrano le
risorse del cluster database per semplificare la gestibilità dei cluster.
Come mostrato nella Tabella 40.2, si può utilizzare SVRCTL per creare e aggiungere servi-
zi. È possibile assegnare servizi alle istanze per un’elaborazione preferenziale (normale) e di-
sponibile (recupero). Si possono identificare altre istanze disponibili a supportare modifiche dei
livelli di servizio o per interruzioni pianificate.
NOTA Si può ricorrere a DBCA per gestire le assegnazioni dei servizi e le prefe-
renze dei servizi.
Per rimuovere un’istanza già esistente da un cluster RAC, avviare DBCA su un nodo diverso
da quello che ospita l’istanza da rimuovere. DBCA visualizzerà un elenco delle istanze correnti
nella configurazione; selezionare quella da rimuovere da questo elenco. DBCA visualizzerà un
elenco dei servizi assegnati a questa istanza in modo che li si possa rilocare in altre istanze del
cluster. L’istanza selezionata verrà deregistrata dal cluster RAC.
-backuploc Cambiare la posizione del file di backup OCR. Per questa voce occorre utilizzare un percorso completo
che sia accessibile da tutti i nodi.
-showbackup Visualizzare la posizione, l’indicatore orario e il nome del nodo di origine per gli ultimi tre file di backup
creati automaticamente.
Architettura a griglia
e gestione della griglia
L
a g di Oracle Database 10g è l’abbreviazione di “grid”. Il “grid
computing” (lett. “elaborazione a griglia”) consente di trattare l’infrastruttura di elaborazione
come un servizio condiviso, la cui composizione viene gestita lontano dalla vista delle applica-
zioni client. In questo senso, il servizio di elaborazione può essere paragonato a un impianto
elettrico in cui i sistemi che forniscono il servizio non sono direttamente visibili da parte degli
utenti finali. La fonte dell’energia elettrica e i sistemi utilizzati per gestirla non risultano palesi
all’utente.
In un’architettura a griglia è possibile gestire le risorse per supportare in modo dinamico le
esigenze dell’utente finale. L’architettura a griglia aiuta a migliorare la disponibilità delle appli-
cazioni e consente la gestione dinamica delle risorse per gestire carichi di lavoro mutevoli. Le
risorse della griglia comprendono server, dischi e istanze. Nelle release precedenti, Oracle met-
teva a disposizione degli strumenti a supporto di alcune caratteristiche correlate alla griglia: la
più famosa era Real Application Clusters di Oracle9i (RAC). Oracle Database 10g introduce
altri strumenti che semplificano la gestione delle griglie di applicazioni, fornendo un insieme
completo di opzioni a supporto del grid computing. Ecco alcune caratteristiche a supporto del
grid computing:
■ Real Application Clusters Si possono creare più istanze che accedono al medesimo database,
consentendo di distribuire il carico di lavoro della memoria tra più server. Si possono inoltre
aggiungere nuove istanze al cluster in relazione alle proprie esigenze.
■ Gestione automatica dello spazio di memorizzazione Si possono creare gruppi di dischi
disponibili (fare riferimento al Capitolo 46) cui assegnare file di dati. Oracle provvederà a gesti-
re gli accessi di I/O ai gruppi di dischi e a ridistribuire i file a seconda della necessità.
■ Tecnologia di replica La replica veloce dei dati tra più database consente l’utilizzo di
database come parte di una griglia di origini dati disponibili. La tecnologia di replica include le
tablespace trasportabili (Capitolo 46), le viste materializzate (Capitolo 24), Oracle Streams (re-
plica basata sui log) e le transazioni distribuite (Capitolo 23).
■ Tecnologia di protezione Si può supportare l’utilizzo condiviso dei database da parte di
applicazioni diverse o processi aziendali. In un database condiviso, potrebbe rivelarsi necessario
creare database virtuali che prevengono l’accesso non autorizzato a dati appartenenti ad altri
settori aziendali o ad altre applicazioni. Per ulteriori dettagli sui Virtual Private Database, si
rimanda al Capitolo 19.
674 CAPITOLO 41
■ Pianificazione delle risorse con Oracle Enterprise Manager (OEM) È possibile utilizza-
re le procedure contenute nel package DBMS_SCHEDULER per creare programmi che
supportano l’esecuzione di script di shell a livello di sistema operativo, oltre a operazioni esegui-
te con il database. Si possono creare programmi tramite la procedura CREATE_PROGRAM,
pianificarli con CREATE_SCHEDULE e inviare il processo attraverso CREATE_JOB.
Questo capitolo offre una panoramica generale delle funzionalità della griglia e spiega in
che modo queste ultime si adattano nell’architettura di grid computing. L’implementazione del-
la griglia richiede che l’infrastruttura sia configurata in modo da supportare l’architettura distri-
buita e flessibile richiesta. Nel prossimo paragrafo verranno introdotti gli elementi di configura-
zione fondamentali per i componenti hardware e dei sistemi operativi.
I file system tradizionali non supportano i requisiti di accesso delle architetture a griglia,
pertanto si dovrà ricorrere a un file system in grado di soddisfare i requisiti di accesso simulta-
neo. Le opzioni più comuni sono le unità raw e i file system per cluster. Le unità raw vengono
utilizzate da anni per supportare gli ambienti RAC di Oracle, poiché consentono l’accesso si-
multaneo da parte di più processi. Tuttavia, amministrare le unità raw è generalmente più diffici-
le che gestire file system equivalenti. Sia le unità raw sia i file system per cluster richiedono un
sistema di memorizzazione con modalità a blocchi, come per esempio SAN e iSCSI.
In linea di massima, i file system sono più semplici da gestire rispetto alle unità raw: li si può
facilmente ridimensionare, spostare e rinominare. In genere, le velocità d’accesso delle unità
raw e dei file system per cluster si equivalgono. A meno di motivi specifici che inducano a
utilizzare delle unità raw nel proprio ambiente, è meglio prediligere l’impiego nella griglia di
file system per cluster. Oracle fornisce un proprio file system per cluster, Oracle Cluster File
System (OCFS), per supportare l’accesso a file condivisi.
stallazione del solo software che non comporti la creazione di un database. Eseguire il file di
configurazione (per UNIX si tratta di root.sh) per completare l’installazione.
gsdctl start
Non appena GSD è in esecuzione, si avvii OUI selezionando le opzioni “Cluster database”.
Dovrebbe comparire una pagina Instance Management dalla quale si può scegliere di aggiungere
istanze a un cluster già esistente. Verrà chiesto di inserire informazioni simili a quelle visualizzate
durante l’installazione del database: dettagli sul gruppo di redo log, informazioni sulla tablespace
e nome dell’istanza. Quando si accettano le impostazioni, DBCA avvierà e creerà l’istanza ri-
chiesta.
Per rimuovere un’istanza dalla griglia, occorre passare attraverso OUI per raggiungere la
pagina Instance Management. Poi si seleziona “Delete Instance” insieme al nome dell’istanza da
rimuovere dal cluster; DBCA provvederà a eliminare l’istanza.
■ Tabelle esterne I file all’esterno del database possono essere considerati come tabelle,
pertanto si possono effettuare query su questi file come se le loro linee fossero le righe di una
tabella. I file possono essere localizzati su dischi condivisi. Vedere il Capitolo 26.
■ Oracle Streams Oracle Streams utilizza le voci di redo log per generare il codice SQL
necessario a replicare le transazioni nei database.
■ Data Pump Export e Import Si può utilizzare Data Pump Export e Import per creare
operazioni sul lato server che estraggono e caricano i dati dai database. Vedere il Capitolo 22.
Tutte queste tecnologie servono a rendere disponibili i dati nella griglia. Il prossimo para-
grafo fornisce ulteriori dettagli sulle capacità di gestione introdotte per supportare l’architettura
a griglia.
Per installare Oracle Management Agent, occorre eseguire OUI su ciascun server dell’am-
biente. Durante l’installazione, scegliere Additional Management Agent come tipo di installa-
zione. Sono disponibili anche le opzioni per l’installazione invisibile; fare riferimento al docu-
mento “Oracle 10g Grid Control Configuration and Installation” per avere indicazioni sull’in-
stallazione invisibile. Oracle fornisce file di risposta standard da utilizzare per le installazioni
invisibili.
Dopo l’installazione, è necessario eseguire il file di comando root.sh in qualità di utente root
per completare il processo post-installazione.
http://oracle.com/support/metalink/index.html
care che l’account sia accessibile (potrebbe essere necessario ricorrere al comando alter user
dbsnmp account unlock). Quindi, si può aprire la pagina Configure Database | Properties della
Grid Control Console di OEM e configurare il database per il monitoraggio. In questa pagina,
inserire la password per l’utente DBSNMP nel database di destinazione.
Per le destinazioni di monitoraggio ASM, spostarsi in Targets | All Targets dalla Grid Control
Console di OEM. Quando si configura la destinazione, verrà chiesta la password SYS da utiliz-
zare nel monitoraggio ASM.
È possibile verificarne lo stato mediante emctl status oms. Ecco come avviare tutti i compo-
nenti di Application Server, compreso Management Service:
opmnctl startall
http://mgmtserver_hostname.domain:port/em
ARCHITETTURA A GRIGLIA E GESTIONE DELLA GRIGLIA 681
Nella Tabella 41.2 sono elencate le impostazioni di altri parametri consigliati per Oracle
Management Repository.
db_block_size 8192
remote_login_passwordfile EXCLUSIVE
timed_statistics TRUE
open_cursors 300
shared_pool_size 67108864
aq_tm_processes 1 o maggiore
session_cached_cursors 200
large_pool_size 0
processes 150
fast_start_mttr_target 300
hash_area_size 1048576
sort_area_size 1048576
pga_aggregate_target 33554432
undo_management AUTO
undo_retention 10800
undo_tablespace UNDOTBS
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
GUIDE
Parte ottava
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 42
I
l dizionario dati di Oracle memorizza tutte le informazioni che
servono a gestire gli oggetti nel database. Anche se costituisce abitualmente il dominio degli
amministratori di database (DBA), il dizionario dati è anche una fonte di informazioni preziose
per gli sviluppatori e gli utenti finali.
In questo capitolo, il dizionario dati, ovvero la directory interna di Oracle, viene descritto
dal punto di vista dell’utente finale; per questo motivo, le tabelle e le viste del dizionario dati non
sono elencate in ordine alfabetico, ma raggruppate per funzione (tabelle, sicurezza e così via).
Questo tipo di organizzazione consente di individuare rapidamente le informazioni desiderate.
Sono descritte tutte le viste del dizionario dati più utilizzate, con esempi del loro impiego.
686 CAPITOLO 42
In base alle opzioni di configurazione di Oracle utilizzate, alcuni dei gruppi non riguardano
tutti i database. Le viste più utilizzate sono analizzate per prime. I aggruppamenti utilizzati in
questo capitolo sono, nell’ordine:
■ Nuove viste introdotte in Oracle Database 10g.
■ Nuove colonne introdotte in Oracle Database 10g.
■ Le “carte stradali”: DICTIONARY (DICT) e DICT_COLUMNS.
■ Oggetti da cui è possibile selezionare: tabelle (e colonne), viste, sinonimi e sequenze.
■ Vincoli e commenti.
■ Indici e cluster.
■ Tipi di dati astratti, strutture correlate a ORDBMS e LOB.
■ Database link e viste materializzate.
■ Trigger, procedure, funzioni e package.
■ Dimensioni.
■ Allocazione e uso dello spazio, comprese partizioni e partizioni secondarie.
■ Utenti e privilegi.
■ Ruoli.
■ Audit.
■ Varie.
■ Monitoraggio: le tabelle di prestazioni dinamiche V$.
Tabella 42.1 Nuove viste del dizionario dati introdotte in Oracle Database 10g.
VISTE ALL_ VISTE DBA VISTE USER_
DBA_ADVISOR_ACTIONS USER_ADVISOR_ACTIONS
DBA_ADVISOR_COMMANDS
DBA_ADVISOR_DEFINITIONS
DBA_ADVISOR_FINDINGS USER_ADVISOR_FINDINGS
DBA_ADVISOR_JOURNAL USER_ADVISOR_JOURNAL
DBA_ADVISOR_LOG USER_ADVISOR_LOG
DBA_ADVISOR_OBJECT_TYPES
DBA_ADVISOR_OBJECTS USER_ADVISOR_OBJECTS
DBA_ADVISOR_PARAMETERS USER_ADVISOR_PARAMETERS
DBA_ADVISOR_RATIONALE USER_ADVISOR_RATIONALE
DBA_ADVISOR_RECOMMENDATIONS USER_ADVISOR_RECOMMENDATIONS
DBA_ADVISOR_SQLA_REC_SUM USER_ADVISOR_SQLA_REC_SUM
DBA_ADVISOR_SQLA_WK_MAP USER_ADVISOR_SQLA_WK_MAP
DBA_ADVISOR_SQLA_WK_STMTS USER_ADVISOR_SQLA_WK_STMTS
DBA_ADVISOR_SQLW_JOURNAL USER_ADVISOR_SQLW_JOURNAL
DBA_ADVISOR_SQLW_PARAMETERS USER_ADVISOR_SQLW_PARAMETERS
DBA_ADVISOR_SQLW_STMTS USER_ADVISOR_SQLW_STMTS
DBA_ADVISOR_SQLW_SUM USER_ADVISOR_SQLW_SUM
DBA_ADVISOR_SQLW_TABLES USER_ADVISOR_SQLW_TABLES
DBA_ADVISOR_SQLW_TEMPLATES USER_ADVISOR_SQLW_TEMPLATES
DBA_ADVISOR_TASKS USER_ADVISOR_TASKS
DBA_ADVISOR_TEMPLATES USER_ADVISOR_TEMPLATES
DBA_ADVISOR_USAGE
DBA_ALERT_HISTORY
ALL_APPLY_ENQUEUE DBA_APPLY_ENQUEUE
ALL_APPLY_EXECUTE DBA_APPLY_EXECUTE
DBA_APPLY_INSTANTIATED_GLOBAL
DBA_APPLY_INSTANTIATED_SCHEMAS
ALL_APPLY_TABLE_COLUMNS DBA_APPLY_TABLE_COLUMNS
ALL_AW_PS
ALL_AWS
ALL_CAPTURE_EXTRA_ATTRIBUTES DBA_CAPTURE_EXTRA_ATTRIBUTES
DBA_COMMON_AUDIT_TRAIL
DBA_DATAPUMP_JOBS USER_DATAPUMP_JOBS
DBA_DATAPUMP_SESSIONS
DBA_ENABLED_AGGREGATIONS
DBA_ENABLED_TRACES
DBA_FEATURE_USAGE_STATISTICS
DBA_HIGH_WATER_MARK_STATISTICS
DBA_HIST_ACTIVE_SESS_HISTORY
DBA_HIST_BASELINE
DBA_HIST_BG_EVENT_SUMMARY
DBA_HIST_BUFFER_POOL_STAT
(segue)
688 CAPITOLO 42
Tabella 42.1 Nuove viste del dizionario dati introdotte in Oracle Database 10g. (continua)
VISTE ALL_ VISTE DBA VISTE USER_
DBA_HIST_CR_BLOCK_SERVER
DBA_HIST_CURRENT_BLOCK_SERVER
DBA_HIST_DATABASE_INSTANCE
DBA_HIST_DATAFILE
DBA_HIST_DB_CACHE_ADVICE
DBA_HIST_DLM_MISC
DBA_HIST_ENQUEUE_STAT
DBA_HIST_EVENT_NAME
DBA_HIST_FILEMETRIC_HISTORY
DBA_HIST_FILESTATXS
DBA_HIST_INSTANCE_RECOVERY
DBA_HIST_JAVA_POOL_ADVICE
DBA_HIST_LATCH
DBA_HIST_LATCH_CHILDREN
DBA_HIST_LATCH_MISSES_SUMMARY
DBA_HIST_LATCH_NAME
DBA_HIST_LATCH_PARENT
DBA_HIST_LIBRARYCACHE
DBA_HIST_LOG
DBA_HIST_METRIC_NAME
DBA_HIST_MTTR_TARGET_ADVICE
DBA_HIST_OPTIMIZER_ENV
DBA_HIST_OSSTAT
DBA_HIST_OSSTAT_NAME
DBA_HIST_PARAMETER
DBA_HIST_PARAMETER_NAME
DBA_HIST_PGA_TARGET_ADVICE
DBA_HIST_PGASTAT
DBA_HIST_RESOURCE_LIMIT
DBA_HIST_ROLLSTAT
DBA_HIST_ROWCACHE_SUMMARY
DBA_HIST_SEG_STAT
DBA_HIST_SEG_STAT_OBJ
DBA_HIST_SERVICE_NAME
DBA_HIST_SERVICE_STAT
DBA_HIST_SERVICE_WAIT_CLASS
DBA_HIST_SESSMETRIC_HISTORY
DBA_HIST_SGA
DBA_HIST_SGASTAT
DBA_HIST_SHARED_POOL_ADVICE
DBA_HIST_SNAP_ERROR
DBA_HIST_SNAPSHOT
DBA_HIST_SQL_PLAN
DBA_HIST_SQL_SUMMARY
(segue)
GUIDA AL DIZIONARIO DATI DI ORACLE 689
Tabella 42.1 Nuove viste del dizionario dati introdotte in Oracle Database 10g. (continua)
VISTE ALL_ VISTE DBA VISTE USER_
DBA_HIST_SQL_WORKAREA_HSTGRM
DBA_HIST_SQLBIND
DBA_HIST_SQLSTAT
DBA_HIST_SQLTEXT
DBA_HIST_STAT_NAME
DBA_HIST_SYS_TIME_MODEL
DBA_HIST_SYSMETRIC_HISTORY
DBA_HIST_SYSMETRIC_SUMMARY
DBA_HIST_SYSSTAT
DBA_HIST_SYSTEM_EVENT
DBA_HIST_TABLESPACE_STAT
DBA_HIST_TBSPC_SPACE_USAGE
DBA_HIST_TEMPFILE
DBA_HIST_TEMPSTATXS
DBA_HIST_THREAD
DBA_HIST_UNDOSTAT
DBA_HIST_WAITCLASSMET_HISTORY
DBA_HIST_WAITSTAT
DBA_HIST_WR_CONTROL
DBA_LOGMNR_LOG
DBA_LOGMNR_PURGED_LOG
DBA_LOGMNR_SESSION
DBA_OUTSTANDING_ALERTS
DBA_RECYCLEBIN USER_RECYCLEBIN
DBA_REDEFINITION_ERRORS
DBA_REDEFINITION_OBJECTS
DBA_REGISTERED_ARCHIVED_LOG
DBA_RSRC_GROUP_MAPPINGS
DBA_RSRC_MAPPING_PRIORITY
ALL_SCHEDULER_JOB_CLASSES DBA_SCHEDULER_JOB_CLASSES
(segue)
690 CAPITOLO 42
Tabella 42.1 Nuove viste del dizionario dati introdotte in Oracle Database 10g. (continua)
VISTE ALL_ VISTE DBA VISTE USER_
ALL_SCHEDULER_WINDOW_DETAILS DBA_SCHEDULER_WINDOW_DETAILS
ALL_SCHEDULER_WINDOW_GROUPS DBA_SCHEDULER_WINDOW_GROUPS
ALL_SCHEDULER_WINDOW_LOG DBA_SCHEDULER_WINDOW_LOG
ALL_SCHEDULER_WINDOWS DBA_SCHEDULER_WINDOWS
ALL_SCHEDULER_WINGROUP_MEMBERS DBA_SCHEDULER_WINGROUP_MEMBERS
DBA_SERVER_REGISTRY
ALL_SERVICES DBA_SERVICES
DBA_SQL_PROFILES
DBA_SQLSET USER_SQLSET
DBA_SQLSET_BINDS USER_SQLSET_BINDS
DBA_SQLSET_REFERENCES USER_SQLSET_REFERENCES
DBA_SQLSET_STATEMENTS USER_SQLSET_STATEMENTS
DBA_SQLTUNE_BINDS USER_SQLTUNE_BINDS
DBA_SQLTUNE_PLANS USER_SQLTUNE_PLANS
DBA_SQLTUNE_RATIONALE_PLAN USER_SQLTUNE_RATIONALE_PLAN
DBA_SQLTUNE_STATISTICS USER_SQLTUNE_STATISTICS
DBA_STREAMS_ADMINISTRATOR
ALL_STREAMS_MESSAGE_CONSUMERS DBA_STREAMS_MESSAGE_CONSUMERS
ALL_STREAMS_MESSAGE_RULES DBA_STREAMS_MESSAGE_RULES
ALL_STREAMS_NEWLY_SUPPORTED DBA_STREAMS_NEWLY_SUPPORTED
ALL_STREAMS_RULES DBA_STREAMS_RULES
ALL_STREAMS_TRANSFORM_FUNCTION DBA_STREAMS_TRANSFORM_FUNCTION
ALL_STREAMS_UNSUPPORTED DBA_STREAMS_UNSUPPORTED
DBA_TABLESPACE_GROUPS
DBA_THRESHOLDS
DBA_TUNE_MVIEW USER_TUNE_MVIEW
RECYCLEBIN) consente la ricreazione degli oggetti eliminati. Per esempi del comando flashback
table si rimanda al Capitolo 28. Tra le altre caratteristiche supportate dalle nuove viste ci sono le
capacità potenziate di generazione di consigli.
Tabella 42.2 Nuove colonne del dizionario dati introdotte in Oracle Database 10g.
VISTA DEL DIZIONARIO DATI STATICA NUOVE COLONNE
ALL_ALL_TABLES DROPPED
ALL_APPLY PRECOMMIT_HANDLER
MAX_APPLIED_MESSAGE_NUMBER
NEGATIVE_RULE_SET_NAME
NEGATIVE_RULE_SET_OWNER
STATUS_CHANGE_TIME
ERROR_NUMBER
ERROR_MESSAGE
ALL_APPLY_DML_HANDLERS APPLY_NAME
ALL_APPLY_PROGRESS SOURCE_DATABASE
ALL_AUDIT_POLICIES SEL
INS
UPD
DEL
AUDIT_TRAIL
POLICY_COLUMN_OPTIONS
ALL_CAPTURE CAPTURE_USER
CAPTURED_SCN
APPLIED_SCN
USE_DATABASE_LINK
FIRST_SCN
SOURCE_DATABASE
SOURCE_DBID
SOURCE_RESETLOGS_SCN
SOURCE_RESETLOGS_TIME
LOGMINER_ID
NEGATIVE_RULE_SET_NAME
NEGATIVE_RULE_SET_OWNER
MAX_CHECKPOINT_SCN
REQUIRED_CHECKPOINT_SCN
LOGFILE_ASSIGNMENT
STATUS_CHANGE_TIME
ERROR_NUMBER
ERROR_MESSAGE
VERSION
CAPTURE_TYPE
ALL_DEF_AUDIT_OPTS FBK
ALL_DIM_ATTRIBUTES ATTRIBUTE_NAME
ALL_ERRORS ATTRIBUTE
MESSAGE_NUMBER
ALL_EXTERNAL_TABLES PROPERTY
ALL_INDEXES IOT_REDUNDANT_PKEY_ELIM
DROPPED
ALL_INDEXTYPES ARRAY_DML
ALL_LOBS TABLESPACE_NAME
FORMAT
PARTITIONED
ALL_LOG_GROUP_COLUMNS LOGGING_PROPERTY
ALL_LOG_GROUPS LOG_GROUP_TYPE
GENERATED
ALL_MVIEWS UNKNOWN_TRUSTED_FD
STALE_SINCE
ALL_OBJECT_TABLES DROPPED
ALL_OUTLINES COMPATIBLE
ENABLED
FORMAT
ALL_PART_COL_STATISTICS HISTOGRAM
ALL_POLICIES IDX
POLICY_TYPE
LONG_PREDICATE
(segue)
692 CAPITOLO 42
Tabella 42.2 Nuove colonne del dizionario dati introdotte in Oracle Database 10g. (continua)
VISTA DEL DIZIONARIO DATI STATICA NUOVE COLONNE
ALL_PROPAGATION NEGATIVE_RULE_SET_OWNER
NEGATIVE_RULE_SET_NAME
ALL_SUBPART_COL_STATISTICS HISTOGRAM
ALL_SUBSCRIBED_COLUMNS SUBSCRIPTION_NAME
ALL_SUBSCRIBED_TABLES SUBSCRIPTION_NAME
ALL_SUBSCRIPTIONS SUBSCRIPTION_NAME
ALL_TAB_COL_STATISTICS HISTOGRAM
ALL_TAB_COLS HISTOGRAM
QUALIFIED_COL_NAME
ALL_TAB_COLUMNS HISTOGRAM
ALL_TAB_MODIFICATIONS DROP_SEGMENTS
ALL_TABLES DROPPED
DBA_ALL_TABLES DROPPED
DBA_APPLY PRECOMMIT_HANDLER
MAX_APPLIED_MESSAGE_NUMBER
NEGATIVE_RULE_SET_NAME
NEGATIVE_RULE_SET_OWNER
STATUS_CHANGE_TIME
ERROR_NUMBER
ERROR_MESSAGE
DBA_APPLY_DML_HANDLERS APPLY_NAME
DBA_APPLY_PROGRESS SOURCE_DATABASE
DBA_AUDIT_EXISTS EXTENDED_TIMESTAMP
PROXY_SESSIONID
GLOBAL_UID
INSTANCE_NUMBER
OS_PROCESS
TRANSACTIONID
SCN
SQL_BIND
SQL_TEXT
DBA_AUDIT_OBJECT EXTENDED_TIMESTAMP
PROXY_SESSIONID
GLOBAL_UID
INSTANCE_NUMBER
OS_PROCESS
TRANSACTIONID
SCN
SQL_BIND
SQL_TEXT
DBA_AUDIT_POLICIES SEL
INS
UPD
DEL
AUDIT_TRAIL
POLICY_COLUMN_OPTIONS
DBA_AUDIT_SESSION EXTENDED_TIMESTAMP
PROXY_SESSIONID
GLOBAL_UID
INSTANCE_NUMBER
OS_PROCESS
DBA_AUDIT_STATEMENT EXTENDED_TIMESTAMP
PROXY_SESSIONID
GLOBAL_UID
INSTANCE_NUMBER
OS_PROCESS
TRANSACTIONID
SCN
SQL_BIND
SQL_TEXT
(segue)
GUIDA AL DIZIONARIO DATI DI ORACLE 693
Tabella 42.2 Nuove colonne del dizionario dati introdotte in Oracle Database 10g. (continua)
VISTA DEL DIZIONARIO DATI STATICA NUOVE COLONNE
DBA_AUDIT_TRAIL EXTENDED_TIMESTAMP
PROXY_SESSIONID
GLOBAL_UID
INSTANCE_NUMBER
OS_PROCESS
TRANSACTIONID
SCN
SQL_BIND
SQL_TEXT
DBA_AW_PS MAXPAGES
DBA_CAPTURE CAPTURE_USER
USE_DATABASE_LINK
FIRST_SCN
SOURCE_DATABASE
SOURCE_DBID
SOURCE_RESETLOGS_SCN
SOURCE_RESETLOGS_TIME
LOGMINER_ID
NEGATIVE_RULE_SET_NAME
NEGATIVE_RULE_SET_OWNER
MAX_CHECKPOINT_SCN
REQUIRED_CHECKPOINT_SCN
LOGFILE_ASSIGNMENT
STATUS_CHANGE_TIME
ERROR_NUMBER
ERROR_MESSAGE
VERSION
CAPTURE_TYPE
DBA_DIM_ATTRIBUTES ATTRIBUTE_NAME
DBA_ERRORS ATTRIBUTE
MESSAGE_NUMBER
DBA_EXTERNAL_TABLES PROPERTY
DBA_FGA_AUDIT_TRAIL STATEMENT_TYPE
EXTENDED_TIMESTAMP
PROXY_SESSIONID
GLOBAL_UID
INSTANCE_NUMBER
OS_PROCESS
TRANSACTIONID
STATEMENTID
ENTRYID
DBA_INDEXES IOT_REDUNDANT_PKEY_ELIM
DROPPED
DBA_INDEXTYPES ARRAY_DML
DBA_LOBS TABLESPACE_NAME
FORMAT
PARTITIONED
DBA_LOG_GROUP_COLUMNS LOGGING_PROPERTY
DBA_LOG_GROUPS LOG_GROUP_TYPE
GENERATED
DBA_LOGSTDBY_LOG APPLIED
DBA_LOGSTDBY_PROGRESS APPLIED_THREAD#
APPLIED_SEQUENCE#
READ_THREAD#
READ_SEQUENCE#
NEWEST_THREAD#
NEWEST_SEQUENCE#
DBA_LOGSTDBY_SKIP USE_LIKE
ESC
(segue)
694 CAPITOLO 42
Tabella 42.2 Nuove colonne del dizionario dati introdotte in Oracle Database 10g. (continua)
VISTA DEL DIZIONARIO DATI STATICA NUOVE COLONNE
DBA_LOGSTDBY_UNSUPPORTED ATTRIBUTES
TPROP
SEGSPARE1
TFLAGS
DBA_MVIEWS UNKNOWN_TRUSTED_FD
STALE_SINCE
DBA_OBJ_AUDIT_OPTS FBK
DBA_OBJECT_TABLES DROPPED
DBA_OUTLINES COMPATIBLE
ENABLED
FORMAT
DBA_PART_COL_STATISTICS HISTOGRAM
DBA_POLICIES IDX
POLICY_TYPE
LONG_PREDICATE
DBA_PROPAGATION NEGATIVE_RULE_SET_OWNER
NEGATIVE_RULE_SET_NAME
DBA_PROXIES AUTHENTICATION
DBA_REGISTRY NAMESPACE
DBA_REGISTRY_HIERARCHY NAMESPACE
DBA_RSRC_PLAN_DIRECTIVES MAX_IDLE_TIME
MAX_IDLE_BLOCKER_TIME
SWITCH_TIME_IN_CALL
DBA_SUBPART_COL_STATISTICS HISTOGRAM
DBA_SUBSCRIBED_COLUMNS SUBSCRIPTION_NAME
DBA_SUBSCRIBED_TABLES SUBSCRIPTION_NAME
DBA_SUBSCRIPTIONS SUBSCRIPTION_NAME
DBA_TAB_COL_STATISTICS HISTOGRAM
DBA_TAB_COLS HISTOGRAM
QUALIFIED_COL_NAME
DBA_TAB_COLUMNS HISTOGRAM
DBA_TAB_MODIFICATIONS DROP_SEGMENTS
DBA_TABLES DROPPED
DBA_TABLESPACES RETENTION
BIGFILE
USER_ALL_TABLES DROPPED
USER_AUDIT_OBJECT EXTENDED_TIMESTAMP
PROXY_SESSIONID
GLOBAL_UID
INSTANCE_NUMBER
OS_PROCESS
TRANSACTIONID
SCN
SQL_BIND
SQL_TEXT
USER_AUDIT_POLICIES SEL
INS
UPD
DEL
AUDIT_TRAIL
POLICY_COLUMN_OPTIONS
USER_AUDIT_SESSION EXTENDED_TIMESTAMP
PROXY_SESSIONID
GLOBAL_UID
INSTANCE_NUMBER
OS_PROCESS
(segue)
GUIDA AL DIZIONARIO DATI DI ORACLE 695
Tabella 42.2 Nuove colonne del dizionario dati introdotte in Oracle Database 10g. (continua)
VISTA DEL DIZIONARIO DATI STATICA NUOVE COLONNE
USER_AUDIT_STATEMENT EXTENDED_TIMESTAMP
PROXY_SESSIONID
GLOBAL_UID
INSTANCE_NUMBER
OS_PROCESS
TRANSACTIONID
SCN
SQL_BIND
SQL_TEXT
USER_AUDIT_TRAIL EXTENDED_TIMESTAMP
PROXY_SESSIONID
GLOBAL_UID
INSTANCE_NUMBER
OS_PROCESS
TRANSACTIONID
SCN
SQL_BIND
SQL_TEXT
USER_AW_PS MAXPAGES
USER_DIM_ATTRIBUTES ATTRIBUTE_NAME
USER_ERRORS ATTRIBUTE
MESSAGE_NUMBER
USER_EXTERNAL_TABLES PROPERTY
USER_INDEXES IOT_REDUNDANT_PKEY_ELIM
DROPPED
USER_INDEXTYPES ARRAY_DML
USER_LOBS TABLESPACE_NAME
FORMAT
PARTITIONED
USER_LOG_GROUP_COLUMNS LOGGING_PROPERTY
USER_LOG_GROUPS LOG_GROUP_TYPE
GENERATED
USER_MVIEWS UNKNOWN_TRUSTED_FD
STALE_SINCE
USER_OBJ_AUDIT_OPTS FBK
USER_OBJECT_TABLES DROPPED
USER_OUTLINES COMPATIBLE
ENABLED
FORMAT
USER_PART_COL_STATISTICS HISTOGRAM
USER_POLICIES IDX
POLICY_TYPE
LONG_PREDICATE
USER_PROXIES AUTHENTICATION
USER_PUBLISHED_COLUMNS CHANGE_SET_NAME
PUB_ID
USER_REGISTRY NAMESPACE
USER_SUBPART_COL_STATISTICS HISTOGRAM
USER_SUBSCRIBED_COLUMNS SUBSCRIPTION_NAME
USER_SUBSCRIBED_TABLES SUBSCRIPTION_NAME
USER_SUBSCRIPTIONS SUBSCRIPTION_NAME
USER_TAB_COL_STATISTICS HISTOGRAM
USER_TAB_COLS HISTOGRAM
QUALIFIED_COL_NAME
(segue)
696 CAPITOLO 42
Tabella 42.2 Nuove colonne del dizionario dati introdotte in Oracle Database 10g. (continua)
VISTA DEL DIZIONARIO DATI STATICA NUOVE COLONNE
USER_TAB_COLUMNS HISTOGRAM
USER_TAB_MODIFICATIONS DROP_SEGMENTS
USER_TABLES DROPPED
USER_TABLESPACES RETENTION
BIGFILE
TABLE_NAME COMMENTS
------------------------- -----------------------------------
ALL_BASE_TABLE_MVIEWS All materialized views with log(s)
in the database that the user can
see
ALL_MVIEWS All materialized views in the
database
ALL_REGISTERED_MVIEWS Remote materialized views of local
tables that the user can see
ALL_VIEWS Description of views accessible to
the user
ALL_XML_VIEWS Description of all XMLType
views that the user has privileges
on
USER_BASE_TABLE_MVIEWS All materialized views with log(s)
owned by the user in the database
USER_MVIEWS All materialized views in the
database
USER_REGISTERED_MVIEWS Remote materialized views of local
tables currently using logs owned
by the user
USER_VIEWS Description of the user's own views
USER_XML_VIEWS Description of the user's own
XMLType views
GUIDA AL DIZIONARIO DATI DI ORACLE 697
È possibile eseguire una query sulle colonne delle viste del dizionario tramite la vista
DICT_COLUMNS. Come la vista DICTIONARY, anche DICT_COLUMNS visualizza i com-
menti inseriti nel database per le viste del dizionario dati. DICT_COLUMNS ha tre colonne:
Table_Name, Column_Name e Comments. Con una query su DICT_COLUMNS è possibile
determinare quali viste del dizionario dati sono più utili per le proprie esigenze.
Per esempio, se si desidera visualizzare le informazioni relative all’uso e all’allocazione
dello spazio per gli oggetti del database, ma non si conosce con esattezza quali viste del diziona-
rio dati memorizzino queste informazioni, è possibile eseguire una query su DICT_COLUMNS,
come mostrato nell’esempio seguente, che cerca tutte le tabelle del dizionario che possiedono
una colonna di nome Blocchi:
select Table_Name
from DICT_COLUMNS
where Column_Name = 'BLOCKS'
and Table_Name like 'USER%'
order by Table_Name;
TABLE_NAME
--------------------
USER_ALL_TABLES
USER_EXTENTS
USER_FREE_SPACE
USER_OBJECT_TABLES
USER_SEGMENTS
USER_TABLES
USER_TAB_PARTITIONS
USER_TAB_STATISTICS
USER_TAB_SUBPARTITIONS
USER_TS_QUOTAS
Per elencare tutti i nomi delle colonne disponibili che possono essere stati utilizzati nel-
l’esempio precedente, occorre effettuare una query su DICT_COLUMNS:
Ogni volta che non si sa con sicurezza dove trovare i dati desiderati, è sufficiente consultare
DICTIONARY e DICT_COLUMNS. Se si scopre che molte viste potrebbero essere utili, occor-
re effettuare una query su DICTIONARY (come nel primo esempio) per visualizzare i commenti
relativi a ciascuna vista.
Il riferimento alla vista USER_CATALOG può avvenire anche tramite il sinonimo pubblico
CAT.
Esistono altri due cataloghi. ALL_CATALOG elenca tutto quello che è contenuto nella vista
USER_CATALOG, più qualunque oggetto per il quale sia stato concesso l’accesso all’utente o
al pubblico (PUBLIC). DBA_CATALOG è una versione a livello di DBA del catalogo in cui
sono visualizzate tutte le tabelle, le viste, le sequenze e i sinonimi presenti nel database. Oltre
alle colonne Table_Name e Table_Type, visualizzate nella query di USER_CATALOG, ALL_CA-
TALOG e DBA_CATALOG includono una colonna Owner.
NOTA Se si ricreano oggetti con qualsiasi metodo, per esempio tramite l’utility
Import, i relativi valori di Created cambieranno, indicando la data di ultima creazione.
Sono disponibili altri due elenchi di oggetti. ALL_OBJECTS elenca tutto ciò che si trova
nella vista USER_OBJECTS oltre agli oggetti per i quali è stato concesso l’accesso all’utente o
al pubblico (PUBLIC). DBA_OBJECTS è una versione a livello di DBA dell’elenco di oggetti,
che visualizza tutti gli oggetti del database. Oltre alle colonne mostrate nella vista USER_
OBJECTS, ALL_OBJECTS e DBA_OBJECTS comprendono una colonna Owner.
Last_DDL_Time Data dell’ultimo comando DDL utilizzato sull’oggetto, compresi alter, grant e revoke.
Timestamp Data di creazione degli oggetti (uguale a Created, ma memorizzata come una colonna alfanumerica).
Generated Flag che indica se il nome dell’oggetto è stato generato dal sistema.
Secondary Flag che indica se l’oggetto è un indice secondario creato da un indice di dominio.
Con una query sulla colonna Table_Name di USER_TABLES vengono visualizzati i nomi
di tutte le tabelle nell’account corrente. Nella query seguente, sono elencate tutte le tabelle i cui
nomi iniziano con a lettera L:
700 CAPITOLO 42
Freelist_Groups Compression
La vista ALL_TABLES mostra tutte le tabelle di proprietà dell’utente e quelle per le quali
gli è stato concesso l’accesso (direttamente o tramite concessioni a PUBLIC). La maggior parte
degli strumenti di generazione di report esterni, che elencano le tabelle disponibili per le query,
ottiene tale elenco con una query su ALL_TABLES. Dato che questa vista è in grado di contene-
re voci per più utenti, contiene, oltre alle colonne elencate in precedenza, una colonna Owner.
DBA_TABLES, che elenca tutte le tabelle del database, ha le stesse definizioni delle colonne di
ALL_TABLES.
Le colonne Degree e Instances in USER_TABLES fanno riferimento a come viene effettua-
ta la query sulla tabella durante le query parallele. Per ulteriori informazioni su Degree, Instances
e gli altri parametri delle tabelle, si consulti la voce CREATE TABLE nel Capitolo 48.
A partire da Oracle Database 10g, USER_TABLES e altre viste del dizionario dati contengono
una nuova colonna denominata Dropped, che conterrà il valore ‘YES' o ‘NO'; fare riferimento
alle informazioni relative al cestino per informazioni sulle descrizioni degli oggetti eliminati.
COLUMN_NAME DATA_TYPE
------------- ---------
ARGOMENTO VARCHAR2
SEZIONE CHAR
PAGINA NUMBER
determinare la distribuzione dei valori delle colonne all’interno della tabella. Sono disponibili
anche le versioni “ALL” e “DBA” di USER_TAB_HISTOGRAMS.
Colonne aggiornabili
È possibile aggiornare i record di viste che contengono join nelle loro query, purché i join sod-
disfino alcuni criteri. La vista USER_UPDATABLE_COLUMNS elenca tutte le colonne che è
possibile aggiornare. È possibile effettuare una query su Owner, Table_Name e Column_Name
per la colonna; la colonna Updatable avrà il valore YES se può essere aggiornata e il valore NO
in caso contrario. Inoltre, è possibile eseguire una query per determinare se sia consentito inse-
rire o eliminare record dalla vista tramite le colonne Insertable e Deletable.
Viste: USER_VIEWS
Alla query base di una vista è possibile accedere tramite la vista del dizionario dati USER_VIEWS,
che contiene dieci colonne; le tre colonne principali sono:
Le altre colonne, descritte più avanti in questo paragrafo, sono correlate alle viste oggetto.
NOTA Questo paragrafo vale soltanto per le viste tradizionali. Per le viste
materializzate, si rimanda al paragrafo “Database link e viste materializzate”, più avanti in
questo capitolo.
La colonna Text è di tipo LONG. Ciò può rappresentare un problema quando si effettua una
query su USER_VIEWS mediante SQL*Plus, poiché SQL*Plus tronca i tipi di dati LONG.
Tuttavia, esiste la possibilità di modificare il punto in cui avviene il troncamento con il comando
set long. USER_VIEWS mette a disposizione un meccanismo per stabilire l’impostazione adat-
ta del punto di troncamento dei dati LONG, come descritto nell’esempio seguente.
La colonna Text_Length visualizza la lunghezza della query della vista. Pertanto, il punto di
troncamento dei dati LONG in SQL*Plus dev’essere impostato a un valore uguale o maggiore
del valore Text_Length della vista. Per esempio, nel listato seguente è mostrata una vista il cui
nome è AGING e la cui Text_Length è pari a 355.
View_Name Text_Length
---------------- -------------
AGING 355
Dato che la lunghezza del testo della vista è pari a 355 caratteri, per incrementare il punto di
troncamento dei LONG almeno a 355 (il valore predefinito è 80) occorre il comando set long, in
modo da visualizzare il testo intero della query della vista:
È possibile eseguire una query su USER_VIEWS per il testo della vista, con la query ripor-
tata nel listato seguente:
select Text
from USER_VIEWS
where View_Name = ‘AGING’;
Se non si fosse utilizzato il comando set long, l’output sarebbe stato troncato a 80 caratteri,
senza che alcun messaggio avvertisse del fatto. Prima di effettuare query su altre viste, è neces-
sario controllare nuovamente i rispettivi valori di Text_Length.
Se nelle viste si utilizzano alias per le colonne, e questi fanno parte della query della vista, le
query sul dizionario dati per informazioni sulle viste risultano semplificate. Dato che in
USER_VIEWS viene visualizzato il testo interno della query sulla vista, sono visualizzati anche
gli alias per le colonne.
Con questo formato si possono creare delle viste:
Elencando i nomi delle colonne nell’intestazione del comando create view si rimuovono gli
alias delle colonne dalle query, evitando così che vengano visualizzati mediante USER_VIEWS.
L’unico modo per visualizzare i nomi delle colonne della vista consisterebbe nell’effettuare una
query su USER_TAB_COLUMNS. Se i nomi delle colonne si trovano nella query, è sufficiente
eseguire una query su una vista del dizionario dati (USER_VIEWS), sia per la query sia per i
nomi delle colonne.
Per esempio, con la vista RIVISTA_VISTA creata nell’ultimo esempio, eseguendo una query
su USER_VIEWS si visualizzerebbe:
select Text
from USER_VIEWS
where View_Name =’RIVISTA_VISTA’;
TEXT
---------------------------------------
select Articolo, Sezione from RIVISTA
Questa query non mostra i nuovi nomi assegnati alle colonne, in quanto tali nomi non sono
stati inseriti nella query sulla vista. Per visualizzare questi nomi di colonna in USER_VIEWS, è
necessario aggiungerli come alias di colonna alla query della vista:
Ora, quando si esegue una query su USER_VIEWS, gli alias di colonna vengono visualizzati
come parte del testo della query sulla vista:
select Text
704 CAPITOLO 42
from USER_VIEWS
where View_Name =’RIVISTA_VISTA’;
TEXT
-----------------------------------------------
select Articolo AlcuniArticoli, Sezione AlcuneSezioni
from RIVISTA
Cycle_Flag Un flag per indicare se il valore deve ritornare a Min_Value una volta raggiunto Max_Value.
lo spazio libero nella tablespace dalla quale sono stati eliminati. I DBA possono vedere tutti gli
oggetti presenti nei cestini di tutti gli utenti tramite la vista DBA_RECYCLEBIN. Non esiste
una versione “ALL” per questa vista. Fare riferimento alla voce relativa al comando purge per
dettagli sulla rimozione degli oggetti dal cestino.
Vincoli: USER_CONSTRAINTS
Le informazioni sui vincoli sono accessibili tramite la vista USER_CONSTRAINTS. Tali infor-
mazioni sono molto utili quando si cerca di modificare i vincoli dei dati o di risolvere problemi
con i dati di un’applicazione. Le colonne di questa vista sono elencate nella Tabella 42.5.
Anche se si tratta di una vista “USER”, essa contiene ugualmente una colonna Owner. In
questa vista, Owner si riferisce al proprietario del vincolo e non al proprietario della tabella (che
è l’utente).
I valori validi per la colonna Constraint_Type sono descritti nella Tabella 42.5. La compren-
sione dei tipi di vincoli è fondamentale quando si cerca di ottenere delle informazioni utili sui
vincoli stessi.
I vincoli FOREIGN KEY hanno sempre valori per le colonne R_Owner e
R_Constraint_Name. Queste due colonne specificano il vincolo cui fa riferimento FOREIGN
KEY. FOREIGN KEY fa riferimento a un altro vincolo e non a un’altra colonna. I vincoli NOT
NULL sulle colonne sono memorizzati come CHECK, pertanto dispongono di un valore
Constraint_Type uguale a ‘C’.
Con una query su USER_CONSTRAINTS si ottengono i nomi di tutti i vincoli su una
colonna. Ciò è molto importante quando si cerca di interpretare i messaggi di errore che forni-
scono solamente il nome del vincolo violato.
Non appena si conosce il nome e il tipo di un vincolo, è possibile verificare le colonne a esso
associate tramite la vista USER_CONS_COLUMNS, descritta nel prossimo paragrafo.
Se non si assegnano ai vincoli dei nomi mentre li si crea, Oracle genererà nomi di vincoli
unici. Per ulteriori informazioni, si rimanda al paragrafo “Vincoli di integrità” nel Capitolo 48.
Se il nome di un vincolo è stato generato dal sistema, ciò viene indicato nella colonna Generated.
Se si differisce un vincolo (come indicato dalla colonna Deferred), il vincolo in questione
non verrà imposto durante la transazione. Per esempio, se si effettuassero aggiornamenti su
vasta scala di tabelle correlate e non fosse possibile garantire l’ordine delle transazioni, si po-
trebbero differire i controlli eseguiti dai vincoli sulle tabelle sino al completamento di tutti gli
aggiornamenti.
ALL_CONSTRAINTS elenca i vincoli su tutte le tabelle cui l’utente o PUBLIC sono in
grado di accedere. DBA_CONSTRAINTS elenca tutti i vincoli del database. Ciascuna di queste
viste ha lo stesso gruppo di colonne di USER_CONSTRAINTS (dal momento che contengono
tutte la colonna Owner).
GUIDA AL DIZIONARIO DATI DI ORACLE 707
Delete_Rule Azione da intraprendere sulle tabelle FOREIGN KEY quando viene eliminato un record PRIMARY KEY
(‘CASCADE’ o ‘NO ACTION’).
Validated Flag (‘VALIDATED’ o ‘NOT VALIDATED’) che indica se tutti i dati obbediscono al vincolo.
Generated Flag che indica se il nome del vincolo è stato generato dal database.
Bad Flag che indica se nella creazione del vincolo è stata utilizzata una data senza specificare un valore di
secolo per i vincoli CHECK, il che produce anni a due cifre ambigui; si applica solo a vincoli contenuti in
database aggiornati da precedenti versioni di ORACLE. Tali vincoli possono causare errori ORA-02436
se non eliminati e ricreati correttamente.
Sono solo due le colonne contenute in questa vista che non si trovano anche in
USER_CONSTRAINTS: Column_Name e Position. Nel listato seguente è riportata una query
di esempio su questa tabella:
COLUMN_NAME POSITION
------------ --------
NOME 1
COGNOME 2
Come mostrato nel listato precedente, la combinazione di Nome e Cognome forma il vinco-
lo (in questo caso, una chiave primaria).
La colonna Position è significativa. Quando si crea un vincolo UNIQUE o PRIMARY KEY,
Oracle crea automaticamente un indice unico sulla serie di colonne specificate. L’indice viene
creato in base all’ordine delle colonne specificato. A sua volta, l’ordine delle colonne influisce
sulle prestazioni dell’indice. Un indice che comprende più colonne può essere utilizzato nel
modo più efficiente se la sua colonna principale (Position=1) viene utilizzata nella clausola
where della query. Per ulteriori informazioni sull’ottimizzatore, si rimanda al Capitolo 43.
Le viste ALL_CONS_COLUMNS e DBA_CONS_COLUMNS hanno le stesse definizioni
delle colonne di USER_CONS_COLUMNS. ALL_CONS_COLUMNS può essere utilizzata per
visualizzare informazioni delle colonne relative ai vincoli su tutte le tabelle cui l’utente può
accedere, a prescindere dal proprietario. DBA_CONS_COLUMNS elenca le informazioni sui
vincoli a livello di colonna per l’intero database.
La creazione del vincolo non è riuscita e nella tabella EXCEPTIONS viene inserito un rife-
rimento a tutte le righe che hanno violato il vincolo. Per esempio, se il vincolo PRIMARY KEY
dell’ultimo esempio avesse generato delle eccezioni, sarebbe stato possibile effettuare una query
sulla tabella EXCEPTIONS, come mostrato nel listato seguente:
Due righe hanno violato il vincolo chiamato SYS_C00516 (che, in questo esempio, è il
nome assegnato al vincolo PRIMARY KEY per la tabella RIVISTA). È possibile stabilire quali
righe della tabella RIVISTA corrispondono a queste eccezioni unendo tramite join la colonna
Row_ID della tabella EXCEPTIONS alla pseudocolonna ROWID della tabella in cui è stato
collocato il vincolo (in questo esempio, la tabella RIVISTA):
select *
from RIVISTA
where RowID in
(select Row_ID from EXCEPTIONS);
NOTA Row_ID è una vera colonna nella tabella EXCEPTIONS, con un tipo di
dati ROWID. Viene unita tramite join alla pseudocolonna ROWID nella tabella da cui sono state
generate le eccezioni.
Per aggiungere un commento a una tabella, occorre utilizzare il comando comment come
nel listato seguente:
select Comments
from USER_TAB_COMMENTS
where Table_Name = 'COMPLEANNO';
COMMENTI
-------------------------------------
Date di compleanno degli impiegati di Blacksburg
Per rimuovere un commento, è sufficiente impostare il commento a due apici che non rac-
chiudono alcuno spazio:
Per visualizzare i commenti di tutte le tabelle cui è possibile accedere, si utilizza la vista
ALL_TAB_COMMENTS. Questa vista ha una colonna Owner aggiuntiva, che specifica il pro-
prietario della tabella. DBA_TAB_COMMENTS elenca tutte le tabelle nel database e possiede
anch’essa una colonna Owner.
Per aggiungere un commento a una colonna, si utilizza il comando comment come mostrato
nel listato seguente:
select Comments
from USER_COL_COMMENTS
where Table_Name = 'COMPLEANNO'
and Column_Name = 'ETA';
Per rimuovere un commento, è sufficiente impostare il commento a due apici che non rac-
chiudono alcuno spazio:
Per visualizzare i commenti di colonna su tutte le tabelle cui è possibile accedere, si utilizza
la vista ALL_COL_COMMENTS. Questa vista contiene una colonna Owner aggiuntiva, che
specifica il proprietario della tabella. DBA_COL_COMMENTS elenca tutte le colonne di tutte
le tabelle nel database e possiede anch’essa una colonna Owner.
Prefix_Length Dropped
Secondary
Ityp_Owner
Ityp_Name
INDEX_NAME UNIQUENESS
---------------- ----------
PK_COMPLEANNO UNIQUE
Descend Un flag Y/N per indicare se la colonna è o meno ordinata in ordine decrescente.
COLUMN_NAME POS
------------ ---
NOME 1
COGNOME 2
Come si può vedere dalla query, l’indice PK_COMPLEANNO è costituito da due colonne:
nell’ordine, Nome e Cognome. Per dettagli sul modo in cui l’ottimizzatore utilizza gli indici a
più colonne, si rimanda al Capitolo 43.
ALL_IND_COLUMNS può essere utilizzata per visualizzare informazioni di colonna rela-
tive agli indici su tutte le tabelle cui l’utente può accedere, a prescindere dal proprietario. La
vista DBA_IND_COLUMNS contiene le informazioni sugli indici a livello di colonna per l’in-
tero database.
Key_Size Buffer_Pool
Ini_Trans Single_Table
Max_Trans Dependencies
Initial_Extent
Next_Extent
Min_Extents
Max_Extents
Pct_Increase
Freelists
Freelist_Groups
GUIDA AL DIZIONARIO DATI DI ORACLE 715
Dato che un singolo cluster è in grado di memorizzare dati provenienti da più tabelle, la
vista USER_CLU_COLUMNS è utile per stabilire quali colonne di quali tabelle corrispondono
alle colonne del cluster.
Non esiste una versione “ALL” per questa vista. Esistono solamente USER_CLU_COLUMNS
per le colonne del cluster dell’utente e DBA_CLU_COLUMNS, che visualizza le corrisponden-
ze delle colonne per tutti i cluster del database.
select Type_Name,
Attributes,
Methods
from USER_TYPES
where Type_Name = 'ANIMALE_TY';
select Attr_Name,
Length,
Attr_Type_Name
from USER_TYPE_ATTRS
where Type_Name = ‘PERSONA_TY’;
716 CAPITOLO 42
select Parameters,
Results
from USER_TYPE_METHODS
where Type_Name = ‘ANIMALE_TY’
and Method_Name = ‘ETA’;
PARAMETERS RESULTS
---------- ----------
2 1
Attr_Type_Owner Proprietario del tipo dell’attributo, se l’attributo stesso è basato su un altro tipo di dati.
Come mai ETA ha due parametri quando è stato definito un solo parametro di input? Per
scoprirlo, è possibile eseguire una query su USER_METHOD_PARAMS, che descrive i para-
metri relativi ai metodi:
USER_METHOD_PARAMS mostra che per ogni metodo Oracle crea un parametro impli-
cito “SELF”. I risultati dei metodi sono visualizzati in USER_METHOD_RESULTS:
select Method_Name,
Result_Type_Name
from USER_METHOD_RESULTS
where Type_Name = ‘ANIMALE_TY’;
METHOD_NAME RESULT_TYPE_NAME
------------------------------ ----------------------------
ETA NUMBER
LOB: USER_LOBS
Come descritto nel Capitolo 35, all’interno del database è possibile memorizzare oggetti di grandi
dimensioni (LOB, Large Objects). La vista USER_LOBS fornisce informazioni sui LOB defini-
ti nelle tabelle, come mostrato nel listato seguente:
select Table_Name,
Column_Name
from USER_LOBS;
718 CAPITOLO 42
TABLE_NAME COLUMN_NAME
------------------------------ ----------------------------
PROPOSTA TESTO_PROPOSTA
PROPOSTA BUDGET
USER_LOBS visualizza anche i nomi dei segmenti utilizzati per contenere i dati LOB quando
questi aumentano; essa tuttavia non visualizza i tipi di dati delle colonne LOB. Per visualizzare
i tipi di dati LOB, è possibile descrivere la tabella che contiene quei LOB oppure eseguire una
query su USER_TAB_COLUMNS (come mostrato in precedenza).
Per utilizzare i tipi di dati BFILE per i LOB, è necessario creare delle directory (si rimanda
alla voce del comando create directory nel Capitolo 48). Il dizionario dati ALL_DIRECTORIES
visualizza i valori delle colonne Owner, Directory_Name e Directory_Path per ogni directory
cui è stato concesso l’accesso. Per questa vista è disponibile anche una versione “DBA”, mentre
non esiste la versione “USER”.
'HQ';
dal momento che è possibile che esistano voci con valore di Host uguale a ‘hq’ invece di ‘HQ’.
La vista ALL_DB_LINKS elenca tutti i database link che sono di proprietà dell’utente o
PUBLIC. DBA_DB_LINKS elenca tutti i link nel database. Moltissime definizioni delle colon-
GUIDA AL DIZIONARIO DATI DI ORACLE 719
Viste materializzate
Per visualizzare informazioni relative alle viste materializzate possedute dal proprio account, è
possibile eseguire una query su USER_MVIEWS. Questa vista, le cui colonne sono elencate
nella Tabella 42.9, mostra le informazioni strutturali sulla vista materializzata complete dei rela-
tivi intervalli di aggiornamento.
select Master_Link
from USER_MVIEWS;
I nomi dei database link restituiti da questa query possono essere utilizzati come input per
query eseguite su USER_DB_LINKS. Questa query visualizza tutte le informazioni disponibili
sui database link utilizzati nelle viste materializzate:
select *
from USER_DB_LINKS
where DB_Link in
(select Master_Link
from USER_MVIEWS);
Nel Capitolo 24 sono descritte altre query utili per la gestione delle viste materializzate.
Le viste ALL_MVIEWS e DBA_MVIEWS hanno le stesse definizioni delle colonne di
USER_MVIEWS. ALL_MVIEWS può essere utilizzata per visualizzare informazioni su tutte le
viste materializzate cui l’utente può accedere, a prescindere dal proprietario. DBA_MVIEWS
elenca informazioni sulle viste materializzate per tutti gli utenti del database.
Due viste correlate, USER_REFRESH e USER_REFRESH_CHILDREN, visualizzano in-
formazioni sui gruppi di aggiornamento. USER_MVIEW_REFRESH_TIMES mostra la data
dell’ultimo aggiornamento per ogni vista materializzata. A partire da Oracle Database 10g è
possibile accedere ai commenti sulle viste materializzate tramite USER_MVIEW_COMMENTS
ed eseguire una query per conoscere i dettagli di riscrittura tramite USER_REWRITE_
EQUIVALENCES.
Container_Name La tabella di base (nel database locale) per i dati della vista materializzata; per i db precedenti a Oracle8i,
corrisponde a Mview_Name preceduto da “SNAP$_”.
Update_Log Nome della tabella che registra le modifiche apportate a una vista materializzata aggiornabile.
Master_Rollback_Seg Il segmento di rollback da usare durante la popolazione della vista materializzata e le operazioni di ag-
giornamento.
Rewrite_Enabled Flag Y/N che indica se la riscrittura della query è abilitata per la vista.
Refresh_Mode DEMAND, COMMIT o NEVER, in relazione alla modalità di aggiornamento per la vista.
Refresh_Method Valori usati per guidare un aggiornamento rapido della vista (Complete, Fast, Never o Force).
Build_Mode Istanziamento IMMEDIATE, DEFERRED o PREBUILT dei dati della vista materializzata durante la sua
creazione.
Last_Refresh_Date Indicatore orario che registra l’ora dell’ultimo aggiornamento dei dati della vista materializzata.
Staleness Stato dei dati della vista materializzata in relazione alle loro tabelle master.
Use_No_Index Flag Y/N che indica se la vista materializzata è stata creata con la clausola USING NO INDEX.
del proprietario della tabella base (Mview_Table_Owner). Molte colonne di questa vista sono
dei flag, come Summary (Y se la vista contiene un’aggregazione), Known_Stale (Y se i dati
della vista sono incoerenti rispetto alla tabella base) e Contains_Views (Y se la vista materializzata
fa riferimento a una vista).
Se la vista materializzata contiene delle aggregazioni, è possibile eseguire una query su
USER_MVIEW_AGGREGATES per ottenere i dettagli relativi alle aggregazioni. Le colonne di
questa vista sono:
GUIDA AL DIZIONARIO DATI DI ORACLE 721
Measure Testo SQL della misura, che esclude però la funzione di aggregazione.
È possibile eseguire una query sui dettagli delle relazioni all’interno delle viste materializzate
partendo dalle viste del dizionario dati USER_MVIEW_DETAIL_RELATIONS e
USER_MVIEW_KEYS. Se la vista materializzata si basa sui join, per i dettagli sui join si ana-
lizzi USER_MVIEW_JOINS. In generale, USER_MVIEW_ANALYSIS è la vista del diziona-
rio dati più utilizzata per quanto riguarda le viste materializzate.
Trigger: USER_TRIGGERS
USER_TRIGGERS contiene informazioni riguardanti i trigger posseduti dal proprio account.
Questa vista, le cui colonne sono elencate nella Tabella 42.10, visualizza il tipo e il corpo del
trigger.
722 CAPITOLO 42
Trigger_Type Tipo del trigger (‘BEFORE STATEMENT’, ‘BEFORE EACH ROW’ e così via).
Base_Object_Type Tipo dell’oggetto sul quale si basa il trigger (TABLE, VIEW, SCHEMA o DATABASE).
Column_Name Per i trigger delle tabelle annidate, il nome della colonna che contiene la tabella annidata.
Referencing_Names Nomi utilizzati per fare riferimento a valori OLD e NEW nel trigger.
La vista ALL_TRIGGERS elenca i trigger per tutte le tabelle cui l’utente ha accesso.
DBA_TRIGGERS elenca tutti i trigger nel database. Entrambe le viste contengono una colonna
aggiuntiva, Owner, che registra il proprietario del trigger.
Una seconda vista del dizionario dati relativa ai trigger, USER_TRIGGER_COLS, mostra
in che modo un trigger utilizza le colonne. La vista elenca il nome di ciascuna colonna su cui
agisce un trigger, e l’uso del trigger stesso. Come per USER_TRIGGERS, anche per questa vista
del dizionario dati sono disponibili le versioni “ALL” e “DBA”.
select Text
from USER_SOURCE
where Name = '&procedure_name'
GUIDA AL DIZIONARIO DATI DI ORACLE 723
NOTA La sequenza delle linee viene mantenuta dalla colonna Line, ed è proprio
per questo motivo che la colonna Line dovrebbe essere utilizzata nella clausola order by.
Type Tipo di oggetto (‘PROCEDURE’, ‘FUNCTION’, ‘PACKAGE’, ‘PACKAGE BODY’, ‘TRIGGER’, ‘TYPE’, ‘TYPE
BODY’, ‘VIEW', ‘JAVA CLASS' o ‘JAVA SOURCE’).
Sequence Numero di sequenza della linea, da usare nella clausola order by della query.
Line Numero di linea all’interno del codice sorgente in cui si è verificato l’errore.
Attribute Flag che indica se la riga selezionata è un errore (‘ERROR') o un avvertimento (‘WARNING').
Le query eseguite su questa vista dovrebbero includere sempre la colonna Sequence nella
clausola order by. Per questa vista sono disponibili anche le versioni “ALL” e “DBA”, che pos-
siedono una colonna in più, Owner, che registra il proprietario dell’oggetto.
listato seguente, le quattro aree dimensionali separate possono essere sommate per determinare
lo spazio totale utilizzato nelle tabelle del dizionario dati SYSTEM per memorizzare l’oggetto.
Le quattro colonne Size, insieme alle colonne Name e Type, rappresentano tutte le colonne
presenti in questa vista.
Per questa vista esiste anche la versione “DBA”. DBA_OBJECT_SIZE elenca le dimensioni
di tutti gli oggetti contenuti nel database.
42.12 Dimensioni
Esiste la possibilità di creare e gestire dimensioni e gerarchie.
Per visualizzare i nomi delle dimensioni, è possibile eseguire una query sulla colonna
Dimension_Name della vista USER_DIMENSIONS. USER_DIMENSIONS contiene anche
colonne per il proprietario della dimensione (Owner), per lo stato (la colonna Invalid, impostata
a “Y” o “N”) e per il livello di revisione (la colonna Revision). Tramite altre viste del dizionario
dati è possibile accedere agli attributi di una dimensione.
Per visualizzare le gerarchie all’interno di una dimensione, è necessario eseguire una query
su USER_DIM_HIERARCHIES. Questa vista possiede solo tre colonne: Owner,
Dimension_Name e Hierarchy_Name. L’esecuzione di una query su
USER_DIM_HIERARCHIES per la dimensione GEOGRAFIA restituisce il nome delle sue
gerarchie:
select Hierarchy_Name
from USER_DIM_HIERARCHIES;
HIERARCHY_NAME
------------------------------
PAESE_ROLLUP
Per visualizzare i dettagli della gerarchia per PAESE_ROLLUP è sufficiente eseguire una
query su USER_DIM_CHILD_OF, come mostrato nel listato seguente. Il primo comando crea
una dimensione denominata GEOGRAFIA che registra le gerarchie di paesi e continenti.
select Child_Level_Name,
Parent_Level_Name,
Position, Join_Key_Id
GUIDA AL DIZIONARIO DATI DI ORACLE 725
from USER_DIM_CHILD_OF
where Hierarchy_Name= PAESE_ROLLUP';
Per visualizzare la chiave di join di una gerarchia, è necessario eseguire una query su
USER_DIM_JOIN_KEY:
LEVEL_NAME CHILD_JOIN_COLUMN
------------------------------ ------------------------------
ID_CONTINENTE CONTINENTE
I livelli di una dimensione sono visibili se si esegue una query sulla vista del dizionario dati
USER_DIM_LEVELS, mentre le colonne di chiave per i vari livelli sono visibili tramite
USER_DIM_LEVEL_KEY. Tramite USER_DIM_ATTRIBUTES è possibile accedere alle in-
formazioni sugli attributi delle dimensioni.
Per tutte le viste del dizionario dati relative alle dimensioni esistono le viste “ALL” e “DBA”
Dato che le viste “USER” per le dimensioni contengono una colonna Owner, nelle viste “ALL”
e “DBA” corrispondenti non si trovano colonne aggiuntive.
Tablespace: USER_TABLESPACES
È possibile eseguire una query sulla vista del dizionario dati USER_TABLESPACES per stabi-
lire a quali tablespace è stato concesso l’accesso e i parametri di memorizzazione predefiniti di
ciascuna di esse. Questi parametri vengono utilizzati per ciascun oggetto memorizzato all’inter-
no di questa tablespace, a meno che un comando create o alter specifichi per tale oggetto dei
parametri di memorizzazione differenti. Le colonne correlate alla memorizzazione della vista
USER_TABLESPACES, elencate nella Tabella 42.11, sono molto simili alle colonne correlate
alla memorizzazione di USER_TABLES. Per ulteriori informazioni si rimanda alla voce
“Memorizzazione” del Capitolo 48.
Non esiste una versione “ALL” per questa vista. DBA_TABLESPACES visualizza i para-
metri di memorizzazione per tutte le tablespace.
726 CAPITOLO 42
Min_Extlen Dimensioni predefinite dell’estensione minima per gli oggetti della tablespace.
Status Stato della tablespace (‘ONLINE’, ‘OFFLINE’, ‘INVALID’, ‘READ ONLY’). Una tablespace “invalid” è una
tablespace eliminata. In questa vista i suoi record sono ancora visibili.
Contents Flag che indica se la tablespace viene utilizzata per memorizzare oggetti permanenti (‘PERMANENT’) o
solo segmenti temporanei (‘TEMPORARY’).
Logging Flag che indica il valore per il parametro LOGGING/NOLOGGING predefinito per gli oggetti della tablespace.
Extent_Management Luogo dove la gestione degli extent viene effettuata per la tablespace (‘DICTIONARY’ o ‘LOCAL’).
Segment_Space_ Flag che indica se lo spazio libero viene gestito tramite free list (MANUAL) o bitmap (AUTO).
Management
Bytes e Max_Bytes vengono convertite in blocchi Oracle, rispettivamente nelle colonne Blocks
e Max_Blocks.
Non esiste una versione “ALL” per questa vista. DBA_TS_QUOTAS visualizza le quote di
memorizzazione per tutti gli utenti e per tutte le tablespace, e rappresenta un modo molto effica-
ce per elencare l’uso dello spazio in tutto il database.
Partition_Name NULL se l’oggetto non è partizionato. Altrimenti, il nome della partizione del segmento.
Segment_Type Tipo del segmento (‘TABLE’, ‘CLUSTER’, ‘INDEX’, ‘ROLLBACK’ e così via).
Freelists Numero di “freelist” (elenchi di blocchi di dati nel segmento che possono essere utilizzati durante gli
inserimenti) allocati al segmento. Se un segmento prevede più freelist, la contesa per i blocchi liberi
durante gli insert contemporanei si riduce.
Freelist_Groups Numero di gruppi di freelist (da utilizzare con l’opzione Parallel Server) allocati al segmento.
Buffer_Pool Buffer pool nel quale il segmento verrà letto (‘DEFAULT’, ‘KEEP’ o ‘RECYCLE’) se sono stati definiti più
buffer pool.
728 CAPITOLO 42
to utile per tenere traccia dell’impatto delle modifiche apportate alle impostazioni next e
pctincrease . Oltre alle colonne Segment_Name, Segment_Type e Tablespace_Name,
USER_EXTENTS contiene tre nuove colonne: Extent_ID (per identificare l’extent all’interno
del segmento), Bytes (la dimensione dell’extent, in byte) e Blocks (la dimensione dell’extent, in
blocchi di Oracle).
Sia USER_SEGMENTS, sia USER_EXTENTS dispongono di versioni “DBA”, utili per
elencare l’impiego di spazio degli oggetti tra i vari proprietari. Sia DBA_SEGMENTS, sia
DBA_EXTENTS prevedono una colonna in più, Owner. Se si desidera elencare tutti i proprieta-
ri che possiedono segmenti di una tablespace, è possibile effettuare una query basata sulla colon-
na Tablespace_Name in DBA_SEGMENTS ed elencare tutti i proprietari di segmenti in questa
tablespace. Non esistono versioni “ALL” di queste viste.
Partitioning_Type Def_Pct_Free
Subpartitioning_Type Def_Pct_Used
Partition_Count Def_Ini_Trans
Def_Subpartition_Count Def_Max_Trans
Partitioning_Key_Count Def_Initial_Extent
Subpartitioning_Key_Count Def_Next_Extent
Def_Logging Def_Min_Extents
Def_Buffer_Pool Def_Max_Extents
Def_Pct_Increase
Def_Freelists
Def_Freelist_Groups
Def_Compression
GUIDA AL DIZIONARIO DATI DI ORACLE 729
Pct_Increase User_Stats
Freelists
Freelist_Groups
Compression
730 CAPITOLO 42
Alle statistiche per le colonne di partizione è possibile accedere tramite la vista del diziona-
rio dati USER_PART_COL_STATISTICS. Le colonne di USER_PART_COL_STATISTICS
assomigliano molto a quelle di USER_TAB_COL_STATISTICS.
Alle informazioni sull’istogramma dei dati per le partizioni è possibile accedere tramite la
vista del dizionario dati USER_PART_HISTOGRAMS. Le colonne di questa vista visualizzano
i valori di endpoint per ciascuna delle barre dell’istogramma. Le colonne sono Table_Name,
Partition_Name, Column_Name, Bucket_Number, Endpoint_Value ed Endpoint_Actual_Value.
Dato che gli indici possono essere partizionati, è disponibile una vista del dizionario dati
USER_IND_PARTITIONS. Le colonne contenute in USER_IND_PARTITIONS possono esse-
re suddivise in tre categorie, come mostrato nella Tabella 42.15.
Le colonne presenti in USER_IND_PARTITIONS riproducono quelle contenute in
USER_INDEXES, con alcune modifiche alle colonne di identificazione. Le colonne di identifi-
cazione per gli indici partizionati mostrano il nome della partizione, il suo valore superiore e la
posizione della partizione all’interno della tabella. Le colonne correlate alle statistiche sono
popolate quando la partizione viene analizzata. Le colonne correlate allo spazio descrivono
l’allocazione dello spazio per l’indice. Per informazioni sui parametri di memorizzazione, si
consulti il paragrafo Memorizzazione del Capitolo 48.
Se una partizione possiede delle partizioni secondarie, tramite le viste del dizionario dati si
potranno visualizzare i dettagli relativi a esse. USER_IND_SUBPARTITIONS contiene le co-
lonne correlate allo spazio e correlate alle statistiche di USER_IND_PARTITIONS, insieme ad
alcune colonne necessarie per identificare la partizione secondaria (Subpartition_Name e
Subpartition_Position). Analogamente, USER_TAB_SUBPARTITIONS contiene le colonne
correlate allo spazio e correlate alle statistiche di USER_TAB_PARTITIONS, insieme alle co-
Domidx_Opstatus Global_Stats
Parameters
GUIDA AL DIZIONARIO DATI DI ORACLE 731
Utenti: USER_USERS
Per visualizzare informazioni sul proprio account, è possibile eseguire una query su
USER_USERS. Questa vista include Username, User_ID (un numero assegnato dal database),
Default_Tablespace, Temporary_Tablespace e la data Created (data in cui è stato creato l’account).
La colonna Account_Status in USER_USERS visualizza lo stato dell’account, precisando se
questo è bloccato, sbloccato (OPEN) oppure scaduto. Se l’account è bloccato, la colonna
Lock_Date visualizza la data in cui l’account è stato bloccato, mentre la colonna Expiry_Date
visualizza la data di scadenza. Inoltre è possibile eseguire una query sulle informazioni relative
al gruppo di consumer di risorse (Initial_Rsrc_Consumer_Group) assegnato dal DBA e al valore
di External_Name.
ALL_USERS contiene solo le colonne Username, User_ID e Created tratte da USER_USERS,
ma elenca queste informazioni per tutti gli account del database. La vista ALL_USERS si rivela
utile quando è necessario conoscere quali nomi utente sono disponibili (per esempio, durante
l’esecuzione di comandi grant). La vista DBA_USERS contiene tutte le colonne presenti in
USER_USERS, più altre due colonne: Password (la password cifrata per l’account) e Profile (il
profilo risorse dell’utente). DBA_USERS elenca queste informazioni per tutti gli utenti del
database.
732 CAPITOLO 42
Le viste del dizionario dati adibite alla visualizzazione dei privilegi di colonna sono presso-
ché identiche nel disegno alle viste per i privilegi di tabella, descritte nel paragrafo precedente.
In ogni vista COL esiste una colonna in più, Column_Name, mentre è assente la colonna Hierarchy.
USER_COL_PRIVS è analoga a USER_ TAB_PRIVS, USER_COL_PRIVS_MADE è analoga
a USER_TAB_PRIVS_MADE e USER_COL_PRIVS_RECD è analoga a USER_TAB_PRIVS_
RECD.
Per tutte le viste dei privilegi di colonna sono disponibili le versioni “ALL”.
DBA_COL_PRIVS elenca tutti i privilegi di colonna concessi agli utenti del database (proprio
come DBA_ TAB_PRIVS elenca tutti i privilegi di tabella concessi agli utenti).
USERNAME PRIVILEGE
------------------------------ -----------------------
PRACTICE CREATE DIMENSION
PRACTICE UNLIMITED TABLESPACE
Non esiste una versione “ALL” per questa vista. Per visualizzare i privilegi di sistema con-
cessi a tutti gli utenti del database, è necessaria una query su DBA_SYS_PRIVS, che ha quasi le
stesse definizioni delle colonne di USER_SYS_PRIVS (la versione DBA ha una colonna Grantee,
mentre la versione USER ha una colonna Username).
42.15 Ruoli
Oltre ai privilegi concessi direttamente agli utenti, è possibile raggruppare in ruoli gruppi ben
determinati di privilegi. I ruoli possono essere concessi a utenti o ad altri ruoli e possono essere
costituiti sia da privilegi di oggetto, sia da privilegi di sistema. Per informazioni sull’impiego e
la gestione dei ruoli, si rimanda al Capitolo 18.
Per visualizzare i ruoli concessi a un utente, si dovrà effettuare una query sulla vista del
dizionario dati USER_ROLE_PRIVS. In essa verrà visualizzato anche qualsiasi ruolo concesso
al pubblico (PUBLIC). Le colonne disponibili per USER_ROLE_PRIVS sono le seguenti:
Admin_Option Un flag per indicare se il ruolo è stato concesso with admin option oppure no (‘YES' o ‘NO').
Default_Role Un flag per indicare se si tratta del ruolo predefinito dell’utente (‘YES' o ‘NO').
OS_Granted Un flag per indicare se il sistema operativo viene usato per gestire i ruoli (‘YES' o ‘NO').
734 CAPITOLO 42
Per elencare tutti i ruoli disponibili nel database, è necessario disporre dell’autorità DBA;
quindi, si può eseguire una query su DBA_ROLES. DBA_ROLE_PRIVS elenca gli assegnamenti
di questi ruoli a tutti gli utenti del database.
I ruoli possono ricevere tre tipi diversi di concessioni e a ciascuna di esse corrisponde una
vista del dizionario dati:
Privilegi di sistema ROLE_SYS_PRIVS. Simile a USER_SYS_PRIVS, eccettuata la presenza di una colonna Role al
posto della colonna Username.
NOTA Se l’utente non è un DBA, queste viste del dizionario dati mostrano solo i
ruoli garantiti all’utente stesso.
Oltre a queste viste ne esistono altre due, ciascuna con un’unica colonna, che elencano i
privilegi e i ruoli abilitati per la sessione in corso:
SESSION_PRIVS La colonna Privilege elenca tutti i privilegi di sistema disponibili per la sessione, sia concessi
direttamente, sia tramite ruoli.
SESSION_ROLES La colonna Role elenca tutti i ruoli attualmente abilitati per la sessione.
42.16 Audit
In qualità di utente senza autorità di DBA all’interno di un database Oracle, non è possibile
abilitare le caratteristiche di audit del database stesso. Se però l’audit è stato abilitato, esisteran-
no delle viste del dizionario dati utilizzabili da chiunque per visualizzare la procedura di audit.
Per le procedure di audit sono disponibili molte viste del dizionario dati. La maggior parte
di queste viste si basa su un’unica tabella di procedura di audit nel database (SYS.AUD$). La
vista più generica a disposizione per la procedura di audit è USER_AUDIT_TRAIL. Le colonne
di questa vista sono descritte nella Tabella 42.16. Dato che USER_AUDIT_TRAIL mostra i
record di audit per molti tipi diversi di azioni, molte delle colonne potranno non essere applicabili
a tutte le righe. La versione “DBA” di questa vista, DBA_AUDIT_TRAIL, elenca tutte le voci
dalla tabella della procedura di audit. La vista USER_AUDIT_TRAIL elenca solo le voci impor-
tanti per l’utente.
A partire da Oracle Database 10g sono disponibili diverse nuove colonne in
USER_AUDIT_TRAIL, tra cui SQL_Text, SQL_Bind, OS_Process e SCN. Per maggiori detta-
gli sull’uso dei valori SCN (System Change Number) si rimanda ai capitoli relativi all’impiego
delle query flashback.
GUIDA AL DIZIONARIO DATI DI ORACLE 735
Admin_Option Flag che indica se il ruolo o privilegio di sistema è stato sottoposto a grant with admin option (‘Y’ o ‘N’).
Ses_Actions Stringa di caratteri che serve come riassunto della sessione e registra i successi e gli insuccessi delle
varie azioni.
ReturnCode Codice di restituzione per ciascun comando eseguito. Se il comando è stato completato con successo,
il codice ReturnCode è 0.
Proxy_SessionID Numero di serie della sessione proxy, se l’utente si è collegato attraverso un meccanismo proxy.
Global_UID Identificatore utente globale per l’utente, se questo si è collegato come utente aziendale.
Instance_Number Numero di istanza come specificato nel file dei parametri di inizializzazione.
OS_Process Identificatore di processo del sistema operativo del processo server di Oracle.
Come si vede nella Tabella 42.16, la gamma di possibilità di audit disponibili è piuttosto
vasta (per un elenco completo si consulti la voce relativa al comando audit nel Capitolo 48). A
ciascun tipo di audit è possibile accedere tramite la relativa vista del dizionario dati. Ecco le viste
disponibili:
USER_AUDIT_STATEMENT Per comandi grant, revoke, audit, noaudit e alter system eseguiti dall’utente.
Per ciascuna delle viste “USER” elencate precedentemente esiste una versione “DBA” che
visualizza tutti i record di procedura di audit che rientrano nella categoria della vista.
Per visualizzare le opzioni di audit attualmente abilitate per i propri oggetti, è necessario
eseguire una query su USER_OBJ_AUDIT_OPTS. In USER_OBJ_AUDIT_OPTS, per ciascun
oggetto menzionato sono elencate le opzioni di audit relative a ciascun comando che può essere
eseguito sull’oggetto stesso (identificato dalle colonne Object_Name e Object_Type). I nomi
delle colonne di USER_OBJ_AUDIT_OPTS corrispondono alle prime tre lettere del comando
(per esempio, Alt per alter, Upd per update). Ciascuna colonna registra se il comando è stato
sottoposto ad audit per un determinato oggetto, quando il comando stesso è completato con
successo (‘S’), non è completato (‘U’) o in entrambi i casi. Le opzioni di audit predefinite attiva-
te per eventuali oggetti nuovi nel database possono essere visualizzate tramite la vista
ALL_DEF_AUDIT_OPTS, che utilizza le stesse convenzioni per l’assegnazione dei nomi alle
colonne utilizzate da USER_OBJ_AUDIT_OPTS. USER_OBJ_AUDIT_OPTS include le co-
lonne Object_Name e Object_Type.
I comandi che possono essere sottoposti ad audit vengono memorizzati in una tabella di
riferimento, denominata AUDIT_ACTIONS, che presenta due colonne: Action (codice numeri-
co per l’azione) e Name (nome dell’azione/comando). Action e Name corrispondono alle colon-
ne Action e Action_Name della vista USER_AUDIT_TRAIL.
I DBA possono utilizzare molte altre viste di audit prive di versioni “USER” corrispondenti,
tra cui DBA_AUDIT_EXISTS, DBA_PRIV_AUDIT_OPTS, DBA_STMT_AUDIT_OPTS e
GUIDA AL DIZIONARIO DATI DI ORACLE 737
42.17 Varie
Oltre alle viste del dizionario dati descritte nei paragrafi precedenti di questo capitolo, all’inter-
no del dizionario dati possono essere disponibili numerose viste e tabelle di vario tipo. Queste
viste e tabelle comprendono le viste riservate ai DBA e la tabella utilizzata quando si esegue il
comando explain plan. Nei paragrafi seguenti sono descritti brevemente tutti i vari tipi di viste.
CHAINED_ROWS
Il comando analyze consente di generare un elenco delle righe concatenate o migrate all’interno
di una tabella. L’elenco delle righe concatenate può essere memorizzato in una tabella di nome
CHAINED_ROWS. Per creare la tabella CHAINED_ROWS nel proprio schema, occorre ese-
guire lo script utlchain.sql (normalmente situato nella sottodirectory /rdbms/admin della home
directory di Oracle).
Per popolare la tabella CHAINED_ROWS, si utilizza la clausola list chained rows into del
comando analyze, come mostrato nel listato seguente:
PLAN_TABLE
Quando si mettono a punto le istruzioni SQL, è possibile stabilire i passaggi che l’ottimizzatore
dovrà seguire per eseguire la query. Per visualizzare il percorso di query, per prima cosa è neces-
sario creare nel proprio schema una tabella di nome PLAN_TABLE. Lo script utilizzato per
creare questa tabella si chiama utlxplan.sql e normalmente si trova nella sottodirectory /rdbms/
admin della home directory di Oracle.
Dopo aver creato la tabella PLAN_TABLE nel proprio schema, si può utilizzare il comando
explain plan, che genera dei record in PLAN_TABLE, contrassegnato con il valore Statement_ID
specificato per la query che si intende spiegare. Si rimanda al Capitolo 43 per i dettagli sulla
generazione dei listati di explain plan.
Le colonne ID e Parent_ID di PLAN_TABLE stabiliscono la gerarchia dei passaggi
(Operations) che l’ottimizzatore seguirà mentre esegue la query. Per ulteriori informazioni
sull’ottimizzatore di Oracle e l’interpretazione dei record di PLAN_TABLE, si rimanda al Capi-
tolo 43.
Librerie
Le routine PL/SQL (Capitolo 31) sono in grado di eseguire programmi C esterni. Per visualizzare
le librerie di programmi C esterni possedute, è possibile effettuare una query su USER_LI-
BRARIES, che visualizza il nome della libreria (Library_Name), il file associato (File_Spec),
specifica se il la libreria può essere caricata dinamicamente (Dynamic) e visualizza lo stato della
libreria stessa (Status). Sono inoltre disponibili le viste ALL_LIBRARIES e DBA_LIBRARIES.
Tali viste contengono una colonna in più, Owner, che indica il proprietario della libreria. Per
ulteriori informazioni sulle librerie si consulti il paragrafo dedicato a create library nel Capitolo 48.
740 CAPITOLO 42
Servizi eterogenei
Per supportare la gestione di servizi eterogenei, Oracle mette a disposizione diverse viste del
dizionario dati. Tutte le viste di questa categoria iniziano con le lettere “HS”, invece di “DBA”.
In generale, queste viste servono principalmente ai DBA. Per dettagli sulle viste “HS”, si consul-
ti Oracle Database Reference.
Strutture
Quando si usano strutture memorizzate, è possibile recuperare i nomi e i dettagli delle strutture
tramite le viste del dizionario dati USER_OUTLINES. Per visualizzare i suggerimenti che costi-
tuiscono la struttura, si esegue una query su USER_OUTLINE_HINTS. Per USER_OUTLINES
e USER_OUTLINE_HINTS sono disponibili le versioni “ALL” e “DBA”.
Consigli
A partire da Oracle Database 10g, gli utenti possono accedere alle viste del dizionario dati rela-
tive ai consigli per la messa a punto. I nomi di queste viste iniziano con “USER_ADVISOR_” ed
esiste un gruppo di viste corrispondenti a livello “DBA_”; ci sono inoltre delle viste di consigli
riservate ai DBA (come DBA_ADVISOR_DEFINITIONS).
Per esempio, USER_ADVISOR_ACTIONS contiene dati relativi alle azioni associate con
tutti i consigli nel database. Ogni azione è specificata nella colonna Command, con sei colonne
di attributi correlate. USER_ADVISOR_LOG visualizza informazioni sullo stato corrente di
tutte le attività, nonché dati specifici dell’esecuzione, come il monitoraggio del progresso e lo
stato di completamento. I parametri per i generatori di consigli sono accessibili tramite USER_
ADVISOR_PARAMETERS; la logica dei consigli è visibile tramite la vista USER_ADVISOR_
RATIONALE.
Per i risultati di un’analisi di tutti i consigli nel database, fare riferimento alla vista USER_
ADVISOR_RECOMMENDATIONS. Un consiglio può essere associato a più azioni (vedere
USER_ADVISOR_ACTIONS) in base alla logica adottata.
GUIDA AL DIZIONARIO DATI DI ORACLE 741
Pianificatori
A partire da Oracle Database 10g, è possibile accedere a un gruppo di viste relative ai processi
Scheduler del database. Tra queste troviamo USER_SCHEDULER_JOBS (tutti i processi
Scheduler di proprietà dell’utente), USER_SCHEDULER_PROGRAMS (i programmi di piani-
ficazione) e USER_SCHEDULER_PROGRAM_ARGS (gli argomenti per i programmi di pia-
nificazione). I dettagli di esecuzione dei processi sono visibili tramite le viste
USER_SCHEDULER_JOB_LOG, USER_SCHEDULER_JOB_RUN_DETAILS e USER_
SCHEDULER_RUNNING_JOBS. Le pianificazioni sono visibili tramite USER_
SCHEDULER_SCHEDULES.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 43
Guida all’ottimizzazione
delle applicazioni
e del codice SQL
A
ogni nuove versione dei suoi prodotti Oracle aggiunge carat-
teristiche che migliorano le prestazioni delle applicazioni; tra queste possono esserci nuove op-
zioni che devono essere implementate manualmente (come il partizionamento) o modifiche più
sotterranee che offrono vantaggi senza costringere ad apportare cambiamenti alle applicazioni
già esistenti.
L’ottimizzazione non dev’essere considerata solo come un’operazione da svolgere dopo che
l’applicazione è stata rilasciata all’ambiente di produzione o dopo aver effettuato un test di
sistema. Come si vedrà, la ricerca di prestazioni ottimali è una caratteristica da pianificare e
dev’essere parte del processo di progettazione.
Questo capitolo presenta una descrizione delle principali novità introdotte con Oracle Database
10g in materia di messa a punto; viene inoltre fornito un insieme di indicazioni e consigli pratici
relativi all’ottimizzazione delle applicazioni Oracle. L’ultimo paragrafo del capitolo è dedicato
all’integrazione di queste caratteristiche con le soluzioni migliori consigliate. Verranno anche
presentate delle linee guida per la generazione e l’interpretazione degli explain plan e delle
strutture memorizzate.
Strumenti automatici
Oracle Database 10g introduce diversi strumenti concepiti per automatizzare la gestione delle
prestazioni; tra questi troviamo Automatic Statistics Collection, Automatic Database Diagnostic
Monitoring (ADDM) e Automatic SQL Tuning. A supporto di questi strumenti, l’Automatic
Workload Repository raccoglie, elabora e mantiene delle statistiche di prestazioni con finalità di
rivelazione di problemi e di messa a punto automatica.
ADDM riduce lo sforzo necessario a diagnosticare e mettere a punto i sistemi Oracle. SQL
Tuning Advisor offre una tecnica rapida ed efficiente per l’ottimizzazione delle istruzioni SQL.
Per l’uso di questi strumenti, si rimanda al set di strumenti di Oracle Enterprise Manager e alla
relativa documentazione.
Automatic Statistics Collection automatizza la raccolta di statistiche dell’ottimizzatore per
gli oggetti. Gli oggetti con statistiche vecchie o senza statistiche vengono analizzati automatica-
mente, quindi gli amministratori non sono più costretti a tener traccia di ciò che deve e ciò che
non deve essere analizzato e nemmeno a effettuare manualmente l’analisi. Il processo
GATHER_STATS_JOB viene pianificato automaticamente per raccogliere statistiche per gli
oggetti che ne sono privi o che presentano statistiche non più attuali.
A partire da Oracle9i, è possibile modificare le dimensioni di alcune delle cache e dei pool
nella SGA mentre il database è in esecuzione. In Oracle Database 10g queste modifiche possono
essere apportate automaticamente da Oracle senza intervento da parte dell’utente. Per abilitare
la funzione Automatic Shared Memory Management, occorre impostare il parametro di
inizializzazione SGA_TARGET a un valore diverso da zero e il parametro STATISTICS_LEVEL
a ‘TYPICAL' o ‘ALL'.
Trace end-to-end
Il trace end-to-end delle applicazioni identifica l’origine di un carico eccessivo, come un’istru-
zione SQL dispendiosa, per identificatore del client, servizio, modulo o azione. I problemi di
carico possono essere individuati per identificatore del client, servizio (un gruppo di applicazio-
ni con attributi comuni), modulo applicativo o azione. I nomi dei servizi vengono impostati
tramite il parametro di inizializzazione DBMS_SERVICE.CREATE_SERVICE o
SERVICE_NAMES. I nomi dei moduli e delle azioni vengono impostati con le procedure SET
MODULE e SET ACTION di DBMS_APPLICATION_INFO.
L’utility trcsess
L’utility a linea di comando trcsess consolida le informazioni di trace provenienti da trace file
selezionati in base ai criteri specificati (ID di sessione, ID del client, nome del servizio, nome
dell’azione o nome del modulo). Trcsess unisce le informazioni in un singolo file di output che
può poi essere elaborato tramite TKPROF.
GU I D A A L L ' O T T I M I Z Z A Z I O N E D E L L E A P P L I C A Z I O N I E D E L C O D I C E S Q L 745
Modifiche dell’ottimizzatore
Ecco le principali modifiche all’ottimizzatore introdotte da Oracle Database 10g:
■ Obsolescenza dell’ottimizzatore basato su regole.
■ Parametri cambiati per il parametro di inizializzazione OPTIMIZER_MODE. CHOOSE e
RULE non sono più validi; ALL_ROWS è quello predefinito.
■ Il campionamento dinamico predefinito tramite OPTIMIZER_DYNAMIC_SAMPLING ora è 2.
■ Al calcolo dei costi è stato aggiunto il costo di CPU; l’unità di costo è il tempo.
■ Nuovi suggerimenti a disposizione per le query: SPREAD_MIN_ANALYSIS, USE_NL_
WITH_INDEX, QB_NAME, NO_QUERY_TRANSFORMATION, NO_USE_NL, NO_USE_
MERGE, NO_USE_HASH, NO_INDEX_FFS, NO_INDEX_SS, NO_STAR_TRANSFORMATION,
INDEX_SS, INDEX_SS_ASC e INDEX_SS_DESC.
■ Alcuni suggerimenti sono stati rinominati: NO_PARALLEL (prima NOPARALLEL), NO_
PARALLEL_INDEX (prima NOPARALLEL_INDEX) e NO_REWRITE (prima NOREWRITE).
■ I suggerimenti AND_EQUAL, HASH_AJ, MERGE_AJ, NL_AJ, HASH_SJ, MERGE_SJ,
NL_SJ, ORDERED_PREDICATES, ROWID e STAR sono stati disapprovati e non dovrebbero
essere utilizzati.
■ Gli indici globali con partizionamento hash possono migliorare le prestazioni degli indici in
cui in cui un numero ridotto di blocchi nell’indice genera molti conflitti negli ambienti OLTP
multiutente.
■ Obsolescenza di Oracle Trace; al suo posto si utilizzano TKPROF o SQL Trace.
■ Sono disponibili viste aggiuntive V$, come V$OSSTAT per le statistiche del sistema opera-
tivo e le viste relative a metrica, soglie e consigli relative agli advisor (generatori di consigli)
disponibili tramite Oracle Enterprise Manager.
A prescindere dalle opzioni di ottimizzazione utilizzate per il database o le singole istruzio-
ni SQL, le prestazioni delle applicazioni possono essere determinate in gran parte dalla misura
in cui ci si attiene alle soluzioni migliori (le cosiddette “best practices”) per la progettazione
delle applicazioni. Il paragrafo che segue presenta le insidie e le soluzioni più comuni in materia
di progettazione.
È una soluzione ragionevole? Assolutamente no! Farà ciò che voleva il programmatore, ma
con un costo significativo per l’applicazione e non c’è nulla che un amministratore di database
possa fare per migliorare le prestazioni. In questo caso il costo non sarà dovuto all’attività di I/O,
perché la tabella DUAL sarà residente nell’area di memoria dell’istanza, bensì a quella della
CPU. Ogni volta che il programma viene eseguito, da tutti gli utenti, il database impiegherà 30
secondi per consumare tutte le risorse della CPU che il sistema può supportare. In questo caso
particolare la query select SysDate from DUAL impegnava più del 40% di tutto il tempo di CPU
utilizzato dall’applicazione: un vero spreco. La messa a punto della singola istruzione SQL non
sarebbe di nessun aiuto; è il progetto dell’applicazione a dover essere rivisto per eliminare l’inu-
tile esecuzione dei comandi.
Per coloro che preferiscono basare la messa a punto sul rapporto di utilizzo della buffer
cache, questo database presentava un rapporto vicino al 100% dovuto all’alto numero di letture
logiche assolutamente superflue senza letture fisiche correlate. Il rapporto di utilizzo della buffer
cache confronta il numero di letture logiche con quello delle letture fisiche;se il 10% delle lettu-
re logiche richiede delle letture fisiche, il rapporto di utilizzo della buffer cache è 100 meno 10,
ossia 90%. I rapporti di utilizzo bassi identificano i database che effettuano un numero elevato di
letture fisiche; i rapporti molto elevati, come quello di questo esempio, possono identificare dei
database che effettuano un numero eccessivo di letture logiche.
Non ci sono parametri di inizializzazione che possono fare in modo che questo cambiamen-
to abbia effetto; è un problema di progettazione e richiede il coinvolgimento attivo di sviluppatori,
progettisti, DBA e utenti finali nel processo di pianificazione e messa a punto.
Si consideri il semplice test seguente: effettuare una scansione completa di una tabella di
grandi dimensioni. Non appena l’esecuzione della query ha inizio, le prime righe vengono
visualizzate. Ora si provi a effettuare la stessa scansione aggiungendo una clausola order by su
una colonna non indicizzata. Non verrà visualizzata alcuna riga finché tutte le righe non sono
state ordinate. Come si spiega questo fatto? Il motivo è che per la seconda query Oracle effettua
un’operazione SORT ORDER BY sui risultati della scansione completa della tabella. Trattando-
si di un’operazione su un’insieme, questo dev’essere completo prima che l’operazione successi-
va possa essere eseguita.
Si immagini ora un’applicazione in cui molte query vengono eseguite nell’ambito di una
procedura e dove ciascuna delle query contiene una clausola order by. Questa si trasforma in una
serie di ordinamenti nidificati: nessuna operazione può avere inizio fino a quando quella prece-
dente non è stata completata.
Occorre ricordare che anche le operazioni union effettuano ordinamenti. Se la cosa è appro-
priata per la logica business, è meglio utilizzare un’operazione union all al posto di union, in
quanto non effettua ordinamenti (perché non elimina i duplicati).
Durante la creazione degli indici, si potrebbero eliminare gli ordinamenti in successione
ricorrendo alla clausola compute statistics del comando create index e raccogliendo le statisti-
che mentre l’indice viene creato.
blocchi della tabella. Gli aggiornamenti per le righe nel blocco utilizzeranno lo spazio riservato
dall’impostazione di pctfree. Può accadere che dal blocco vengano eliminate delle righe, ma
questo non verrà nuovamente aggiunto alla lista dei blocchi liberi fino a quando l’utilizzo dello
spazio non scende al di sotto dell’impostazione di pctused. Ciò significa che nelle applicazioni
che prevedono molti inserimenti e cancellazioni di righe, è facile trovare molti blocchi che usano
poco di più dello valore di pctused per ciascun blocco. In tal caso, ogni blocco risulta usato per
poco più del 40%, pertanto ogni blocco presente nella buffer cache è pieno solo in quella misura:
ciò produce un aumento significativo del numero di blocchi richiesti per completare ciascun
comando. Se la propria applicazioni effettua molte operazioni delete e insert, si consiglia di
prendere in considerazione la possibilità di aumentare pctused in modo che il blocco venga
aggiunto nuovamente alla lista dei blocchi liberi il più velocemente possibile.
Se l’impostazione di pctfree è troppo bassa, gli aggiornamenti potrebbero costringere Oracle
a spostare la riga (che prende il nome di riga migrata). In alcuni casi il concatenamento delle
righe è inevitabile, come quando la lunghezza della riga è superiore alla dimensione del blocco
del database. Quando si verificano i fenomeni del concatenamento e della migrazione delle ri-
ghe, ogni accesso a una riga richiederà l’accesso a più blocchi, influendo sul numero di letture
logiche necessarie per ogni comando. È possibile rilevare il concatenamento delle righe analiz-
zando la tabella e controllando le statistiche a essa relative tramite USER_TABLES.
Divide et impera
Se non si può evitare di eseguire operazioni dispendiose sui dati, si può tentare di dividere il
lavoro in elementi più gestibili. Spesso è possibile limitare il numero di righe su cui agiscono le
operazioni, migliorando notevolmente le prestazioni.
GU I D A A L L ' O T T I M I Z Z A Z I O N E D E L L E A P P L I C A Z I O N I E D E L C O D I C E S Q L 753
Usare le partizioni
Le partizioni possono avere molti vantaggi per gli utenti finali, i DBA e gli addetti all’assistenza
per le applicazioni. Per gli utenti i vantaggi potenziali sono due: migliori prestazioni delle query
e maggiore disponibilità del database. Le prestazioni delle query possono migliorare grazie al-
l’eliminazione delle partizioni: l’ottimizzatore sa quali partizioni possono contenere i dati ri-
chiesti da una query, pertanto quelle che non partecipano vengono eliminate dal processo di
interrogazione. Dato che sono necessarie meno letture logiche e fisiche, la query dovrebbe esse-
re completata più rapidamente.
La disponibilità migliora per via dei vantaggi che le partizioni generano per DBA e addetti
all’assistenza per le applicazioni. Molte funzioni amministrative possono essere eseguite su sin-
gole partizioni, consentendo di lasciare inalterato il resto della tabella. Per esempio, è possibile
troncare (comando truncate) una singola partizione di una tabella. È possibile dividere una
partizione, spostarla in una tablespace diversa o scambiarla con una tabella esistente (in modo
che la tabella che prima era indipendente ora sia considerata una partizione). Si possono inoltre
raccogliere statistiche su una partizione alla volta. Tutte queste capacità restringono l’ambito
delle funzioni amministrative, riducendo il loro impatto sulla disponibilità complessiva del
database.
Usare il parallelismo
Quasi tutte le operazioni principali possono essere eseguite in parallelo, comprese query,
inserimenti, creazioni di oggetti e caricamenti di dati. Le opzioni di parallelismo consentono di
chiamare in causa più processori nell’esecuzione di un singolo comando, dividendo efficace-
mente il comando in più comandi coordinati più piccoli. L’esecuzione del comando dovrebbe
risultare migliore. È possibile specificare un grado di parallelismo a livello di oggetto e aggirarlo
tramite suggerimenti nelle proprie query.
Test corretti
Nella maggior parte delle metodologie di sviluppo, il test delle applicazioni avviene in più fasi,
tra cui il test dei moduli, il test del sistema completo e il test di prestazioni. In molti casi il test del
sistema completo e il test di prestazioni non vengono eseguiti in modo adeguato a causa dei
vincoli di tempo dovuti al fatto che l’applicazione è vicina alla data di rilascio prevista. Ne
risulta che le applicazioni vengono rilasciate all’ambiente di produzione senza che sia possibile
garantire in alcun modo che la funzionalità e le prestazioni dell’applicazione nel complesso
soddisferanno le necessità degli utenti. Questo è un difetto grave e importante e non dovrebbe
essere tollerato dagli utenti dell’applicazione. Gli utenti non hanno bisogno che un solo compo-
nente dell’applicazione funzioni correttamente, bensì che l’intera applicazione operi in modo
754 CAPITOLO 43
appropriato a sostegno di un processo aziendale. Se non riescono a fare ciò che dovrebbero in
una giornata di lavoro, l’applicazione ha fallito.
Questo è un principio fondamentale in relazione all’identificazione della necessità di
ottimizzazione: se l’applicazione rallenta il processo aziendale, dev’essere messa a punto. I test
effettuati devono essere in grado di determinare se l’applicazione agirà come un freno sul pro-
cesso aziendale una volta sottoposta al carico di lavoro previsto.
righe al secondo nel database. Effettuare lo stesso test negli altri ambienti di database in modo da
identificare se ce n’è qualcuno decisamente diverso dagli altri.
Ora si consideri l’applicazione. Si riescono a inserire righe nelle tabelle tramite l’applica-
zione a una velocità che sia anche solo vicina a quella appena calcolata? Molte applicazioni
vengono eseguite a meno del 5% della velocità supportata dall’ambiente, in quanto sono intral-
ciate da indici inutili o dal tipo di problemi di progettazione descritti in precedenza nel capitolo.
Se la loro velocità di caricamento diminuisce, per esempio da 40 a 20 righe al secondo, l’atten-
zione dell’ottimizzazione non dovrebbe essere rivolta unicamente al modo in cui è avvenuta la
riduzione, ma anche a come l’applicazione sia riuscita a ottenere l’inserimento di solo 40 righe
al secondo in un ambiente che supporta l’inserimento di migliaia di righe al secondo.
NOTA Per poter utilizzare set autotrace on, il DBA deve aver creato prima il ruo-
lo PLUSTRACE nel database e poi aver concesso questo ruolo all’account dell’utente. Il ruolo
PLUSTRACE consente di accedere alle viste di base relative alle prestazioni nel dizionario dati
di Oracle. Lo script necessario a creare il ruolo PLUSTRACE prende il nome di plustrce.sql e in
genere è situato nella directory /sqlplus/admin sotto la home directory del software Oracle.
Il file che crea la tabella PLAN_TABLE è situato nella sottodirectory /rdbms/admin della
directory home del software Oracle.
Quando si utilizza set autotrace on, i record vengono inseriti nella copia della tabella
PLAN_TABLE per mostrare l’ordine delle operazioni eseguite. Terminata la query, vengono
visualizzati i dati selezionati. Dopo la visualizzazione dei dati della query, viene mostrato l’ordi-
ne delle operazioni, seguito da informazioni statistiche riguardanti l’elaborazione della query.
La trattazione seguente relativa al comando set autotrace on concentra l’attenzione sulla parte di
output che visualizza l’ordine delle operazioni.
NOTA Per visualizzare solo l’output di explain plan senza eseguire la query, oc-
corre utilizzare il comando set autotrace on trace explain.
Se si usa il comando set autotrace on con le opzioni predefinite, l’explain plan delle query
non viene visualizzato fino a che le query non sono state completate. Il comando explain plan
(descritto successivamente) visualizza i percorsi di esecuzione senza eseguire le query. Quindi,
per rendersi conto delle prestazioni di una query, si può attivare il comando explain plan prima di
eseguirla. Se invece si è quasi sicuri che le prestazioni di una query sono accettabili, si può
utilizzare set autotrace on per verificarne il percorso di esecuzione.
GU I D A A L L ' O T T I M I Z Z A Z I O N E D E L L E A P P L I C A Z I O N I E D E L C O D I C E S Q L 757
NOTA Quando si usa il comando set autotrace on, Oracle cancella automatica-
mente i record che inserisce in PLAN_TABLE dopo aver visualizzato il percorso di esecuzione.
select *
from BIBLIOTECA;
Execution plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=1 Card=31 Bytes=12
40)
1 0 TABLE ACCESS (FULL) OF 'BIBLIOTECA' (TABLE) (Cost=1 Card=31
Byte=1240)
delete
from BIBLIOTECA_AUTORE;
Execution plan
----------------------------------------------------------
0 DELETE STATEMENT Optimizer=ALL_ROWS (Cost=4 Card=37 Bytes=12
58)
1 0 DELETE OF 'BIBLIOTECA_AUTORE'
2 1 TABLE ACCESS (FULL) OF 'BIBLIOTECA_AUTORE' (TABLE) (Cost=
4 Card=37 Bytes=1258)
Il comando delete, come previsto, richiede la scansione completa di una tabella. Se le tabel-
le sono state analizzate, l’output della colonna “Execution plan” visualizza il numero di righe di
ciascuna tabella, il costo relativo di ciascuna fase e il costo complessivo dell’operazione. I costi
mostrati nei passaggi sono cumulativi, ossia corrispondono ai costi del passaggio più quelli di
tutti i passaggi secondari. Queste informazioni consentono di evidenziare le operazioni più di-
spendiose per l’elaborazione della query.
758 CAPITOLO 43
Nell’esempio seguente viene eseguita una query leggermente più complessa. Si tratta di una
query basata su indice che viene effettuata sulla tabella BIBLIOTECA, che utilizza l’indice di
chiave primaria.
Execution plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=3 Card=2 Bytes=80)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'BIBLIOTECA' (TABLE) (Cost
=3 Card=2 Bytes=80)
2 1 INDEX (RANGE SCAN) OF 'SYS_C004834' (INDEX (UNIQUE)) (Co
st=1 Card=2)
Questo listato include tre operazioni. L’operazione 2, INDEX RANGE SCAN dell’indice di
chiave primaria della tabella BIBLIOTECA (il suo nome è stato generato dal sistema), fornisce
i dati per l’operazione 1, TABLE ACCESS BY INDEX ROWID. I dati restituiti dall’operazione
TABLE ACCESS BY INDEX ROWID vengono utilizzati per soddisfare la query (operazione 0).
L’output precedente mostra anche che l’ottimizzatore indenta automaticamente ogni fase
successiva all’interno del piano esecutivo. In generale, l’elenco delle operazioni andrebbe letto
dall’interno verso l’esterno e dall’alto verso il basso. In questo modo, se vengono elencate due
operazioni, quella più interna è in genere quella che viene eseguita per prima. Se due operazioni
sono sullo stesso livello di indentazione, allora quella elencata per prima (con il numero di
operazione più basso) verrà eseguita per prima.
Nell’esempio che segue, vengono unite tramite join le tabelle BIBLIOTECA e
BIBLIOTECA_AUTORE senza l’ausilio di indici. Oracle utilizzerà un’operazione join chiama-
ta merge join, in cui ciascuna tabella viene ordinata separatamente prior prima che i due insiemi
di righe ordinati vengano uniti:
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=7 Card=5 Bytes=320)
1 0 MERGE JOIN (Cost=7 Card=5 Bytes=320)
2 1 INDEX (FULL SCAN) OF 'SYS_C004834' (INDEX (UNIQUE)) (Cos
t=1 Card=31)
3 1 SORT (JOIN) (Cost=5 Card=37 Bytes=1258)
4 3 TABLE ACCESS (FULL) OF 'BIBLIOTECA_AUTORE' (TABLE) (Cos
t=1 Card=37 Bytes=1258)
A prima vista, l’indentazione del listato precedente può creare un po’ di confusione, ma le
informazioni riguardo la gerarchia delle operazioni fornite con la numerazione delle operazioni
stesse consentono di chiarire l’ordine di esecuzione. Le operazioni più interne sono quelle che
vengono eseguite per prime: TABLE ACCESS FULL e INDEX FULL SCAN. Successivamente,
i dati della scansione completa di tabella vengono elaborati tramite un’operazione SORT JOIN
(nell’operazione 4), mentre l’output prodotto dalla scansione di indice (che è già ordinato) viene
GU I D A A L L ' O T T I M I Z Z A Z I O N E D E L L E A P P L I C A Z I O N I E D E L C O D I C E S Q L 759
utilizzato come base per l’operazione TABLE ACCESS BY INDEX ROWID (fase 2). La fase 2
e la fase 4 hanno entrambe l’operazione 1, MERGE JOIN, come chiamante. L’operazione MERGE
JOIN restituisce i dati all’utente tramite l’istruzione select.
Se la stessa query fosse stata eseguita come un join NESTED LOOPS, sarebbe stato genera-
to un percorso d’esecuzione differente. Come mostrato nel listato seguente, il join NESTED
LOOPS è in grado di sfruttare l’indice di chiave primaria che si trova sulla colonna Titolo della
tabella BIBLIOTECA.
NOTA In base alla dimensione delle tabelle e delle statistiche disponibili, Oracle
potrebbe scegliere di effettuare un tipo diverso di operazione join, chiamata hash join, invece di
un join NESTED LOOPS.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=4 Card=37 Bytes=19
24)
1 0 NESTED LOOPS (Cost=4 Card=37 Bytes=1924)
2 1 TABLE ACCESS (FULL) OF 'BIBLIOTECA_AUTORE' (TABLE) (Cost=
4 Card=37 Bytes=1258)
3 1 INDEX (UNIQUE SCAN) OF 'SYS_C004834' (INDEX (UNIQUE)) (C
ost=1 Card=1 Bytes=18)
I join NESTED LOOPS sono tra i pochi percorsi di esecuzione che non seguono la regola di
“lettura dall’interno verso l’esterno”, applicata ai percorsi esecutivi indentati. Per leggere corret-
tamente il percorso di esecuzione di NESTED LOOPS, si esamini l’ordine delle operazioni che
forniscono direttamente i dati all’operazione NESTED LOOPS (in questo caso la 2 e la 3). Di
queste due operazioni, viene eseguita per prima quella con il numero minore (nell’esempio, la
2). Pertanto, l’operazione TABLE ACCESS FULL della tabella BIBLIOTECA_AUTORE viene
eseguita per prima (BIBLIOTECA_AUTORE è la tabella guida per la query).
Dopo aver stabilito la tabella guida per la query, la parte restante del percorso di esecuzione
può essere letta dall’interno verso l’esterno e dall’alto verso il basso. La seconda operazione
eseguita è INDEX UNIQUE SCAN dell’indice di chiave primaria della tabella BIBLIOTECA.
Quindi, l’operazione NESTED LOOPS è in grado di restituire le righe all’utente.
Se al posto di un join NESTED LOOPS fosse stato selezionato un hash join, il percorso di
esecuzione sarebbe stato il seguente:
Execution plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=6 Card=37 Bytes=19
24)
1 0 HASH JOIN (Cost=6 Card=37 Bytes=1924)
2 1 INDEX (FULL SCAN) OF 'SYS_C004834' (INDEX (UNIQUE)) (Cos
760 CAPITOLO 43
Il percorso esecutivo dell’hash join mostra che sono state eseguite due scansioni separate. Dal
momento che le due operazioni compaiono allo stesso livello di indentazione, la scansione del-
l’indice di chiave primaria della tabella BIBLIOTECA viene eseguita per prima (in quanto pos-
siede un numero d’operazione più basso).
explain plan
for
Nel listato seguente, viene riportato un esempio di esecuzione del comando explain plan:
explain plan
for
select /*+ USE_HASH (biblioteca) */
BIBLIOTECA_AUTORE.NomeAutore
from BIBLIOTECA, BIBLIOTECA_AUTORE
where BIBLIOTECA.Titolo = BIBLIOTECA_AUTORE.Titolo;
Quando si esegue il comando explain plan, i record vengono inseriti nella tabella PLAN_
TABLE. È possibile interrogare direttamente PLAN_TABLE oppure è possibile utilizzare il
package DBMS_XPLAN affinché formatti i risultati. L’uso del package DBMS_XPLAN è illu-
strato nel listato seguente:
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 37 | 1924 | 4 (25)| 00:00:01 |
|* 1 | HASH JOIN | | 37 | 1924 | 4 (25)| 00:00:01 |
| 2 | INDEX FULL SCAN | SYS_C004834 | 32 | 608 | 1 (100)| 00:00:01 |
| 3 | TABLE ACCESS FULL| BIBLIOTECA_AUTORE | 37 | 1258 | 4 (25)| 00:00:01 |
L’output include la colonna Cost, che visualizza il costo relativo di ogni fase e delle sue fasi
secondarie. Essa include inoltre i valori di ID, l’indentazione per mostrare le relazioni tra i
passaggi e una sezione aggiuntiva che elenca le condizioni di limitazione applicate a ciascun
passaggio.
Quando si mette a punto una query, si deve prestare attenzione i passaggi che effettuano la
scansione di molte righe ma ne restituiscono solo un numero ridotto. Per esempio, si dovrebbe
evitare di effettuare una scansione di tabella completa o una tabella con diversi milioni di righe
per restituire solo tre righe. Si può utilizzare l’output dell’explain plan per identificare i passaggi
che hanno a che fare con il numero maggiore di righe.
select *
from BIBLIOTECA;
Per risolvere la query precedente, Oracle esegue una scansione completa sulla tabella BI-
BLIOTECA. Se questa tabella è di dimensioni ridotte, l’operazione può risolversi in breve tem-
po, con un minimo impatto sulle prestazioni. Tuttavia, via via che le dimensioni della tabella
BIBLIOTECA aumentano, crescono anche i costi dell’operazione in termini di prestazioni. Se
più utenti eseguono scansioni complete della tabella BIBLIOTECA, i costi associati crescono
ancora più velocemente.
Con una pianificazione adeguata, le scansioni complete di una tabella non rappresentano per
forza un problema per le prestazioni. Si dovrebbe collaborare con i propri amministratori di
database per essere certi che quest’ultimo sia stato configurato in modo tale da sfruttare caratte-
ristiche come le query parallele e le letture di più blocchi. A meno che l’ambiente per le scansioni
complete di tabelle non sia stato configurato correttamente, sarebbe opportuno controllarne l’uso.
Oracle potrà usare l’operazione TABLE ACCESS BY INDEX ROWID per recuperare la riga in
questione.
Quando è noto il ROWID, si conosce anche l’esatta collocazione fisica della riga. È possibi-
le utilizzare degli indici per accedere alle informazioni di ROWID, come descritto nel paragrafo
“Operazioni che utilizzano gli indici, più avanti nel capitolo”. Dato che gli indici consentono un
accesso rapido ai valori di ROWID, aiutano a migliorare le prestazioni delle query che fanno uso
di colonne indicizzate.
Suggerimenti
All’interno di una query è possibile specificare suggerimenti che guidino il CBO nell’elabora-
zione della query stessa. Per specificare un suggerimento, si utilizza la sintassi mostrata nel-
l’esempio che segue. Si inserisca la stringa seguente subito dopo la parola chiave select:
/*+
FULL(biblioteca)
*/
Se non si utilizzasse il suggerimento FULL per risolvere questa query, Oracle pianifichereb-
be normalmente l’impiego dell’indice di chiave primaria sulla colonna Titolo. Dato che la tabel-
la è ancora piccola, una sua scansione completa non è dispendiosa. Quando le dimensioni della
tabella incominceranno a crescere, probabilmente si opterà per un accesso basato sui valori di
ROWID.
Valutazione VARCHAR2(2),
constraint CATFK foreign key (NomeCategoria)
references CATEGORIA(NomeCategoria));
Ora la tabella BIBLIOTECA possiede due indici: un indice unico sulla colonna Titolo, e un
indice non unico sulla colonna NomeCategoria. Per la risoluzione di una query si potrebbero
utilizzare uno o più indici, in base al modo in cui la query stessa viene scritta ed eseguita. In
quanto parte del processo di creazione dell’indice, le statistiche a esso relative sono state raccol-
te tramite la clausola compute statistics. Dato che la tabella è già popolata con delle righe, non
sarà necessario eseguire un comando separato per analizzare l’indice.
select *
from BIBLIOTECA
where Titolo = ‘INNUMERACY’;
Internamente, l’esecuzione della query precedente viene suddivisa in due fasi. Per prima
cosa, si accede all’indice della colonna Titolo tramite un’operazione INDEX UNIQUE SCAN.
Dall’indice viene restituito il valore di ROWID che corrisponde al titolo “INNUMERACY”;
questo valore di ROWID viene quindi utilizzato per eseguire una query sulla tabella BIBLIOTE-
CA attraverso un’operazione TABLE ACCESS BY INDEX ROWID.
Se tutte le colonne selezionate dalla query fossero contenute nell’indice, Oracle non avrebbe
bisogno di utilizzare l’operazione TABLE ACCESS BY INDEX ROWID; nel caso in cui i dati si
trovassero nell’indice, questo rappresenterebbe tutto ciò che serve per soddisfare la query. Poi-
ché in questo caso la query ha selezionato tutte le colonne dalla tabella BIBLIOTECA, e l’indice
non conteneva tutte le colonne di questa tabella, è stato necessario ricorrere all’operazione TABLE
ACCESS BY INDEX ROWID.
Si consideri nuovamente la tabella BIBLIOTECA, con un indice unico sulla colonna Titolo.
Una query del tipo:
select Titolo
from BIBLIOTECA
where Titolo like ‘M%’;
restituirebbe tutti i valori di Titolo che iniziano con ‘M’. Poiché la clausola where si riferisce alla
colonna Titolo, l’indice di chiave primaria di questa colonna potrà servire a risolvere la query.
Tuttavia, nella clausola where non è specificato un valore unico, bensì un intervallo di valori. Di
conseguenza, si accede all’indice unico di chiave primaria tramite un’operazione INDEX RANGE
SCAN. Poiché le operazioni INDEX RANGE SCAN richiedono la lettura di più valori dall’in-
dice, risultano meno efficienti delle operazioni INDEX UNIQUE SCAN.
Nell’esempio precedente, la query ha selezionato solo la colonna Titolo. Dato che i valori
della colonna Titolo sono memorizzati nell’indice di chiave primaria, che è in fase di analisi, non
è necessario che il database acceda direttamente alla tabella BIBLIOTECA durante l’esecuzione
della query. L’operazione INDEX RANGE SCAN dell’indice di chiave primaria è l’unica ri-
chiesta per risolvere la query.
La colonna NomeCategoria della tabella BIBLIOTECA possiede un indice non unico sui
propri valori. Se nella clausola where della query si specifica una condizione limitativa per i
valori di NomeCategoria, viene eseguita un’operazione INDEX RANGE SCAN dell’indice di
NomeCategoria. Poiché l’indice BIBLIOTECA$CATEGORIA non è unico, il database non può
eseguire un’operazione INDEX UNIQUE SCAN su BIBLIOTECA$CATEGORIA, anche se
nella query la colonna NomeCategoria viene uguagliata a un unico valore.
select Titolo
from BIBLIOTECA
where NomeCategoria = 'SAGGIADULTI';
Poiché l’indice BIBLIOTECA$CATEGORIA non è unico, questa query può restituire più
righe e quando si leggono questi dati si potrebbe ricorrere a un’operazione di INDEX RANGE
SCAN. In base alle statistiche della tabella, Oracle può decidere di eseguire una scansione com-
pleta di tabella.
Se viene utilizzato l’indice, l’esecuzione della query precedente può includere due opera-
zioni: un’operazione INDEX RANGE SCAN di BIBLIOTECA$CATEGORIA (per ricavare i
valori di ROWID di tutte le righe contenenti valori “SAGGIADULTI” nella colonna NomeCate-
goria), seguita da un’operazione TABLE ACCESS BY INDEX ROWID della tabella BIBLIO-
TECA (per recuperare i valori della colonna Titolo).
GU I D A A L L ' O T T I M I Z Z A Z I O N E D E L L E A P P L I C A Z I O N I E D E L C O D I C E S Q L 765
Se una colonna possiede un indice unico e viene messa a confronto con un valore contenente
un segno =, allora al posto di INDEX RANGE SCAN si userà INDEX UNIQUE SCAN.
select Titolo
from BIBLIOTECA
where Titolo like ‘M%’;
È possibile eseguire una scansione dell’indice anche mentre si utilizzano gli operatori < o >:
select Titolo
from BIBLIOTECA
where Titolo > 'M';
Quando si specifica un intervallo di valori per una colonna, non viene utilizzato un indice
per risolvere la query se il primo carattere specificato è un carattere jolly. La query seguente non
effettuerà un’operazione INDEX RANGE SCAN sugli indici disponibili:
select Editore
from BIBLIOTECA
where Titolo like ‘%M%’;
Dato che il primo carattere della stringa utilizzata per il confronto dei valori è un carattere
jolly, l’indice non potrà essere utilizzato per trovare velocemente i dati corrispondenti. In questo
caso, viene eseguita una scansione completa della tabella (operazione TABLE ACCESS FULL).
In base alle statistiche relative alla tabella e all’indice, Oracle potrebbe scegliere di eseguire una
scansione completa dell’indice. In questo esempio, se la colonna selezionata è Titolo, l’ottimiz-
zatore può decidere di eseguire una scansione intera dell’indice di chiave primaria piuttosto che
una scansione completa della tabella BIBLIOTECA.
select COUNT(*)
from BIBLIOTECA
where NomeCategoria = 'SAGGIADULTI';
Come si procede nel caso in cui non si sa se i valori della colonna NomeCategoria sono
memorizzati in lettere maiuscole, minuscole, o miste? In una situazione simile, si può scrivere la
query in questo modo:
select COUNT(*)
from BIBLIOTECA
where UPPER(NomeCategotria) = 'SAGGIADULTI';
usa la funzione UPPER) eseguirà un’operazione TABLE ACCESS FULL sulla tabella BIBLIO-
TECA, a meno che non sia stato creato un indice basato sulla funzione UPPER(NomeCategoria);
per i dettagli relativi agli indici basati sulle funzioni, si rimanda al Capitolo 17.
Se si concatenano due colonne o una stringa e una colonna, gli indici su queste colonne non
vengono utilizzati. L’indice memorizza il valore reale della colonna e qualsiasi modifica di quel
valore impedisce all’ottimizzatore di utilizzarlo.
select Titolo
from BIBLIOTECA
where NomeCategoria is null;
Dato che NomeCategoria è l’unica colonna con una condizione di limitazione nella query e,
in questo caso, la condizione limitativa è un controllo di valore NULL, l’indice BIBLIOTECA$CA-
TEGORIA non viene utilizzato e la risoluzione viene effettuata tramite un’operazione TABLE
ACCESS FULL.
Che cosa accade se sulla colonna viene effettuato un controllo IS NOT NULL? Tutti i valori
non NULL della colonna vengono memorizzati nell’indice; tuttavia la ricerca nell’indice non
sarebbe efficiente. Per risolvere la query, l’ottimizzatore dovrebbe leggere ciascun valore del-
l’indice e accedere alla tabella per ciascuna riga restituita da quest’ultimo. Nella maggior parte
dei casi, risulta più efficiente una scansione completa della tabella rispetto a una scansione del-
l’indice (con le operazioni TABLE ACCESS BY INDEX ROWID associate) per tutti i valori
restituiti dall’indice. Pertanto la query seguente può non utilizzare un indice:
select Titolo
from BIBLIOTECA
where NomeCategoria is not null;
select *
from BIBLIOTECA
where Titolo = ‘INNUMERACY’;
Cosa accadrebbe se si desiderasse selezionare tutti i record che non hanno un valore di
Titolo uguale a ‘INNUMERACY'? Il segno = verrebbe sostituito da !=, e la query assumerebbe
l’aspetto seguente:
select *
from BIBLIOTECA
where Titolo != 'INNUMERACY';
Quando si risolve questa nuova versione della query, l’ottimizzatore può anche non usare un
indice. Gli indici vengono utilizzati quando i valori vengono confrontati esattamente con un
GU I D A A L L ' O T T I M I Z Z A Z I O N E D E L L E A P P L I C A Z I O N I E D E L C O D I C E S Q L 767
altro valore, ossia quando le condizioni di limitazione sono di uguaglianza, non di disuguaglian-
za. In questo esempio, l’ottimizzatore opterebbe per un indice solo se decidesse che la scansione
completa di indice (insieme alle operazioni TABLE ACCESS BY INDEX ROWID necessarie
per ottenere tutte le colonne) potrebbe essere più rapida di una scansione completa di tabella.
Un altro esempio di disuguaglianza è rappresentato dalla clausola not in, quando impiegata
in una subquery. La query seguente seleziona dei valori dalla tabella BIBLIOTECA per libri che
non sono stati scritti da Stephen Jay Gould:
select *
from BIBLIOTECA
where Titolo NOT IN
(select Titolo
from BIBLIOTECA_AUTORE
where NomeAutore = 'STEPHEN JAY GOULD');
In alcuni casi, la query del listato precedente non sarebbe in grado di utilizzare un indice
sulla colonna Titolo della tabella BIBLIOTECA, poiché non è impostata uguale a nessun valore.
Al contrario, il valore di BIBLIOTECA.Titolo viene usato con una clausola not in per eliminare
le righe che corrispondono a quelle restituite dalla subquery. Per utilizzare un indice è necessario
impostare la colonna indicizzata uguale a un valore. In molti casi, Oracle riscriverà internamente
la clausola not in trasformandola in una clausola not exists, consentendo così alla query di usare
un indice. La query seguente, che usa una clausola in, potrebbe usare un indice sulla colonna
BIBLIOTECA.Titolo, oppure potrebbe eseguire un join non indicizzato tra le tabelle;
l’ottimizzatore sceglierà il percorso con il minor costo basandosi sulle statistiche disponibili:
select *
from BIBLIOTECA
where Titolo IN
(select Titolo
from BIBLIOTECA_AUTORE
where NomeAutore = 'STEPHEN JAY GOULD');
Se l’indice è selettivo
Tutte le regole precedenti che stabiliscono se un indice può essere utilizzato considerano la
sintassi della query che viene eseguita e la struttura dell’indice disponibile. L’ottimizzatore può
768 CAPITOLO 43
sfruttare la selettività dell’indice per giudicare se un suo eventuale impiego possa ridurre il costo
dell’esecuzione della query.
In un indice altamente selettivo, un piccolo numero di record viene associato a ciascun
valore distinto della colonna. Per esempio, se in una tabella ci sono 100 record e 80 valori distinti
per una colonna di quella tabella, la selettività di un indice su quella colonna è di 80/100 = 0,80.
Maggiore è la selettività, minore è il numero di righe restituite per ciascun valore distinto nella
colonna.
Il numero di righe restituite per valore distinto è importante nella fase di scansione di un
intervallo di valori. Se un indice ha una bassa selettività, le molte operazioni INDEX RANGE
SCAN e TABLE ACCESS BY INDEX ROWID utilizzate per recuperare i dati possono richiede-
re un lavoro maggiore rispetto all’operazione TABLE ACCESS FULL di una tabella.
La selettività di un indice non viene considerata dall’ottimizzatore, a meno che non si sia
analizzato l’indice. L’ottimizzatore è in grado di utilizzare istogrammi per esprimere giudizi
riguardo alla distribuzione dei dati all’interno di una tabella. Per esempio, se i valori dei dati
sono fortemente asimmetrici, tanto che la maggior parte di essi si trova in un intervallo molto
ristretto, l’ottimizzatore può evitare di utilizzare l’indice per i valori contenuti in quell’intervallo
e sfruttarlo invece per i valori che stanno al di fuori di esso.
Suggerimenti
Sono disponibili diversi suggerimenti per guidare l’ottimizzatore nella modalità di utilizzo degli
indici. INDEX è il suggerimento correlato all’indice più utilizzato. Il suggerimento INDEX
comunica all’ottimizzatore di usare una scansione basata sull’indice nella tabella specificata.
Con questa opzione non è necessario specificare il nome dell’indice, anche se è possibile elenca-
re indici specifici, se lo si desidera.
Per esempio, nella query seguente viene utilizzato il suggerimento INDEX per suggerire
l’uso di un indice sulla tabella BIBLIOTECA durante la risoluzione della query:
risce l’uso del metodo TABLE ACCESS BY INDEX ROWID per la tabella specificata. Il sugge-
rimento AND_EQUAL suggerisce all’ottimizzatore di unire i risultati di più scansioni di indice.
contrario, se viene eseguita un’operazione di gruppo, come un ordinamento, i record non vengo-
no visualizzati immediatamente. Durante operazioni di questo tipo, l’utente deve attendere che
tutte le righe vengano elaborate. Pertanto è necessario limitare il numero di operazioni di gruppo
effettuate da query utilizzate da utenti in linea (in modo da ridurre il tempo di risposta dell’appli-
cazione). Le operazioni di ordinamento e raggruppamento sono le più comuni nella produzione
di report di grandi dimensioni e nelle transazioni batch.
Ordinamento di righe
Sono tre le operazioni interne di Oracle che ordinano le righe senza raggrupparle. La prima è
SORT ORDER BY, utilizzata quando in una query è presente una clausola order by. Per esem-
pio, la query e l’ordinamento della tabella BIBLIOTECA vengono effettuati in base ai valori di
Editore:
Quando si esegue questa query, l’ottimizzatore recupera i dati dalla tabella BIBLIOTECA
tramite un’operazione TABLE ACCESS FULL (dato che non esistono condizioni di limitazione
per la query, tutte le righe vengono restituite). I record recuperati non vengono però visualizzati
immediatamente, perché un’operazione SORT ORDER BY ordina i record prima che l’utente
possa vedere i risultati.
Occasionalmente, a un’operazione di ordinamento può venire richiesto di eliminare i record
doppi mentre li ordina. Per esempio, com’è possibile visualizzare i valori distinti di Editore nella
tabella BIBLIOTECA? La query avrebbe l’aspetto seguente:
Come per la query precedente, anche questa non ha condizioni di limitazione, per cui viene
eseguita un’operazione TABLE ACCESS FULL per recuperare i record dalla tabella BIBLIO-
TECA. Tuttavia, la parola chiave distinct indica all’ottimizzatore di restituire solo i valori distin-
ti per la colonna Editore.
Per risolvere la query, l’ottimizzatore prende i record restituiti dall’operazione TABLE
ACCESS FULL e li ordina tramite un’operazione SORT UNIQUE NOSORT. Nessun record
viene visualizzato fino a che tutti i record non sono stati elaborati.
Oltre a essere utilizzata dalla parola chiave distinct, l’operazione SORT UNIQUE NOSORT
viene invocata quando si usano le funzioni minus, intersect e union (ma non union all).
Una terza operazione di ordinamento, SORT JOIN, viene sempre utilizzata come parte di
un’operazione MERGE JOIN e mai da sola. Le implicazioni di SORT JOIN sulle prestazioni dei
join sono descritte nel paragrafo “Operazioni che eseguono join” più avanti in questo capitolo.
Raggruppamento di righe
Due delle operazioni interne di Oracle ordinano le righe mentre raggruppano assieme i record
uguali. Le due operazioni, SORT AGGREGATE e SORT GROUP BY, vengono utilizzate insie-
me alle funzioni di raggruppamento (come MIN, MAX e COUNT). La sintassi della query deter-
mina quale operazione utilizzare.
Nella query seguente viene selezionato dalla tabella BIBLIOTECA il valore massimo di
Editore in base all’ordine alfabetico:
select MAX(Editore)
from BIBLIOTECA;
GU I D A A L L ' O T T I M I Z Z A Z I O N E D E L L E A P P L I C A Z I O N I E D E L C O D I C E S Q L 771
Per risolvere la query, l’ottimizzatore esegue due operazioni separate. Per prima cosa un’ope-
razione TABLE ACCESS FULL che seleziona i valori di Editore dalla tabella. In secondo luogo,
le righe vengono analizzate tramite un’operazione SORT AGGREGATE, che restituisce all’utente
il valore massimo di Editore.
Se la colonna Editore fosse indicizzata, l’indice potrebbe essere utilizzato per risolvere query
riguardanti il valore massimo o minimo dell’indice (come descritto in uno dei paragrafi prece-
denti, “Operazioni che utilizzano gli indici”). Dato che la colonna Editore non è indicizzata, è
richiesta un’operazione di ordinamento. Il valore massimo di Editore non viene restituito da
questa query fino a che non sono stati letti tutti i record ed è stata completata l’operazione SORT
AGGREGATE.
L’operazione SORT AGGREGATE è stata utilizzata nell’esempio precedente perché nella
query non compariva alcuna clausola group by. Le query in cui è specificata la clausola group by
utilizzano un’operazione interna chiamata SORT GROUP BY.
Come si fa a ricavare il numero dei titoli presenti per ciascun editore? La query seguente
seleziona il conteggio di ciascun valore di Editore dalla tabella BIBLIOTECA per mezzo di una
clausola group by:
Questa query restituisce un record per ciascun valore distinto di Editore. Per ogni valore di
Editore, il numero delle sue occorrenze nella tabella BIBLIOTECA viene calcolato e visualizzato
nella colonna COUNT(*).
Per risolvere questa query, Oracle esegue innanzi tutto una scansione completa della tabella
(non esistono condizioni di limitazione per la query). Dato che si utilizza una clausola group by,
le righe restituite dall’operazione TABLE ACCESS FULL vengono elaborate da un’operazione
SORT GROUP BY. I record vengono restituiti all’utente dopo che tutte le righe sono state ordi-
nate in gruppi e che il conteggio di ciascun gruppo è stato calcolato. Come con le altre operazio-
ni di ordinamento, nessun record viene restituito all’utente fino a che tutti i record non sono stati
elaborati.
Le operazioni incontrate finora hanno coinvolto esempi semplici: scansioni complete di
tabelle, scansioni di indici e operazioni di ordinamento. La maggior parte delle query che acce-
dono a un’unica tabella utilizza le operazioni descritte nei paragrafi precedenti. Quando si mette
a punto una query per un utente in linea, è consigliabile evitare l’uso di operazioni di ordinamen-
to e di raggruppamento che costringano gli utenti ad attendere che i record vengano elaborati.
Quando possibile, è opportuno scrivere query che consentano agli utenti dell’applicazione di
ricevere velocemente i record nel momento in cui la query viene risolta. Minore è il numero di
operazioni di ordinamento e di raggruppamento effettuate, più rapida sarà la restituzione del
primo record trovato all’utente. In una transazione batch, le prestazioni della query vengono
misurate in base al tempo complessivo impiegato per suo il completamento, non al tempo neces-
sario per restituire la prima riga. Di conseguenza, le transazioni batch possono utilizzare le ope-
razioni di ordinamento e di raggruppamento senza impatto sulle prestazioni percepibili dell’ap-
plicazione.
Se l’applicazione non richiede che tutte le righe vengano ordinate prima della visualizzazione
dell’output della query, è opportuno considerare l’eventualità di usare il suggerimento FIRST_
ROWS, che indica all’ottimizzatore di dare la precedenza a percorsi esecutivi che non eseguono
operazioni di gruppo.
772 CAPITOLO 43
select Titolo
from BIBLIOTECA
UNION
select Titolo
from LIBRO_ORDINE;
select Titolo
from BIBLIOTECA;
select Titolo
from LIBRO_ORDINE
select Titolo
from BIBLIOTECA
UNION ALL
select Titolo
from LIBRO_ORDINE;
Quando elabora quest’ultima query, l’ottimizzatore esegue le scansioni richieste dalle due
query, seguite da un’operazione UNION ALL. Non è richiesta alcuna operazione SORT UNIQUE
NOSORT, poiché una clausola union all non elimina i record doppi.
Nell’elaborare la query union, l’ottimizzatore indirizza separatamente ciascuna delle query
destinate alla union. Anche se tutti gli esempi presentati nei listati precedenti hanno coinvolto
query semplici con scansioni di tabelle complete, le query destinate a union possono essere
molto articolate, con corrispondenti percorsi di esecuzione complessi. I risultati non vengono
restituiti all’utente fino a che tutti i record non sono stati elaborati.
Quando si utilizza la clausola minus, la query viene elaborata in modo molto simile al per-
corso esecutivo intrapreso per l’esempio di union. Nella query seguente, vengono confrontati i
valori di Titolo provenienti dalle tabelle BIBLIOTECA e LIBRO_ORDINE. Se un valore di
Titolo esiste nella tabella LIBRO_ORDINE ma non in BIBLIOTECA, questo valore verrà resti-
tuito dalla query. In altre parole, si desidera visualizzare in ordine tutti i Titoli che non si posseg-
gono ancora.
select Titolo
from LIBRO_ORDINE
MINUS
select Titolo
from BIBLIOTECA;
Quando si esegue questa query, le due query destinate a MINUS vengono eseguite
separatamente. La prima query:
select Titolo
from LIBRO_ORDINE
richiede una scansione dell’indice basata sulla chiave primaria LIBRO_ORDINE. La seconda
query:
select Titolo
from BIBLIOTECA;
richiede una scansione di indice completa per l’indice di chiave primaria della tabella BIBLIO-
TECA.
Per eseguire la parola chiave minus, ciascun gruppo di record restituito dalle scansioni com-
plete delle tabelle viene ordinato attraverso un’operazione SORT UNIQUE NOSORT (con la
quale vengono ordinate le righe ed eliminate quelle doppie). L’insieme di righe ordinate viene
quindi elaborato per mezzo dell’operazione MINUS. L’operazione MINUS non viene eseguita
fino a che ciascun gruppo di record restituito dalle query non risulta ordinato. Nemmeno l’ope-
razione di ordinamento restituisce i record fino a che non ha terminato di passarli in rassegna
tutti, quindi l’operazione MINUS non può iniziare fino a che entrambe le operazioni SORT
UNIQUE NOSORT non sono state completate. Come per l’esempio della query union, la query
mostrata nell’esempio riguardante l’operazione MINUS offre scarse prestazioni per gli utenti in
linea che si basano sulla velocità con cui la query restituisce la prima riga.
La clausola intersect confronta i risultati di due query e stabilisce quali righe sono in comu-
ne. La query che segue determina i valori di Titolo che si trovano sia nella tabella BIBLIOTECA
sia nella tabella LIBRO_ORDINE:
select Titolo
from LIBRO_ORDINE
INTERSECT
select Titolo
from BIBLIOTECA;
select Titolo
from LIBRO_ORDINE
774 CAPITOLO 43
richiede una scansione intera dell’indice di chiave primaria della tabella LIBRO_ORDINE. La
seconda query:
select Titolo
from BIBLIOTECA;
richiede una scansione intera dell’indice di chiave primaria della tabella BIBLIOTECA. I risul-
tati delle scansioni delle due tabelle vengono elaborati separatamente dalle operazioni SORT
UNIQUE NOSORT. In altre parole, vengono ordinate le righe provenienti dalla tabella
LIBRO_ORDINE e quelle della tabella BIBLIOTECA. I risultati dei due ordinamenti vengono
confrontati dall’operazione INTERSECTION, mentre la clausola intersect restituisce i valori di
Titolo restituiti a loro volta da entrambi gli ordinamenti.
Il percorso di esecuzione di una query che utilizza una clausola intersect richiede l’impiego
di operazioni SORT UNIQUE NOSORT. Dato che le operazioni SORT UNIQUE NOSORT non
restituiscono alcun record all’utente fino a che l’intero gruppo di righe non è stato ordinato, le
query che fanno uso della funzione INTERSECT devono attendere che entrambi gli ordinamenti
siano completati prima di poter effettuare l’operazione INTERSECTION. A causa di questa
dipendenza dalle operazioni di ordinamento, le query che utilizzano la funzione INTERSECT
non restituiscono alcun record all’utente fino a che gli ordinamenti non risultano completati.
Tutte le clausole union, minus e intersect richiedono l’elaborazione di gruppi di righe prima
di restituire qualsiasi riga all’utente. Gli utenti in linea di un’applicazione possono riscontrare
cali di prestazioni per le query che utilizzano queste funzioni, anche se gli accessi alle tabelle
coinvolte sono stati messi a punto in modo accurato; la dipendenza dalle operazioni di ordina-
mento influisce sulla velocità con cui la prima riga viene restituita all’utente.
Quando si opera una selezione dalla vista NARRADULTI, l’ottimizzatore preleva i criteri
dalla query e li combina con il testo della query della vista. Se nella query della vista si specifi-
cano delle condizioni di limitazione, queste se possibile vengono applicate al testo della query
della vista. Per esempio, se si esegue la query
In questo esempio, la vista non ha alcun impatto sulle prestazioni della query. Quando il
testo della vista viene unito con le condizioni di limitazione della query, le opzioni che
l’ottimizzatore ha a sua disposizione aumentano; potrà scegliere tra più indici e più percorsi di
accesso ai dati.
Il modo in cui una vista viene elaborata dipende dalla query su cui si basa. Se il testo della
query della vista non può essere unito con la query che utilizza la vista, questa viene risolta
prima che il resto delle condizioni venga applicato. Si consideri la vista seguente:
La vista EDITORE_CONTA visualizza una riga per ciascun valore distinto di Editore nella
tabella BIBLIOTECA insieme al numero dei record che possiedono quel valore. La colonna
Conta_Edi della vista EDITORE_CONTA registra il conteggio per ciascun valore distinto di
Editore.
In che modo l’ottimizzatore elabora la query seguente della vista EDITORE_CONTA?
select *
from EDITORE_CONTA
where Conta_Edi > 1;
La query si riferisce alla colonna Conta_Edi della vista. Tuttavia, la clausola where della query
non può essere associata al testo della query della vista, poiché Conta_Edi viene creata tramite
un’operazione di raggruppamento. La clausola where potrà essere applicata dopo che il gruppo
di risultati proveniente dalla vista EDITORE_CONTA sia stato completamente risolto.
Le viste che contengono operazioni di raggruppamento vengono risolte prima che venga
applicata la parte restante dei criteri della query. Analogamente alle operazioni di ordinamento,
le viste con operazioni di raggruppamento non restituiscono alcun record fino a che non è stata
elaborata l’intera sequenza di risultati. Se la vista non contiene operazioni di raggruppamento, il
testo della query può essere unito con le condizioni di limitazione della query che esegue la
selezione dalla vista. Di conseguenza, le viste con operazioni di raggruppamento limitano il
numero di opzioni disponibili per l’ottimizzatore e non restituiscono i record fino a che tutte le
righe sono state elaborate; le query effettuate dagli utenti in linea su queste viste hanno presta-
zioni scarse.
Quando la query viene elaborata, per prima cosa l’ottimizzatore risolve la vista. Dal mo-
mento che la query della vista è:
l’ottimizzatore legge i dati dalla tabella BIBLIOTECA tramite un’operazione TABLE ACCESS
FULL. Dato che viene utilizzata una clausola group by, le righe restituite dall’operazione TABLE
ACCESS FULL vengono elaborate da un’operazione SORT GROUP BY. Un’altra operazione,
FILTER, elaborerà i dati. L’operazione FILTER serve per eliminare le righe che si basano sui
criteri specificati nella query:
Se si usa una vista che possiede una clausola group by, le righe non vengono restituite dalla
vista fino a che ciascuna di esse non è stata elaborata dalla vista stessa. Di conseguenza, la query
776 CAPITOLO 43
può impiegare parecchio tempo per restituire la prima riga, e le prestazioni della vista percepite
dagli utenti in linea possono risultare inaccettabili. Se si riuscissero a rimuovere le operazioni di
ordinamento e di raggruppamento dalle viste, si incrementerebbero le probabilità che il testo
della vista possa essere unito con quello della query che chiama la vista e di conseguenza le
prestazioni potrebbero migliorare (benché la query possa utilizzare altri gruppi di operazioni che
influiscono negativamente sulle prestazioni).
Quando il testo della query viene unito con il testo della vista, aumentano le opzioni a
disposizione dell’ottimizzatore. Per esempio, la combinazione delle condizioni di limitazione
della query con le condizioni di limitazione della vista può consentire l’uso di un indice prima
inutilizzabile durante l’esecuzione della query.
L’unione automatica del testo della query e di quello della vista può essere disattivata trami-
te il suggerimento NO_MERGE. Il suggerimento PUSH_PRED forza un predicato di join in una
vista; con PUSH_SUBQ le subquery non unite vengono valutate il più presto possibile nel per-
corso esecutivo.
Selezioni da subquery
Ogni volta che è possibile, l’ottimizzatore combina il testo proveniente da una subquery con il
resto della query. Per esempio, si consideri la query seguente:
select Titolo
from BIBLIOTECA
where Titolo in
(select Titolo from LIBRO_ORDINE);
select BIBLIOTECA.Titolo
from BIBLIOTECA, LIBRO_ORDINE
where BIBLIOTECA.Titolo = LIBRO_ORDINE.Titolo;
Con la query scritta sotto forma di join, l’ottimizzatore dispone di alcune operazioni per
elaborare i dati (come descritto nel paragrafo “Operazioni che eseguono join” più avanti nel
capitolo).
Se la subquery non può essere risolta come join, allora viene risolta prima che la parte
restante del testo della query venga elaborato rispetto ai dati; si tratta di un meccanismo simile al
modo in cui l’operazione FILTER viene utilizzata per le viste. In realtà, l’operazione FILTER
viene utilizzata per le subquery se queste non possono essere unite con il resto della query.
Le subquery che dipendono da operazioni di raggruppamento presentano gli stessi problemi
di messa a punto delle viste che contengono operazioni di raggruppamento. Le righe recuperate
da queste subquery devono essere elaborate completamente prima di poter applicare le restanti
condizioni di limitazione della query.
select BIBLIOTECA.Titolo
from BIBLIOTECA, LIBRO_ORDINE
where BIBLIOTECA.Titolo = LIBRO_ORDINE.Titolo;
select Titolo
from BIBLIOTECA inner join LIBRO_ORDINE
using (Titolo);
oppure
select Titolo
from BIBLIOTECA natural inner join LIBRO_ORDINE;
Le condizioni di join possono agire come condizioni di limitazione per il join stesso. Dato
che la colonna BIBLIOTECA.Titolo è uguagliata a un valore nella clausola where, l’ottimizzatore
può, durante l’esecuzione della query, utilizzare un indice sulla colonna BIBLIOTECA.Titolo.
Se la colonna LIBRO_ORDINE.Titolo dispone di un indice, anche questo indice può essere
preso in considerazione dall’ottimizzatore.
Oracle presenta tre metodi principali per elaborare i join: le operazioni MERGE JOIN, le
operazioni NESTED LOOPS e le operazioni HASH JOIN. In base alle condizioni presenti nella
query, gli indici disponibili e alle statistiche disponibili, l’ottimizzatore sceglie quale operazione
di join utilizzare. In relazione alla natura dell’applicazione e delle query, si può decidere di
indurre l’ottimizzatore a utilizzare un metodo differente dalla sua prima scelta. Nei paragrafi che
seguono vengono analizzate le caratteristiche dei diversi metodi di join e le condizioni in cui
ciascuno di essi si rivela più utile.
MERGE JOIN
In questa operazione, i due input del join vengono elaborati separatamente, ordinati e uniti tra-
mite join. Le operazioni MERGE JOIN vengono comunemente utilizzate quando non vi sono
indici disponibili per le condizioni di limitazione della query.
Nella query seguente vengono unite tramite join le tabelle BIBLIOTECA e
BIBLIOTECA_AUTORE. Se nessuna delle tabelle possiede un indice sulla colonna Titolo, non
ci sono indici che possano essere utilizzati durante la query (poiché esistono altre condizioni di
778 CAPITOLO 43
limitazione nella query). Questo esempio ricorre a un suggerimento per indurre l’uso di un’ope-
razione merge join:
oppure
Per risolvere la query, l’ottimizzatore può scegliere di eseguire un’operazione MERGE JOIN
delle tabelle. Questa operazione richiede che ciascuna delle tabelle venga letta separatamente (in
genere tramite un’operazione TABLE ACCESS FULL oppure una scansione di indice comple-
ta). Il gruppo di righe restituito dalla scansione della tabella BIBLIOTECA_AUTORE viene
ordinato tramite un’operazione SORT JOIN. Il gruppo di righe restituito dalle operazioni INDEX
FULL SCAN e TABLE ACCESS BY INDEX ROWID sulla tabella BIBLIOTECA è già ordina-
to (nell’indice), quindi per questa parte del percorso esecutivo non è necessaria un’altra opera-
zione SORT JOIN. I dati ricavati dalle operazioni SORT JOIN vengono uniti con un’operazione
MERGE JOIN.
Quando si utilizza un’operazione MERGE JOIN per unire tramite join due gruppi di record,
ciascun gruppo viene elaborato separatamente prima di essere unito. L’operazione MERGE JOIN
non può iniziare fino a che non ha ricevuto i dati da entrambe le operazioni SORT JOIN che le
forniscono l’input. Le operazioni SORT JOIN, a loro volta, non forniscono dati a MERGE JOIN
fino a che tutte le righe non sono state ordinate. Se gli indici fungono da sorgenti di dati, le
operazioni SORT JOIN possono essere ignorate.
Se l’operazione MERGE JOIN deve attendere il completamento di due operazioni SORT
JOIN separate, un join che utilizza MERGE JOIN normalmente offre prestazioni scarse per gli
utenti in linea. Questo problema è dovuto al ritardo nella restituzione della prima riga del join
agli utenti. Se le tabelle aumentano di dimensione, il tempo richiesto per il completamento degli
ordinamenti aumenta drasticamente. Se le tabelle hanno dimensioni molto diverse tra di loro,
l’ordinamento eseguito sulla tabella più grande influisce negativamente sulle prestazioni com-
plessive della query.
Dal momento che le operazioni MERGE JOIN richiedono una scansione e un ordinamento
completi delle tabelle coinvolte, queste operazioni dovrebbero essere effettuate solo se entrambe
le tabelle sono molto piccole o molto grandi. Se entrambe le tabelle sono molto piccole, il pro-
cesso di scansione e ordinamento viene completato velocemente. Se entrambe le tabelle sono
molto grandi, le operazioni di ordinamento e scansione richieste dalle operazioni MERGE JOIN
possono sfruttare le opzioni parallele di Oracle.
Oracle è in grado di eseguire operazioni in parallelo, permettendo così a più processori di
partecipare all’esecuzione di un unico comando. Tra le operazioni che possono essere eseguite
in parallelo vi sono quelle TABLE ACCESS FULL e le operazioni di ordinamento. Dato che
MERGE JOIN le utilizza entrambe, può ottenere grandi vantaggi dalle opzioni parallele di Oracle.
L’esecuzione in parallelo di query che coinvolgono operazioni MERGE JOIN spesso incrementa
le prestazioni (purché siano disponibili adeguate risorse di sistema per supportare le operazioni
parallele).
GU I D A A L L ' O T T I M I Z Z A Z I O N E D E L L E A P P L I C A Z I O N I E D E L C O D I C E S Q L 779
NESTED LOOPS
Le operazioni NESTED LOOPS consentono di unire tramite join due tabelle con un metodo di
risoluzione ciclica: i record vengono recuperati da una tabella e, per ciascun record recuperato,
viene effettuato un accesso alla seconda tabella, che avviene in base a un indice.
Nel listato seguente, viene riproposta una forma della query del paragrafo precedente MERGE
JOIN. Viene utilizzato un suggerimento per consigliare un accesso basato sugli indici per la
tabella BIBLIOTECA:
Dal momento che la colonna Titolo della tabella BIBLIOTECA viene utilizzata come parte
della condizione di join nella query, l’indice di chiave primaria è in grado di risolvere il join.
Quando si esegue la query, per effettuare il join può essere utilizzata un’operazione NESTED
LOOPS.
Per effettuare un join NESTED LOOPS, per prima cosa l’ottimizzatore deve selezionare
una tabella guida per il join, ovvero la tabella che viene letta per prima (solitamente attraverso
un’operazione TABLE ACCESS FULL, anche se accade molto spesso di vedere scansioni di
indice). Per ciascun record nella tabella guida verrà eseguita una query sulla seconda tabella
all’interno del join. La query di esempio unisce tramite join le tabelle BIBLIOTECA e BIBLIO-
TECA_AUTORE in base ai valori della colonna Titolo. Durante l’esecuzione di NESTED LOOPS,
un’operazione selezionerà tutti i record dalla tabella BIBLIOTECA_AUTORE. Viene controlla-
to l’indice di chiave primaria della tabella BIBLIOTECA per stabilire se contiene una voce per
il valore nel record corrente prelevato dalla tabella BIBLIOTECA_AUTORE. Se si trova una
corrispondenza, allora il valore di Titolo verrà restituito dall’indice di chiave primaria di BI-
BLIOTECA. Qualora fosse necessario prelevare altre colonne da BIBLIOTECA, la riga verreb-
be selezionata dalla tabella BIBLIOTECA tramite un’operazione TABLE ACCESS BY INDEX
ROWID.
In un join NESTED LOOPS sono coinvolte almeno due operazioni di accesso ai dati: un
accesso alla tabella guida e un accesso, solitamente basato sugli indici, alla tabella dipendente. I
metodi di accesso ai dati più utilizzati, TABLE ACCESS FULL, TABLE ACCESS BY INDEX
ROWID e le scansioni di indice, restituiscono dei record alle operazioni successive non appena
ne trovano uno; non attendono che l’intero gruppo di record venga selezionato. Dato che queste
operazioni sono in grado di fornire rapidamente agli utenti le prime righe corrispondenti, i join
NESTED LOOPS vengono riservati normalmente per gli utenti in linea.
Nell’implementazione di join NESTED LOOPS, è necessario considerare la dimensione
delle tabella guida. Se la tabella guida è grande e viene letta tramite una scansione completa di
tabella, l’operazione TABLE ACCESS FULL eseguita su di essa può influire negativamente
sulle prestazioni della query. Se gli indici sono disponibili su entrambi i lati del join, Oracle
selezionerà una tabella guida per la query. L’ottimizzatore effettua un controllo per quanto ri-
guarda la dimensione delle tabelle e la selettività degli indici, scegliendo il percorso con il costo
complessivo minore.
Quando si uniscono tramite join tre tabelle, Oracle esegue due join separati: un join di due
tabelle che genera un insieme di record e successivamente un join tra questo insieme di record e
la terza tabella. Se si utilizzano join NESTED LOOPS, l’ordine in cui le tabelle vengono unite si
complica. L’output del primo join genera un insieme di record che funge da tabella guida per il
secondo join.
La dimensione del gruppo di record restituiti dal primo join influisce sulle prestazioni del
secondo join, pertanto può avere un impatto significativo sulle prestazioni dell’intera query. Si
780 CAPITOLO 43
dovrebbe provare per prima cosa a unire tramite join le tabelle più selettive, in modo che l’impat-
to esercitato da questi join su quelli futuri sia trascurabile. Se nel primo join di una query a più
join vengono assemblate tabelle di grandi dimensioni, la dimensione di queste tabelle influirà su
ciascun join successivo e avrà un impatto negativo sulle prestazioni complessive della query.
L’ottimizzatore dovrebbe selezionare il percorso di join corretto; è possibile confermare i costi e
il percorso di join generando l’explain plan.
I join NESTED LOOPS risultano utili quando le tabelle coinvolte nel join hanno dimensioni
diverse; infatti è possibile utilizzare la tabella più piccola come tabella guida ed effettuare sele-
zioni dalla tabella più grande tramite un accesso basato su indice. Tanto più l’indice è selettivo,
tanto più velocemente viene completata la query.
HASH JOIN
L’ottimizzatore può decidere in modo dinamico di eseguire dei join con l’operazione HASH
JOIN al posto di MERGE JOIN o NESTED LOOPS. Questa operazione confronta due tabelle in
memoria. Durante un’operazione HASH JOIN viene eseguita la scansione della prima tabella e
il database applica le funzioni di “hash” ai dati per preparare la tabella al join. I valori derivati
dalla seconda tabella vengono letti (solitamente tramite un’operazione TABLE ACCESS FULL)
e viene utilizzata la funzione di hash per confrontare la seconda tabella con la prima. Le righe
corrispondenti vengono restituite all’utente.
L’ottimizzatore può scegliere di eseguire hash join anche se gli indici sono disponibili. Nella
query d’esempio del listato seguente, le tabelle BIBLIOTECA e BIBLIOTECA_AUTORE ven-
gono unite tramite join sulla colonna Titolo:
La tabella BIBLIOTECA ha un indice unico sulla colonna Titolo. Dato che l’indice è dispo-
nibile e può essere utilizzato per valutare le condizioni di join, l’ottimizzatore può scegliere di
eseguire un join NESTED LOOPS delle due tabelle, come mostrato nel paragrafo precedente. Se
si esegue un hash join, ciascuna tabella viene letta tramite un’operazione separata. I dati ricavati
dalle scansioni della tabella e dell’indice fungono da input per un’operazione HASH JOIN.
L’hash join non si basa su operazioni che elaborano gruppi di righe. Le operazioni coinvolte in
hash join restituiscono velocemente i record agli utenti. Gli hash join sono adatti per le query
eseguite da utenti in linea se le tabelle sono piccole e la loro scansione può essere completata in
breve tempo.
Suggerimenti
I suggerimenti possono servire per ignorare le selezioni dell’ottimizzatore relative a un metodo
di join. Con i suggerimenti è possibile specificare quale metodo di join utilizzare oppure l’obiet-
tivo di quest’ultimo.
GU I D A A L L ' O T T I M I Z Z A Z I O N E D E L L E A P P L I C A Z I O N I E D E L C O D I C E S Q L 781
Se si desidera che tutti i join di una query su più tabelle utilizzino operazioni NESTED
LOOPS, è sufficiente specificare il suggerimento USE_NL senza nessun riferimento alle tabel-
le. In generale, è opportuno indicare i nomi delle tabelle ogni volta che si utilizza un suggeri-
mento per specificare un metodo di join, perché non si sa in che modo la query verrà utilizzata in
futuro. Persino la configurazione attuale degli oggetti del database potrebbe non essere nota; per
esempio, uno degli oggetti nella clausola from potrebbe essere una vista che è stata messa a
punto per utilizzare le operazioni MERGE JOIN.
782 CAPITOLO 43
/*+ USE_NL(IO.MIA_TABELLA) */
Al contrario, è necessario fare riferimento alla tabella mediante il suo nome, senza il pro-
prietario:
/*+ USE_NL(mia_tabella) */
Se esistono più tabelle con lo stesso nome, occorre assegnare loro degli alias e farvi riferi-
mento nel suggerimento. Per esempio, nel caso in cui una tabella venga unita tramite join a se
stessa, la clausola from potrebbe includere il testo mostrato di seguito:
Nel listato seguente è possibile vedere un suggerimento che forza il join BIBLIOTECA-
BIBLIOTECA a utilizzare NESTED LOOPS e nel quale viene specificato l’alias della tabella:
/*+ USE_NL(s2) */
L’ottimizzatore ignora i suggerimenti scritti con una sintassi inadeguata. Qualsiasi suggeri-
mento scritto con una sintassi inadatta viene considerato un commento (in quanto racchiuso tra
la sequenza di caratteri /* e */).
Se si utilizzano i join NESTED LOOPS, è necessario prestare attenzione all’ordine in cui le
tabelle vengono unite tramite join. Il suggerimento ORDERED, quando utilizzato con i join
NESTED LOOPS, influisce sull’ordine con cui vengono unite le tabelle.
Quando si specifica il suggerimento ORDERED, le tabelle vengono unite nell’ordine in cui
sono elencate nella clausola from della query. Se la clausola from contiene tre tabelle, come:
le prime due tabelle vengono unite tramite il primo join e il risultato di quest’ultimo viene unito
alla terza tabella.
Dal momento che l’ordine dei join è fondamentale per le prestazioni dei join NESTED
LOOPS, il suggerimento ORDERED viene spesso utilizzato in abbinamento a USE_NL. Se si
specificano dei suggerimenti per stabilire l’ordine dei join, è necessario assicurarsi che la distri-
buzione dei valori all’interno delle tabelle da unire non cambi eccessivamente nel tempo; in caso
contrario l’ordine specificato potrebbe in futuro incidere negativamente sulle prestazioni.
È possibile utilizzare USE_MERGE per suggerire all’ottimizzatore di eseguire un’opera-
zione MERGE JOIN tra le tabelle specificate. Nel listato seguente, il suggerimento comunica
all’ottimizzatore di effettuare un’operazione MERGE JOIN tra le tabelle BIBLIOTECA e
BIBLIOTECA_AUTORE:
select BIBLIOTECA_AUTORE.NomeAutore
from BIBLIOTECA, BIBLIOTECA_AUTORE
where BIBLIOTECA.Titolo||'' = BIBLIOTECA_AUTORE.Titolo||'';
In Oracle Database 10g, l’ottimizzatore non consente alle stringhe null di bloccare l’uso
degli indici: la query utilizza l’indice sulla colonna BIBLIOTECA.Titolo come parte dell’esecu-
zione di un’operazione HASH JOIN.
Come si è già osservato durante la trattazione dell’operazione NESTED LOOPS, l’ordine
dei join è importante quanto il metodo selezionato. Se un join di grandi dimensioni o non selettivo
è il primo di una serie, la grande mole di dati restituiti influirà negativamente sulle prestazioni
dei join successivi della query, così come sulle prestazioni della query nel suo complesso.
In base ai suggerimenti, all’obiettivo prefisso e alle informazioni statistiche, l’ottimizzatore
può scegliere di utilizzare un’ampia varietà di metodi di join all’interno della stessa query. Per
esempio, l’ottimizzatore può valutare una query di tre tabelle come un join NESTED LOOPS di
due tabelle, seguito da un MERGE JOIN dell’output prodotto dall’operazione NESTED LOOPS
con la terza tabella. Combinazioni simili di tipi di join si trovano solitamente quando è attivo
l’obiettivo ALL_ROWS dell’ottimizzatore.
784 CAPITOLO 43
Per conoscere l’ordine delle operazioni, si può utilizzare il comando set autotrace on in
modo da vedere il percorso di esecuzione, come descritto in precedenza nel capitolo.
Nella query precedente, è stata aggiunta una seconda operazione, SORT ORDER BY, per la
clausola order by Editore. Dato che è possibile eseguire in parallelo anche l’operazione di ordi-
namento, la query può utilizzare nove processi sul server anziché cinque (quattro per la scansione
della tabella, quattro per l’ordinamento e uno per il coordinamento della query). L’ottimizzatore
stabilisce in modo dinamico il grado di parallelismo da utilizzare basandosi sulle impostazioni
della tabella, sul layout del database e sulle risorse di sistema disponibili.
Se si desidera disattivare l’esecuzione in parallelo di una query, è possibile usare il suggeri-
mento NO_PARALLEL (chiamato NOPARALLEL nelle versioni precedenti a Oracle Database
10g). Questo suggerimento può essere utilizzato per eseguire in modo seriale una query su una
tabella per la quale le query vengono eseguite normalmente in parallelo.
Se una tabella piccola cui si accede di frequente viene letta tramite una scansione completa,
i suoi dati possono essere mantenuti il più a lungo possibile nella SGA. È possibile contrasse-
GU I D A A L L ' O T T I M I Z Z A Z I O N E D E L L E A P P L I C A Z I O N I E D E L C O D I C E S Q L 785
gnare la tabella come appartenente al pool “Keep” utilizzando la clausola buffer_pool del co-
mando create table or alter table. Se la tabella è stata progettata per la memorizzazione nel pool
Keep, i suoi blocchi in memoria vengono tenuti separati dalla cache principale. Se il pool Keep
è dimensionato adeguatamente, i blocchi resteranno in memoria fino alla chiusura del database.
Se una tabella viene utilizzata spesso da molte query o utenti, e non esiste uno schema di
indicizzazione appropriato disponibile, è consigliabile utilizzare il pool Keep per migliorare le
prestazioni relative agli accessi alla tabella. Questo approccio risulta particolarmente utile per le
tabelle statiche.
CREATE_STORED_OUTLINES = sviluppo
In questo esempio, le strutture memorizzate verranno memorizzate per query contenute nel-
la categoria SVILUPPO.
Per creare una struttura, è necessario disporre del privilegio di sistema CREATE ANY
OUTLINE. Si utilizzi il comando create outline per creare una struttura per una query, come
mostrato nel listato seguente:
NOTA È possibile creare delle strutture per i comandi DML e per i comandi cre-
ate table as select.
Dopo aver creato una struttura, la si potrà modificare. Per esempio, potrebbe essere necessa-
rio alterare la struttura in modo che rifletta le modifiche significative nei volumi e nella distribu-
zione dei dati. Per generare di nuovo i suggerimenti utilizzati durante l’esecuzione della query si
può ricorrere alla clausola rebuild del comando alter outline:
Sempre con la clausola rename del comando alter outline è possibile rinominare una struttura:
Con la clausola change category del comando alter outline è possibile modificare la catego-
ria di una struttura.
È possibile abilitare l’uso delle strutture memorizzate impostando il parametro
USE_STORED_OUTLINES a TRUE nella propria sessione (tramite alter session) o nel proprio
database (tramite alter system).
Per gestire le strutture memorizzate, si utilizza il package OUTLN_PKG, che offre tre pos-
sibilità:
■ Eliminare le strutture che non sono mai state utilizzate.
■ Eliminare le strutture con una categoria specifica.
■ Spostare le strutture da una categoria all’altra.
Ciascuna di queste tre possibilità ha una procedura corrispondente in OUTLN_PKG. Per
eliminare le strutture che non sono mai state utilizzate, si esegue la procedura DROP_UNUSED,
come mostrato nel listato seguente:
execute OUTLN_PKG.DROP_UNUSED;
Per eliminare tutte le strutture contenute in una determinata categoria, si esegue la procedu-
ra DROP_BY_CAT, che come unico parametro di input ha il nome della categoria. L’esempio
seguente elimina tutte le strutture contenute nella categoria SVILUPPO:
execute OUTLN_PKG.DROP_BY_CAT -
(cat => 'SVILUPPO');
GU I D A A L L ' O T T I M I Z Z A Z I O N E D E L L E A P P L I C A Z I O N I E D E L C O D I C E S Q L 787
Per assegnare nuovamente le strutture da una vecchia categoria a una nuova, si esegue la
procedura UPDATE_BY_CAT, come mostrato nell’esempio seguente:
execute OUTLN_PKG.UPDATE_BY_CAT -
(old_cat => 'SVILUPPO', -
new_cat => 'TEST');
43.6 Conclusioni
Nei paragrafi precedenti sono stati illustrati i metodi utilizzati dall’ottimizzatore per accedere ai
dati e per operare su di essi. Nella messa a punto delle query, vanno tenuti presenti diversi fattori.
■ L’obiettivo dell’utente Si vuole fare in modo che le righe vengano restituite velocemente,
oppure l’attenzione maggiore è rivolta al tempo complessivo di risoluzione della query?
■ Il progetto dell’applicazione In che modo questa query si adatta al progetto complessivo
dell’applicazione? Come viene eseguita? Ci sono fattori esterni che ne influenzano le prestazioni?
■ l tipo di join utilizzati Le tabelle sono indicizzate in modo appropriato?
■ La dimensione delle tabelle Quanto sono grandi le tabelle per cui si esegue la query? Se vi
sono più join, quant’è grande la mole di dati restituita da ciascuno?
■ La selettività dei dati Quanto sono selettivi gli indici utilizzati?
■ Le operazioni di ordinamento Quante operazioni di ordinamento vengono eseguite? Vi
sono operazioni di ordinamento nidificate?
Se si riescono a gestire in modo accurato gli aspetti relativi alle prestazioni, il numero di
query “problematiche” all’interno del proprio database dovrebbe diminuire. Se ci si accorge che
una query richiede più risorse di quante dovrebbe, è consigliabile utilizzare i comandi set autotrace
on o explain plan per stabilire l’ordine delle operazioni utilizzate per la query. I suggerimenti e le
informazioni forniti nel corso di questo capitolo possono essere utilizzati per la successiva mes-
sa a punto delle operazioni o per la loro impostazione.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 44
Esempi pratici
di ottimizzazione
C
ome si è visto nel Capitolo 43, la messa a punto delle presta-
zioni inizia con la progettazione. In molti casi le prestazioni insoddisfacenti derivano da un
problema fondamentale di progettazione interno al sistema. Si potrebbe riuscire a identificare le
parti dell’applicazione che assorbono la quantità maggiore di risorse, concentrando gli sforzi di
ottimizzazione futuri su parametri specifici o su istruzioni SQL del database. In questo capitolo
verranno esaminati alcuni casi in cui vengono rilevati diversi problemi di prestazioni e la loro
risoluzione. I casi esaminati presentano tre aree problematiche comuni: problemi ambientali,
query problematiche e architettura dell’applicazione. L’analisi viene effettuata dal punto di vista
di chi si occupa della messa a punto.
La raccolta di queste statistiche è importante, sia per identificare le aree problematiche sia
per misurare l’impatto sulle prestazioni mentre l’ambiente del database e il codice SQL delle
applicazioni vengono modificati durante il processo di ottimizzazione. Ciascuna di queste stati-
stiche, o i suoi componenti, viene riportata tramite Statspack. È possibile selezionare le statisti-
che per il database perché l’ultima volta è stato avviato dalle viste delle prestazioni dinamiche,
come V$SYSSTAT e V$WAITSTAT, tuttavia tali statistiche saranno distorte dalle altre attività
del database non associate all’applicazione. La tabella che segue mostra le statistiche iniziali
raccolte nel corso di un test durato tre ore. I risultati vengono illustrati nel formato fornito al-
l’inizio del report di Statspack:
STATISTICA VALORE
Durata del test 10.800 secondi (3 ore)
Transazioni al secondo 10
In base a queste informazioni, qual è la prima area su cui concentrarsi? Il sistema era molto
attivo: 1.700 esecuzioni al secondo e 67.000 letture logiche al secondo erano la prova di un
grande numero di richieste al database eseguite costantemente in un arco di tre ore. Per analizza-
re correttamente le statistiche, si dovrebbe iniziare a trasformarle in un insieme coerente di
unità. In questo esempio, si consideri tutta l’attività in base a quanto avviene al secondo. Divi-
diamo le statistiche presentate in precedenza a livello di intervallo per 10.800 per vedere i loro
valori al secondo:
(segue)
ESEMPI PRATICI DI OTTIMIZZAZIONE 791
(continua)
Ordinamenti in memoria 74
Transazioni 10
Con tutte le statistiche presentate nelle stesse unità, è possibile sviluppare rapidamente una
panoramica di come appare in media un secondo nel database. Il numero totale di attese per
letture fisiche che si verificano in un secondo di attività normale era 3.028 + 416 = 3.444. Queste
attese venivano sostenute quando il database tentava di risolvere una richiesta di lettura fisica, e
in un secondo di attività normale c’erano 6.300 richieste di questo tipo. Pertanto una lettura
fisica era costretta ad attendere in media quasi il 55 percento del tempo (3.444 / 6.300); Solo
circa il 45 percento delle richieste di lettura venivano completate senza incorrere in attese.
Nel contempo, anche le scritture dovevano attendere. Si verificavano 55 attese di blocchi di
dati al secondo ogni 100 tentativi di effettuare scritture fisiche: ancora una volta un rapporto di
attesa del 55 percento. Un’analisi delle statistiche di I/O relative ai file di dati (disponibili trami-
te Statspack e attraverso query su V$FILESTAT) mostravano che l’attività di I/O del database
era distribuita in modo uniforme tra le tablespace più attive. Se l’I/O non fosse stato distribuito
in modo uniforme, probabilmente si sarebbe potuto attribuire la causa principale delle attese di
I/O a un disco o un gruppo di dischi che incontravano problemi.
Come ridurre il numero di attese fisiche? Se come possibili cause dei problemi di prestazio-
ni si fossero prese in considerazione solo le query che effettuano delle scansioni complete delle
tabelle, molto probabilmente l’impatto sull’applicazione sarebbe stato minimo. Le scansioni
complete di tabelle portavano alle attese di letture sparse illustrate nella tabella precedente, che
costituivano solo il 12 percento (416 / 3.444) del totale delle attese di letture fisiche. Se si fossero
eliminate completamente tutte le attese generate dalle scansioni complete di tabelle, probabil-
mente non si avrebbe avuto un influsso significativo sulle prestazioni dell’applicazione.
In base a questo scenario, è possibile formulare le ipotesi seguenti:
■ I requisiti delle applicazioni superavano la capacità di I/O del sistema così com’era
configurato.
■ L’applicazione generava un grande numero di esecuzioni di comandi SQL.
■ La maggior parte dei comandi SQL eseguiti non genera letture fisiche. Il rapporto di utilizzo
della buffer cache dei blocchi di dati supera il 90 percento (in questo caso 1 – 6.300 / 67.000).
■ L’applicazione potrebbe anche consumare grandi quantità di risorse della CPU, in quanto
esegue molti comandi e gestisce molto attivamente la coda di I/O.
In base a queste ipotesi, da dove dovrebbe iniziare il lavoro di ottimizzazione? Il profilo
ottenuto indicava un’applicazione con un’intensa attività di lettura (avvengono 6.300 letture
fisiche al secondo a fronte di solo 100 scritture fisiche). Le query stesse sembravano essere
abbastanza ottimizzate (a giudicare dal rapporto di utilizzo complessivo; è probabile che vi fos-
792 CAPITOLO 44
sero singole query non correttamente ottimizzate). Letture e scritture andavano incontro allo
stesso problema: l’impossibilità di accedere ai dischi abbastanza velocemente da evitare le atte-
se. Ne risulta che per prima cosa l’attenzione dovrebbe essere rivolta alla stabilizzazione del-
l’ambiente di I/O. Si comporta bene? Se non si riscontrano problemi nel sistema di I/O e il
codice SQL dell’applicazione non può essere cambiato, si potrebbe dover aggiornare o potenzia-
re l’ambiente per sostenere i carichi generati dall’applicazione.
Nella maggior parte delle moderne configurazioni di impresa è disponibile un’area di buffer
per l’ambiente dei dischi. Ne risulta che la maggior parte delle richieste di lettura non raggiunge
i dischi, perché vengono soddisfatte dal buffer. In questo studio circa il 10 percento delle letture
logiche generava richieste di lettura fisica. L’ambiente di I/O era concepito per gestire il 90
percento di tali richieste di lettura fisica tramite il proprio buffer. Dato che in questo ambiente il
buffer non era configurato correttamente per sostenere questo volume di attività, la maggior
parte delle richieste di lettura fisica raggiungeva il disco. Il perfezionamento dell’uso del buffer
portò a un miglioramento di tutta l'attività di I/O ed eliminò molti degli accessi al disco.
Come effetto collaterale del miglioramento dell’I/O, fu possibile ridurre i requisiti di CPU
dell’applicazione; ciò fu possibile perché il sistema non era più costretto a dedicare tutto quel
tempo alla gestione delle code di I/O e tali risorse ora invece erano disponibili per i processi
degli utenti. È possibile che alcuni altri processi sul sistema ora possano essere liberi di utilizza-
re in misura maggiore le risorse disponibili; ciò illustra la necessità di continuare a monitorare il
sistema anche una volta completata l’operazione di ottimizzazione.
Per ridurre ulteriormente il carico del sistema, le operazioni che potevano essere eseguite in
modalità batch vennero rimosse dalla parte di elaborazione in linea dell’applicazione. Per fare
un confronto, la tabella che segue mostra le statistiche in seguito all’ottimizzazione dell’ambien-
te di I/O e alla modifica dell’applicazione:
Transazioni 10
Nell’ambiente rivisto il numero di letture fisiche è stato ridotto del 40 percento, ma il nume-
ro di attese è diminuito di oltre l’80 percento. Il database era in grado di sostenere lo stesso
numero di letture logiche, transazioni e scritture fisiche (con minori attese durante le scritture) e
le prestazioni per gli utenti finali ora erano accettabili.
Ma questa non è la fine: si verificano ancora delle attese, il database crescerà nel corso del
tempo, gli utenti svilupperanno nuove query e verranno aggiunti moduli all’applicazione. In
occasione di queste modifiche, si dovrebbero tenere sotto controllo le statistiche fondamentali in
modo da isolare l’impatto delle modifiche sull’ambiente, identificare le aree problematiche e
prevedere l’evoluzione delle prestazioni.
ESEMPI PRATICI DI OTTIMIZZAZIONE 793
select T35.C1
from T35
where (lower(T35.C4) like '%tom clark%');
Sono almeno tre i difetti di questa query se dev’essere usata in un’applicazione di produzio-
ne. Se la si dovesse eseguire una sola volta, le prestazioni potrebbero essere accettabili: si effet-
tuerà una scansione completa della tabella T35 per via dei motivi elencati tra breve. Ma cosa
accade quando molti utenti concorrenti eseguono delle query simili e se la tabella T35 contiene
milioni di righe? E nel caso in cui questa query venga messa a disposizione a un mondo di utenti
tramite un’interfaccia Web? Le prestazioni dell’applicazione ne soffrono e influiscono negativa-
mente sul processo vero e proprio che essa dovrebbe supportare.
Tra i problemi della query troviamo i seguenti:
■ Non si fa alcun uso di bind variable. Tutte le esecuzioni della query saranno analizzate
separatamente, a meno che l’amministratore del database abbia impostato il parametro di
inizializzazione CURSOR_SHARING su FORCE o SIMILAR (l’impostazione preferita). Se
CURSOR_SHARING è impostato su EXACT, l’area SQL condivisa si riempirà di migliaia di
comandi quasi identici, analizzati separatamente e diversi solo per il valore letterale passato
nella stringa di ricerca.
■ Non è stato definito alcun indice basato su funzione sulla colonna C4, ma la query esegue
una funzione LOWER sulla colonna. Se è disponibile solo un indice standard. Oracle potrebbe
non essere in grado di utilizzare l’indice a supporto di questa query.
■ La stringa di ricerca inizia con un carattere jolly di percentuale. Ne risulta che ci si aspette-
rebbe che Oracle effettui una scansione completa di tabella per trovare i valori che soddisfano i
criteri.
794 CAPITOLO 44
NOTA Si dovrebbe generare l’explain plan per qualunque query che debba essere
sottoposta a ottimizzazione.
Consideriamo una possibile soluzione al terzo problema, il contenuto della stringa di ricer-
ca. In questa applicazione, l’utente ha digitato il nome (in questo caso “tom clark”) e il codice
dell’applicazione vi ha aggiunto del caratteri jolly all’inizio e alla fine nel tentativo di ottenere il
numero massimo di corrispondenze trovate. Lo sviluppatore dell’applicazione ha presentato al-
l’utente tutti i potenziali valori che potrebbero eventualmente soddisfare la stringa di ricerca
esatta.
Dal lato dell’amministrazione del database, ci si può accertare che CURSOR_SHARING
sia configurato correttamente, e si può creare un indice basato su funzione sulla colonna C4 in
modo che vengano scelte le scansioni di indice invece delle scansioni di tabella. Ma il problema
fondamentale rimane: come si può riscrivere la query in modo che selezioni il numero minore
possibile di righe per generare il proprio gruppo di risultati?
La risposta è da cercare nell’uso di Oracle Text. Come si è visto nel Capitolo 25, è possibile
creare indici di testo sulle colonne a supporto delle ricerche di stringhe, caratteri jolly, espansio-
ni di testo e altro ancora. In questo caso si passerà il nome come stringa di ricerca e l’indice di
testo cercherà le corrispondenze tra i suoi valori indicizzati, tenendo in considerazione i caratteri
jolly. Lo sviluppatore dell’applicazione dovrà modificare la query in modo che usi la sintassi di
Oracle Text e l’amministratore del database dovrà creare e mantenere gli oggetti dell’indice di
testo; tuttavia i guadagni in termini di prestazioni sono significativi, in quanto vengono elimina-
te le scansioni complete della grande tabella.
NOTA Se si utilizzano gli indici per indicizzare i nomi, è necessario creare una
stoplist vuota, altrimenti Oracle ignorerà le parole comuni (come ‘AN') che potrebbero essere
nomi reali.
In questo caso particolare, l’uso degli indici di testo ridusse decisamente i tempi di ricerca
per gli utenti che accedono tramite Web. Il numero delle letture fisiche e logiche della tabella
oggetto di ricerca si ridusse in modo significativo e rimase basso con il crescere dell’applicazio-
ne. L’amministratore del database e i responsabili della manutenzione dell’applicazione avevano
degli oggetti indice di testo aggiuntivi da gestire in cambio del guadagno di prestazioni ottenuto.
Gli indici di testo non sono una soluzione per tutti i problemi. Nella maggior parte delle
situazioni la soluzione sarà un indice contenente più colonne. L’importante è identificare le
query più voraci di risorse (interrogando V$SQL o con Statspack) e analizzarle dal punto di vista
dell’architettura dell’applicazione. Per ogni query, occorre chiedersi per che cosa viene usata e
perché fa ciò che fa. Si consideri una semplice query come la seguente:
tabelle dell’applicazione solo quando si aggiunge una nuova partizione, il tempo di fermo del-
l’applicazione è minimo, in particolare se si riescono a utilizzare solo indici locali sulle tabelle
partizionate.
L’approccio exchange partition divide efficacemente le due operazioni effettuate sulla tabel-
la, il caricamento e l’interrogazione da parte degli utenti. Una volta che si riesca a separare
queste due operazioni, le capacità di progettazione e manutenzione aumentano notevolmente.
Consideriamo ora uno scenario leggermente migliore: gli utenti devono avere a disposizione
tutti i dati in una volta, ma non interrogano direttamente la tabella in cui vengono caricati. Le
query degli utenti sono rivolte a viste materializzate basate sulla tabella. Si dovrebbero ottimizzare
le viste materializzate in modo da renderle aggiornabili rapidamente, consentendo di applicare
in modo incrementale le modifiche delle tabelle caricate agli oggetti che gli utenti interrogheran-
no. Ancora una volta la separazione dell’operazione di caricamento di massa dalle query sugli
stessi oggetti migliora decisamente le opzioni di manutenzione. Per dettagli sulla configurazio-
ne delle opzioni di aggiornamento delle viste materializzate, si rimanda al Capitolo 24.
Se gli utenti interrogano sempre delle viste materializzate che aggregano i dati, si potrebbe
considerare l’ipotesi di non caricare per nulla i dati, utilizzando invece delle tabelle esterne
(Capitolo 26) per fare riferimento ai file dei dati durante un’operazione insert as select in una
summary table. Le tabelle esterne non possono essere indicizzate, pertanto porteranno a una
scansione completa del file: dato però che non si caricano i dati grezzi, l’operazione insert as
select della summary table potrebbe risultare più veloce del caricamento dei dati e della loro
aggregazione. Come effetto collaterale, i dati dovranno essere memorizzati una sola volta (a
livello di file system) invece che due.
A prescindere da quale di queste opzioni verrà scelta, si dovrebbe analizzare la possibilità di
utilizzare opzioni che sfruttano le risorse di sistema disponibili, tra cui query parallele, DML
parallelo, caricamento parallelo, partizionamento ed elaborazione su vasta scala. In termini di
miglioramento delle prestazioni del caricamento stesso, sono disponibili molte caratteristiche:
L’uso di nologging durante i caricamenti, l’uso dei caricamenti di SQL*Loader Direct Path e
l’avvio di processi Data Pump paralleli. Si osservi che molte di queste opzioni possono essere
applicate a livello di singola partizione.
La messa a punto dei caricamenti batch richiede un giudizio preciso sul grado in cui verrà
utilizzata l’elaborazione d’insieme. È possibile configurare l’applicazione in modo che elabori
una riga alla volta. Per esempio, è possibile inserire una riga in una tabella master e quindi
inserire tutte le righe secondarie in altre tabelle prima di inserire un’altra riga nella tabella master
e ripetere il processo. L’approccio a riga singola soffrirà con l’aumento del volume delle righe.
L’approccio a riga singola garantisce una coerenza di lettura tra le tabelle caricate, ma se il
processo viene eseguito nelle ore non lavorative (o se viene utilizzato il metodo exchange partition),
questo vantaggio potrebbe non essere percepito dagli utenti.
Per confronto, è possibile creare operazioni d’insieme che elaborano grandi volumi di righe
in una sola volta. È probabile che a un certo punto il numero di righe elaborate come insieme
influirà sulle prestazioni del caricamento, in particolare se l’elaborazione implica ordinamenti
complessi. In tal caso, potrebbe essere necessario spezzare il grande processo batch in più pas-
saggi ed elaborare gruppi più piccoli. Per esempio, il flusso dell’operazione potrebbe essere il
seguente:
■ Selezionare 100.000 righe dalle tabelle di origine.
■ Effettuare le aggregazioni e trasformazioni necessarie su queste righe.
■ Memorizzare i risultati di queste aggregazioni e trasformazioni in una tabella di lavoro tem-
poranea.
■ Selezionare le successive 100.000 righe dalle tabelle di origine.
ESEMPI PRATICI DI OTTIMIZZAZIONE 797
■ Ripetere i passaggi fino a quando tutte le righe saranno state elaborate e inserite nella tabella
di lavoro temporanea.
■ Indicizzare e analizzare correttamente la tabella di lavoro temporanea.
■ Effettuare operazioni aggiuntive sui dati contenuti nella tabella di lavoro temporanea (come
la generazione di totali generali o l’esecuzione di join con altre tabelle).
■ Inserire nella tabella di produzione le righe provenienti dalla tabella di lavoro temporanea.
■ Eliminare o troncare la tabella di lavoro temporanea.
Questa sequenza di operazioni tenta di sfruttare i vantaggi di entrambi gli approcci, dando
vita a un approccio procedurale che opera su gruppi di righe. Quanto devono essere grandi questi
gruppi? Dipende dall’ambiente operativo, dalle operazioni effettuate e dai dati stessi. Si dovreb-
be collaudare correttamente il processo per accertarsi che l’approccio più procedurale venga
completato più rapidamente rispetto alla singola operazione batch. Si dovrebbe prendere in con-
siderazione il numero maggiore di potenziali punti di errore nell’approccio procedurale e gestire
di conseguenza le eccezioni.
In questo esempio, il processo di caricamento quotidiano originale richiedeva 12 ore per
essere completato. Suddividendolo in parti più piccole, il tempo totale si riduceva di tre ore,
abbastanza per eseguire il processo più volte nell’intervallo di tempo a disposizione, se necessario.
Queste decisioni di progettazione richiedono di conoscere i propri dati, come vengono uti-
lizzati e come influiscono sul processo aziendale. A prescindere dalla propria architettura, oc-
corre essere in grado di collaudare l’applicazione simulando un carico di lavoro reale in condi-
zioni ripetibili. Durante i test e durante l’uso nell’ambente di produzione, è necessario poter
monitorare l’ambiente e l’applicazione per individuare i problemi di prestazioni che possono
manifestarsi con il crescere del volume dei dati.
Durante il processo di ottimizzazione, si potrebbe dover scendere a compromessi. Per esem-
pio, nei tentativi di messa a punto dei processi batch, si potrebbe allocare più spazio su disco al
database (per la tabella di lavoro temporanea) per migliorare le prestazioni generali. Ogni parte
dell’applicazione dev’essere considerata fondamentale per l’intera applicazione e sviluppata e
pianificata di conseguenza. Quando le prestazioni dell’applicazione influiscono su quelle del
processo aziendale, si dovrebbero identificare le aree problematiche, come l’ambiente, alcune
query particolari o l’architettura del flusso dei dati, e implementare un progetto maggiormente
in sintonia con le necessità dell’applicazione.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 45
Guida a Oracle
Application Server 10g
L
o sviluppo di applicazioni per il Web è un processo comples-
so. Il numero di linguaggi di programmazione, API, framework e piattaforme di sviluppo conti-
nua a crescere a velocità impressionante. I dipartimenti di IT che desiderano mantenere il pro-
prio vantaggio competitivo sono costretti a valutare e abbracciare nuove tecnologie molto più
rapidamente di prima, portando a tempi di sviluppo più brevi per i progetti e a meno tempo
perché gli sviluppatori assorbano le nuove tecnologie. Questi fattori, assieme al fatto che agli
sviluppatori viene sempre più richiesto di avere una conoscenza pratica e di fornire consigli su
temi quali la progettazione di database, reti, metodologie di sviluppo, strumenti per la genera-
zione di codice, framework Java e gestione del codice sorgente, hanno portato a una crisi nel
mondo dello sviluppo: gli sviluppatori non hanno abbastanza ore nella giornata per imparare
tutti gli aspetti delle attività che devono svolgere per essere membri produttivi dei propri dipar-
timenti di IT. Fortunatamente per gli sviluppatori, Oracle ha fornito una serie di prodotti che
consentono di creare e collaudare le applicazioni rapidamente, si interfacciano con database
Oracle senza problemi e distribuiscono queste applicazioni sul Web in modo sicuro e con il
minimo sforzo. I prodotti per lo sviluppo di Oracle e Application Server offrono inoltre il valore
aggiunto della maturità: sono infatti tecnologie stabili e collaudate, utilizzate in una vasta gam-
ma di ambienti di produzione in tutto il mondo.
Il nucleo fondamentale per il lavoro di sviluppo è l’application server, a volte erroneamente
indicato come Web server (i Web server sono un componente secondario di un application server).
LaApplication server raccoglie le richieste provenienti da un’applicazione client (nella maggior
parte dei casi un browser Web), le elabora e restituisce i risultati. L’application server, in relazio-
ne al tipo di richieste che riceve, può chiamare altri programmi o comunicare con il database per
800 CAPITOLO 45
soddisfare la richiesta del client. Gli application server usano TCP/IP, il protocollo che definisce
le regole per stabilire le connessioni tra computer, e HTTP (Hypertext Transfer Protocol) per
controllare la comunicazione tra un browser Web e un Web server.
Oracle Application Server 10g è un prodotto concepito per far fronte a tutti gli ostacoli che
un’organizzazione deve superare quando decide di distribuire sul Web le proprie applicazioni.
Benché i dettagli relativi all’installazione e all’amministrazione dell’Application Server non
rientrino tra le finalità di questo capitolo, tutti gli sviluppatori Oracle possono trarre vantaggio
da una comprensione del sistema di riferimento di base per lo sviluppo Web e delle soluzioni
offerte da Oracle per ciascuno dei pezzi di questo sistema. Per utilizzare il linguaggio della
documentazione di Oracle, le implementazioni di queste soluzione prendono il nome di servizi e
sono integrate nello stack di prodotto di Oracle Application Server 10g.
Il numero di strumenti e servizi offerti da Oracle Application Server 10g può sembrare
enorme; di certo nessuno avrà bisogno di implementare tutti i servizi forniti. I servizi che vengo-
no installati e configurati ma non sono utilizzati sprecano risorse, pertanto si consiglia di sce-
gliere con attenzione le opzioni di installazione. Le organizzazioni possono scegliere solo i ser-
vizi che desiderano sfruttare. Anche se un particolare servizio non viene selezionato in fase di
installazione, è possibile tornare indietro e aggiungere a Oracle Application Server 10g la fun-
zionalità in questione in un secondo momento senza influire sulla configurazione di produzione
corrente.
Un buon esempio di quanto appena detto potrebbe essere Forms Server, che fa parte di
Oracle Application Server 10g: esso consente di prendere i moduli Oracle Forms esistenti e di
metterli a disposizione sul Web. Oppure può accadere che un’organizzazione abbia iniziato a
utilizzare Oracle Portal per sviluppare rapidamente alcuni moduli e report che vengono pubbli-
cati sul Web a favore dei dipendenti. Questo progetto iniziale ha guadagnato una tale popolarità
che si è deciso di spostare sul Web i moduli di Oracle Forms, i report di Oracle Reports e i fogli
di lavoro di Oracle Discoverer (che hanno degli insiemi di caratteristiche più ricchi rispetto ai
componente a essi equivalenti in Oracle Portal) e di integrare alcuni di questi componenti con
Oracle Portal. Un amministratore può riconfigurare l’Application Server per aggiungere la fun-
zionalità necessaria senza influire sul lavoro svolto fino a quel momento.
L’organizzazione può pertanto passare a un modello basato sul Web senza sprecare il tempo
e le risorse già investite nello sviluppo di Oracle Forms, Oracle Reports o Oracle Discoverer.
Con la crescita delle proprie necessità, è possibile accrescere i propri sforzi di sviluppo con delle
pagine per server PL/SQL (PSP, PL/SQL Server Pages) o con uno strumento come JDeveloper
per implementare tecnologie come JavaServer Pages (JSP), Enterprise JavaBeans (EJB), Struts o
applet Java. Se il traffico del sito cresce, è possibile migliorare le prestazioni implementando il
servizio Web Cache per memorizzare in una cache le pagine più richieste. Gli utenti avanzati
possono creare i propri report ad hoc con Discoverer. È possibile espandere il proprio portale per
integrare contenuto, componenti Web (come moduli, report o portlet XML) e contenuto prove-
niente da siti esterni con un investimento minimo in termini di tempo di sviluppo e progettazio-
ne. L’insieme di funzionalità di Oracle Application Server 10g consente di affrontare pratica-
mente tutte le sfide di sviluppo che le organizzazioni moderne si trovano ad affrontare.
L’architettura di Oracle Application Server 10g consente di scalare aggiungendo altri
Application Server (chiamati livelli intermedi nella documentazione di Oracle) e altri server
Web Cache. È persino possibile consentire ad altri di incorporare il proprio contenuto grazie
all’uso di XML e degli Enterprise JavaBeans. Tutto ciò viene gestito attraverso una singola
interfaccia Web, l’Enterprise Manager Web Site Application Server Control.
Si potrebbe obiettare che gli sviluppatori non hanno alcun bisogno di conoscere l’architettu-
ra di Oracle Application Server 10g. Tuttavia si invita seriamente a compiere uno sforzo per
capire gli elementi fondamentali grazie ai quali l’application server svolge le proprie funzioni di
base. I dettagli amministrativi di Oracle Application Server 10g probabilmente saranno di com-
GUIDA A ORACLE APPLICATION SERVER 10g 801
petenza di una amministratore di sistema o di un DBA, ma ci sono molti compiti che ricadono
sulle spalle dello sviluppatore.
mod_dms
mod_onsint Oracle
Forms 10g
mod_oprocmgr
mod_oradav
Servizi Servizi Servizi
mod_ossl di gestione del contenuto per portali di caching
mod_osso
La Tabella 45.1 elenca i diversi componenti di Oracle Application Server 10g configurati
con ciascun tipo di installazione.
In base a questa tabella, se si intendono mettere a disposizione attraverso il Web moduli
Oracle Forms, report Oracle Reports e/o cartelle e fogli di lavoro di Oracle Discoverer, è neces-
sario installare l’opzione Business Intelligence and Forms. Se si desidera utilizzare Oracle Portal
e/o sviluppare applicazioni da utilizzare con dispositivi wireless (palmari), occorre selezionare
l’opzione Portal and Wireless. Se si ha bisogno soltanto di un Web server per distribuire applica-
804 CAPITOLO 45
OC4J X X X
OracleAS TopLink X X X
OracleAS Portal X X
OracleAS Wireless X X
OracleAS Personalization X
OracleAS Discoverer X
zioni J2EE, occorre selezionare l’opzione J2EE and Web Cache. Quando si installa il livello
intermedio, si crea una “istanza” di OracleAS.
La Figura 45.2 mostra la pagina di amministrazione con tutti i servizi per un livello interme-
dio installato con l’opzione Business Intelligence and Forms.
A partire dalla versione 8.1.7, il database Oracle include un server HTTP come parte della
propria installazione. Questo fornisce solo i primi due componenti della tabella 45.1: un server
HTTP e i container OC4J.
Il secondo componente di Oracle Application Server 10g in ordine di importanza prende il
nome di infrastruttura. Si tratta di un’istanza di Oracle Application Server 10g che mantiene le
informazioni di sicurezza e di clustering. Nella documentazione di Oracle i diversi tipi di com-
ponenti di protezione forniti da Oracle prendono il nome di “Identity Management”. Il compo-
nente di Identity Management forniscono funzionalità per la gestione di directory, sicurezza e
utenti. I componenti di Identity Management sono i seguenti:
■ Oracle Internet Directory.
■ OracleAS Single Sign-On.
■ Oracle Delegated Administration Services.
■ Oracle Directory Integration and Provisioning.
■ OracleAS Certificate Authority.
Per le opzioni Business Intelligence and Forms e Portal and Wireless è necessaria un’infra-
struttura. Quest’ultima per default utilizza un database Oracle 9i per memorizzare le informazio-
ni di Identity Management, ma è possibile specificare manualmente se il database dev’essere
GUIDA A ORACLE APPLICATION SERVER 10g 805
NOTA Dal punto di vista tecnico, i server Forms e Reports possono essere
configurati in modo che non utilizzino una infrastruttura in Oracle Application Server 10g, ma
è molto più comune la scelta di usarne una.
La topologia descrive il layout delle istanze di Oracle Application Server 10g installate nella
propria organizzazione. Oracle Application Server 10g può essere installato in così tanti modi
diversi che nella guida all’installazione c’è un intero capitolo intitolato “Recommended
Topologies”. La topologia più comune implica l’installazione dell’infrastruttura su una macchi-
na e del livello intermedio su un’altra. È possibile installare l’infrastruttura e il livello interme-
dio sulla stessa macchina, a patto di disporre di sufficienti risorse di disco e di memoria (in
quanto ogni istanza deve essere installata nella propria ORACLE_HOME) o di diversi livelli
intermedi su diversi server. La Figura 45.4 presenta alcune topologie comuni. Nello sforzo di
offrire alle organizzazioni una grande flessibilità, l’infrastruttura e i livelli intermedi non devono
essere in esecuzione sulla stessa piattaforma hardware o di sistema operativo; essi tuttavia devo-
no eseguire la medesima versione del software Oracle Application Server 10g.
806 CAPITOLO 45
NOTA Dato che tutte le istanza devono eseguire la stessa versione del software,
qualunque patch applicata a un’istanza di Oracle Application Server 10g deve essere applicata
a tutte le istanze, anche se sono in esecuzione sulla stessa macchina..
SQL*Net
Internet HTTP
DBS
HTTPS
consumer
SQL*Net
Internet HTTP HTTP
DBS
HTTPS HTTPS
consumer
SQL*Net
Internet HTTP HTTP HTTP
DBS
HTTPS HTTPS HTTPS
consumer
■ Kit per sviluppatori Interfacce per la programmazione delle applicazioni (API, Application
Programming Interface) che aiutano nella creazione delle applicazioni.
I progettisti di Apache sono stati abbastanza intelligenti da capire che non avevano nessun
modo per prevedere tutti i modi possibili in cui si sarebbe potuto utilizzare il loro Web server,
pertanto lo hanno progettato con un’interfaccia aperta che incorpora un’architettura modulare
attraverso la quale è possibile aggiungere ulteriori funzionalità. Queste estensioni spesso sono
indicate con il termine mod (moduli) e iniziano tutte con il prefisso “mod_”. I moduli possono
essere collegati in modo statico al Web server o possono essere caricati in modo dinamico in fase
di esecuzione con il supporto Dynamic Shared Object (DSO) in UNIX o tramite libreria a colle-
gamento dinamico (DLL) in Windows. L’API per questi componenti modulari si basa sul lin-
guaggio di programmazione C. La Tabella 45.2 elenca i moduli in dotazione con il server Apache
fornito con Oracle Application Server 10g.
Per maggiori informazioni su Apache, si prega di consultare il sito http://www.apache.org.
mod_define Fornisce supporto per il Distributed Authoring and Versioning. No Sì (solo UNIX)
(segue)
810 CAPITOLO 45
Tabella 45.2 Moduli Apache forniti in Oracle Application Server 10g. (continua)
MODULO FUNZIONALITÀ FORNITA FORNITA SUPPORTATA
AL SERVER APACHE DA ORACLE? DA ORACLE?
mod_digest Questo modulo implementa una versione più datata No Sì
dell’autenticazione Digest MD5.
)segue)
GUIDA A ORACLE APPLICATION SERVER 10g 811
Tabella 45.2 Moduli Apache forniti in Oracle Application Server 10g. (continua)
MODULO FUNZIONALITÀ FORNITA FORNITA SUPPORTATA
AL SERVER APACHE DA ORACLE? DA ORACLE?
mod_mime_magic Questo modulo si occupa di determinare il tipo MIME di un file No Sì
analizzando alcuni byte del suo contenuto. È concepito come
“seconda linea difensiva” per i casi che mod_mime non riesce
a risolvere.
mod_so Sui sistemi operativi selezionati, questo modulo può essere utilizzato No Sì
per caricare moduli in Apache in fase di esecuzione tramite
il meccanismo Dynamic Shared Object (DSO), invece di richiedere
una ricompilazione (sperimentale).
(segue)
812 CAPITOLO 45
Tabella 45.2 Moduli Apache forniti in Oracle Application Server 10g. (continua)
MODULO FUNZIONALITÀ FORNITA FORNITA SUPPORTATA
AL SERVER APACHE DA ORACLE? DA ORACLE?
mod_speling Questo modulo tenta di correggere gli errori di ortografia No Sì
degli URL che gli utenti possono aver commesso, ignorano
l’uso delle maiuscole e consentendo la presenza al massimo
di un errore.
migliori per detenere la logica dell’applicazione e in genere sono classificate come “servizi di
logica business”. Ciò non significa che queste tecnologie si escludono a vicenda: volendo si
potrebbe infatti inserire la propria logica business in una tecnologia concepita per la presentazio-
ne dei dati (come un’applicazione JSP); ma i servizi di presentazione e di logica business sono
stati concepiti con l’idea di separare il codice che guida la logica da quello che controlla il modo
in cui gli utenti finali interagiscono con i dati, con l’intento di rendere più agevole la manuten-
zione e il potenziamento delle applicazioni, in particolare in un ambiente collaborativo dove
molti programmatori con diverse capacità e attitudini lavoreranno a un singolo progetto.
Tradizionalmente la tecnologia utilizzata per la logica business basata su Web era Enterprise
JavaBeans (EJB), l’architettura di componente sul lato server per la piattaforma Java 2 Enterprise
Edition (J2EE). La tecnologia EJB consente lo sviluppo di applicazioni distribuite, transazionali,
sicure e portabili basate sulla tecnologia Java. La specifica di EJB è una delle diverse API Java
presenti nella piattaforma J2EE. La specifica descrive in dettaglio in che modo un application
server fornisce agli oggetti sul lato server gli elementi seguenti:
■ Servizi Web.
■ Persistenza.
■ Transazioni
■ Controllo di concorrenza.
■ Eventi con il Java Messaging Service (JMS).
GUIDA A ORACLE APPLICATION SERVER 10g 813
“Quella qualità di un’istanza di dati relativa alla sua esistenza al di là e al di fuori della
durata del suo processo di creazione o della durata di altri processi che la utilizzano. In
questo contesto, persistenza normalmente viene utilizzata nella descrizione della durata
di oggetti in relazione alle sessioni, ossia se la loro durata va o meno oltre le sessioni”.
Si rimanda alla trattazione di TopLink più avanti nel capitolo nel paragrafo “Servizi del
livello di persistenza” per maggiori informazioni sullindicazione strategica di Oracle in merito
all’implementazione della persistenza per OC4J.
In aggiunta, la specifica di Enterprise JavaBean definisce i ruoli giocati dal container EJB e
dagli EJB, nonché come distribuire gli EJB in un container.
Centrale per la comprensione degli EJB è il concetto di pattern, che Sun definisce nel modo
seguente:
Una soluzione a un problema non viene considerata un pattern a meno che non vi sia un
modo per mostrare che può essere applicata a tipi di problemi ricorrenti nella definizione della
soluzione. I pattern sono descritti da cinque caratteristiche principali: contesto, problema, solu-
zione, forze e conseguenze.
Gli EJB tuttavia sono notoriamente difficili da programmare e mantenere. In risposta a que-
sto problema, Oracle ha creato un framework di servizi di logica business chiamato Business
Components for Java (BC4J), che cerca di eliminare molta della complessità degli EJB conti-
nuando a fornire tutta la loro funzionalità. Con BC4J, gli sviluppatori possono realizzare e col-
laudare la logica business orientata agli oggetti in componenti che si integrano automaticamente
con i database relazionali, riutilizzano la logica business tramite più viste dei dati e accedono a
queste viste e le aggiornano da servlet o pagine JSP.
Ci si potrebbe chiedere perché mai sia necessario memorizzare la logica business nel livello
intermedio. Dopo tutto, la maggior parte delle applicazioni Oracle non memorizza la propria
logica business in package, procedure, funzioni e trigger del database? Ci possono essere diverse
ragioni per implementare la logica business tramite BC4J:
■ Non si desidera avere una mescolanza dei paradigmi a oggetti e relazionale nella propria
applicazione.
■ L’accesso al database avverrà solo tramite client che usano BC4J.
■ Lo staff dei programmatori conosce a fondo Java e ha poca familiarità con PL/SQL.
■ Si accederà a database Oracle e non Oracle.
814 CAPITOLO 45
Alcune società potrebbero non voler essere “bloccate in Oracle”, in altre parole desiderano
avere libertà di scelta sul produttore del database. In genere questa è una scelta sconsigliata,
perché in tal modo non si potranno ottenere le prestazioni massime dall’applicazione Oracle.
Le attività di progettazione, scrittura, debug, documentazione, distribuzione e manutenzio-
ne di un framework di pattern J2EE richiedono una grande quantità di tempo e fatica. BC4J
implementa pattern per sviluppatori, offrendo loro un vantaggio notevole che consente di avere
applicazioni J2EE realizzate, distribuite e potenziate più rapidamente.
Ovviamente la memorizzazione della logica business nel livello intermedio non è un requi-
sito. Tradizionalmente gli sviluppatori Oracle memorizzano la logica business nel database Oracle
sotto forma di package, procedure, funzioni, trigger e vincoli. Per agevolare lo sviluppo di appli-
cazioni destinate al Web, Oracle fornisce un modulo Apache chiamato mod_plsql che consente
di effettuare richieste alle stored procedure del database direttamente dal browser. A partire da
Oracle 8.1.7, è stato incluso un gruppo di package chiamato PL/SQL Web Toolkit come parte dei
package incorporati nel database. Grazie a questo toolkit, è possibile generare pagine Web, inter-
rogare, recuperare e visualizzare dati tratti da un database Oracle, calcolare in modo dinamico il
contenuto delle pagine Web e molto altro ancora.
È anche possibile memorizzare la logica business in un modulo Oracle Form. Oracle
Application Server 10g, quando viene installato con l’opzione Business Intelligence and Forms,
può servire moduli Oracle Forms sul Web al browser Web di un client, dove il modulo viene
visualizzato come applet Java contenente l’interfaccia utente per il motore runtime del modulo.
Quando si invia un URL per avviare un’applicazione basata su Oracle Forms, il listener Web
accetta la richiesta e scarica l’applet Oracle Forms nel browser. Questa applet stabilisce quindi
una connessione permanente con un motore runtime Oracle Forms. Tutta l’elaborazione avviene
tra l’applet Oracle Forms e il motore runtime di Oracle Forms Services, che gestisce senza inter-
ruzioni qualsiasi query o la trasferisce al database. Oracle Forms Server può essere configurato
per utilizzare le funzionalità Single Sign-On (SSO) e Oracle Internet Directory (OID) di Oracle
Application Server 10g per rendere sicuro l’accesso. Oracle Forms può anche essere integrato in
Oracle Portal per utilizzare le sue funzionalità di pubblicazione.
Servlet 2.3
EJB 2.0
JMS 1.0.2b
JDBC 2.0
SOAP 1.1
WSDL 1.1
UDDI 2.0
816 CAPITOLO 45
Questa soluzione può essere vantaggiosa per chi ha poca esperienza con Java. Le pagine PSP
sono componenti compilati eseguiti come stored procedure Oracle. Il servizio Oracle PSP inclu-
de il PSP Compiler e il PL/SQL Web Toolkit. Le pagine Web esistenti possono essere rese dina-
miche imporporando i tag PL/SQL per eseguire operazioni sul database e visualizzare i risultati.
Dato che le pagine PSP sono eseguite come stored procedure, è importante osservare che la loro
elaborazione avviene sul database server; le altre tecnologie analizzate in questo capitolo vengo-
no eseguite sull’application server.
Figura 45.5 Una cartella di lavoro di Oracle Discoverer visualizzata tramite un browser Web.
In Oracle Application Server 10g non c’è nessun ambiente per lo sviluppo di Oracle Forms
and Reports. I componenti di Forms Server e Reports Server esistono unicamente per prendere i
moduli Oracle Forms e i report Oracle Reports e pubblicarli sul Web. Oracle Discoverer Server
ha la capacità di mettere a disposizione sul Web cartelle e fogli di lavoro di Discoverer, ma è
anche in grado di sviluppare cartelle e fogli di lavoro utilizzando un browser Web come propria
interfaccia. Questa parte di Discoverer Server, chiamata Discoverer Plus, può essere utilizzata in
sostituzione dell’Oracle Discoverer Desktop. Grazie all’interfaccia Web di Discoverer Plus, non
sarà più necessario installare il software di Discoverer Desktop su tutti i client che devono creare
e gestire cartelle e fogli di lavoro. Il programma Discoverer Administrator, utilizzato per ammi-
nistrare gli End-User Layers (EUL) e i privilegi di Discoverer, sono ancora richiesti. La Figura
45.6 illustra un foglio di lavoro di Oracle Discoverer visualizzato in Discoverer Plus.
so nuovi processi aziendali, aumentare la produttività mettendo una potenza maggiore nelle
mani degli utenti aziendali e aumentare l’efficienza tramite la condivisione delle conoscenze e
tempi di ricerca ridotti.
Oracle Portal è in grado di gestire e visualizzare praticamente qualunque tipo di dato, of-
frendo la capacità di creare portali che consentono agli utenti di accedere ad applicazioni Web,
documenti aziendali, report di business intelligence, grafici e collegamenti ad altre forme di dati
che possono trovarsi sia all’interno sia all’esterno della intranet aziendale. Le pagine di Portal
sono suddivise in regioni, che possono contenere elementi diversi come file di fogli di calcolo o
elaboratori di testi, o portlet, che forniscono accesso a risorse Web come applicazioni o altre
pagine Web. Una volta scritti e collaudati, i portlet possono essere pubblicati su pagine in cui
saranno visibili a quegli utenti che hanno accesso alle pagine. In relazione ai livelli di esperienza
degli utenti finali e alla flessibilità che si desidera offrire loro, la pagina di Portal può essere
impostata in modo che gli utenti finali possano modificare la propria pagina aggiungendo, elimi-
nando o modificando il contenuto, in modo analogo ai siti come http://my.yahoo.com. Oracle
Portal è unico nel senso che il suo ambiente di sviluppo è esso stesso un’applicazione Portal.
Una volta che sviluppatori e amministratori hanno preso confidenza con l’ambiente di Portal,
sarà facile per loro comprendere i meccanismi dello sviluppo di Portal. Grazie all’approccio allo
sviluppo di applicazioni Portal basato su procedure guidate, gli sviluppatori riusciranno a essere
produttivi in poco tempo. La Figura 45.7 illustra una schermata di sviluppo di Portal.
GUIDA A ORACLE APPLICATION SERVER 10g 819
XML Toolkit
L’Oracle XML Developer’s Kit 10g (XDK) è un gruppo di componenti, strumenti e utility scritti
in Java, C e C++ (disponibili in Oracle Database 10g e Oracle Application Server 10g) che
agevole il compito di realizzare e distribuire applicazioni XML. La produzione di Oracle XDK è
pienamente supportata e il kit viene fornito con una licenza di ridistribuzione commerciale.
Oracle XDK è costituito dai componenti seguenti:
■ Parser XML Consente di creare e analizzare XML con le interfacce DOM (Document
Object Model), SAX (Simple API for XML) e JAXP (Java API for XML Processing). L’accesso
a XMLType in Oracle Database 10g può avvenire con le informazioni DOM C unificate. Il
supporto DOM include la specifica 3.0.
■ Processori XSLT (eXtensible Stylesheet Language Transformation) Per trasformare o
effettuare il rendering di XML (ora con supporto Java XSLT 2.0).
■ VM e compilatore XSLT Fornisce un motore di trasformazione XSLT C che utilizza fogli
di stile compilati.
■ Elaboratore di schemi XML Supporto per la validazione di schemi XML. Ora include le
informazioni di validazione per l’elaborazione stream.
■ XML JavaBeans Analisi, trasformazione, confronto, recupero e compressione di docu-
menti XML tramite componenti Java.
■ Generatore di classi XML Ora con supporto JAXP, il generatore di classi XML genera
automaticamente classi a partire da DTD (Document Type Definition) e schemi XML per inviare
XML da moduli o applicazioni Web.
■ Utility SQL per XML Genera documenti XML, DTD e schemi XML da query SQL in Java
e inserisce documenti XML nei database Oracle.
■ Servlet XSQL Combina XML, SQL e XSLT nel server per fornire contenuto Web dinamico
e realizzare siti e servizi Web sofisticati che si appoggiano a database.
■ Elaboratore di pipeline XML Invoca i processi Java tramite file di controllo XML.
■ Utility TransX Agevola il caricamento di dati e messaggi di partenza globalizzati nei database
Oracle.
■ FTP Il File Transfer Protocol consente di trasferire uno o più file da un computer all’altro
attraverso Internet.
■ SMB Server Message Block è un protocollo per la condivisione tra computer di file, stam-
panti, porte seriali e astrazioni di comunicazione come named pipe e mail slot.
■ WebDAV Web Distributed Authoring and Versioning è un meccanismo che permette lo
sviluppo di pagine Web in collaborazione.
■ NFS Il Network File System è una suite di protocolli sviluppata e distribuita con licenza da
Sun Microsystems che consente a computer di diverse marche che eseguono sistemi operativi
differenti di condividere file e spazio di memorizzazione su disco.
■ AFP L’Apple Filing Protocol è un protocollo di rete di Apple per fornire accesso server/
client ai file in una rete AppleShare.
■ IMAP4 Internet Messaging Access Protocol 4 è uno standard di rete che consente agli
utenti di gestire messaggi e cartelle di posta elettronica da più posizioni e sistemi. Gli utenti
possono scegliere di memorizzare i propri messaggi sul proprio computer locale (o client) o su
un server.
■ SMTP Il Simple Mail Transfer Protocol è un protocollo utilizzato per inviare messaggi di
posta elettronica su Internet. SMTP è un insieme di regole relative all’interazione tra un pro-
gramma che invia posta elettronica e un programma che la riceve.
Gli sviluppatori possono anche creare server di protocollo personalizzati o proprietari.
L’Oracle Content Management SDK è pienamente integrato con Oracle Text, Oracle Workflow,
Oracle interMedia, Oracle Advanced Queuing e altri prodotti per API di Oracle; è inoltre inte-
grato con i prodotti per infrastruttura della piattaforma Oracle come Oracle Internet Directory.
In precedenza era noto come Oracle Internet File System.
Wireless Toolkit
Oracle Application Server Wireless (OracleAS Wireless) è una piattaforma per il controllo wireless
e vocale completa e flessibile. Le imprese possono distribuire applicazioni wireless basate su
browser, applicazioni vocali, notifiche, Java 2 Micro Edition (J2ME) e applicazioni di
messaggistica bidirezionali. OracleAS Wireless aiuta le imprese e i fornitori di servizi a realizza-
re, gestire e mantenere in modo efficiente applicazioni wireless e vocali. Tra le caratteristiche
principali di OracleAS Wireless ci sono le seguenti:
■ Multi-Channel Server Consente l’accesso alle applicazioni attraverso diversi metodi di
recapito, come SMS, accesso vocale, WAP, Pocket PC e così via. Gli sviluppatori possono con-
822 CAPITOLO 45
centrarsi sulla creazione di applicazioni mobili per qualunque canale in un unico linguaggio che
adotta standard aperti e che manterrà la propria validità nel futuro.
■ Supporto J2ME Java 2 Micro Edition fornisce un ambiente runtime leggero per dispositivi
mobili, consentendo lo sviluppo sul lato client basato su standard industriali invece che su
interfacce proprietarie.
■ J2ME Developer's Kit Offre la capacità di estendere i servizi Web a dispositivi J2ME.
■ J2ME Provisioning System Questo gestore di applicazioni Web consente di caricare appli-
cazioni J2ME nel repository del database per una gestione efficiente e una memorizzazione
sicura.
■ Notifications and Multi-Media Messaging Questa caratteristica potenzia le possibilità di
invio di messaggistica intelligente con una nuova funzionalità per avvisi azionabili, adattamento
dei messaggi e controllo di recapito con funzione failover.
■ Web Clipping Consente di ritagliare e racimolare contenuto Web esistente per creare appli-
cazioni wireless che riutilizzano applicazioni basate su browser per PC.
■ Servizi di localizzazione Danno pieno accesso alle funzionalità Location-Based Service
(LBS), come posizionamento dell’utente, geocodifica, mappatura, indicazioni di guida e ricerca
di directory aziendali.
Per sviluppare applicazioni destinate a periferiche mobili, Oracle ha creato il Wireless
Developer’s Kit, un pacchetto scaricabile che fornisce agli sviluppatori documentazione, esem-
pi, modelli di codice e procedure guidate per i costrutti di interfaccia utente mobile più comuni.
Il Wireless Development Kit può essere utilizzato su qualunque PC o portatile, sia esso connesso
alla rete o disconnesso, per realizzare e collaudare applicazioni wireless e vocali. Gli sviluppatori
possono utilizzare qualunque ambiente (IDE, Integrated Development Environment) per svilup-
pare la propria applicazione mobile, compreso Oracle JDeveloper. JDeveloper Wireless Extension
tra le proprie caratteristiche include simulatori incorporati che consentono agli sviluppatori di
vedere in anteprima l’applicazione mobile, nonché modelli di codice, procedure guidate, analisi
del codice e distribuzione automatica su server Oracle AS.
Le applicazioni wireless possono essere distribuite nei modi seguenti:
■ Hosting di servizi Oracle fornisce un servizio di hosting che mantiene le connessioni e
consente di accedere a un repository sicuro. Questo è il modo più veloce per implementare lo
sviluppo destinato a dispositivi wireless.
■ Distribuzione interna Le aziende distribuiscono e mantengono la propria infrastruttura di
protezione basata su firewall.
■ Interna con hosting di servizi Web Le aziende installano l’infrastruttura Oracle9iAS
Wireless nei propri locali utilizzando le funzioni desiderate come servizio Web.
La protezione viene fornita tramite diversi protocolli diversi, in relazione al tipo di applica-
zione wireless:
■ Applicazioni basate su browser Protette con il protocollo IEEE 802.11: HTTPS, WAP
1.2, WAP 2.0.
■ SMS (Short Message Service) Protette tramite la protezione del protocollo GPRS (General
Packet Radio Service); le applicazioni posso utilizzare Symmetric Shared Encryption Keys.
■ Posta elettronica La protezione in genere è garantita nel dominio se il mail server e
l’application server sono situati presso l’operatore mobile. Se i server si trovano presso l’azien-
da, è necessario utilizzare un canale protetto (Secure Sockets Layer [SSL] o Transport Layer
Security [TLS]).
■ Vocali HTTPS può proteggere il canale tra il gateway vocale e l’application server.
GUIDA A ORACLE APPLICATION SERVER 10g 823
■ Java Portlet Wizard Un componente aggiuntivo di JDeveloper che fornisce una utility
basata su procedure guidate per la creazione di portlet JPDK .
■ PL/SQL Generator Una utility che semplifica la creazione di portlet PL/SQL.
■ Test Suite Include le utility Provider Test e Test Harness per il collaudo di Web Providers
senza disporre di un’installazione di OracleAS Portal.
■ Esempi Vari esempi di codice che evidenziano le diverse soluzioni di sviluppo.
■ Articoli White paper per sviluppatori che spiegano in modo approfondito i problemi dello
sviluppo.
Per maggiori informazioni sullo scaricamento e l’installazione del Portal Development Kit.
consultare il sito http://portalstudio.oracle.com.
SQL*Net
Internet HTTP
HTTPS DBS
consumer
SQL*Net
Internet HTTP HTTP
HTTPS HTTPS DBS
consumer
Web Cache
di OracleAS 10g
Livello intermedio
di OracleAS 10g
■ Gestione delle prestazioni degli utenti finali Questa è la più significativa tra le nuove
caratteristiche di Web Cache. Gli amministratori possono configurare OracleAS Web Cache in
modo da misurare i tempi di risposta degli utenti per singoli URL, gruppi di URL, o persino
intere applicazioni Web, a prescindere dal fatto che gli URL siano o meno inseriti nella cache. La
funzionalità Analyze consente di visualizzare report dettagliati in contesto di gruppo, URL, do-
minio, visitatore o applicazione, nonché in un contesto giornaliero, settimanale o mensile. Un’ul-
teriore discesa nei dettagli fornisce informazioni sui tempi di risposta e sulla distribuzione del
carico per aiutare a bilanciare le risorse del Web server.
■ Protezione Web Cache ora supporta le applicazioni che richiedono l’uso di certificati SSL
sul lato client per l’autenticazione PKI. Oracle Application Server ora supporta l’hardware con-
forme a nCipher BHAPI per la distribuzione su server che eseguono la Web cache e/o il server
HTTP di Oracle.
■ Caching In precedenza gli amministratori potevano inserire nella cache una versione di una
pagina per tutti i browser o una versione per ciascun tipo e versione di browser. Ora invece
828 CAPITOLO 45
possono personalizzare le regole di caching per definire i gruppi di browser che condivideranno
una versione inserita nella cache di una pagina.
■ Invalidazione La release 9.0.4 di Web Cache introduce un meccanismo di invalidazione in
linea come strumento aggiuntivo per la gestione dell’aggiornamento del contenuto. L’invalidazione
in linea offre un utile modo con cui i server di origine possono fare sì che i messaggi di
invalidazione “cavalchino” le risposte alle transazioni inviate a Web Cache. Nelle versioni pre-
cedenti di Web Cache, la chiave di cache basata su URL era l’identificatore unico per un docu-
mento inserito nella cache. Le richieste di invalidazione devono specificare o degli URL esatti o
un insieme di URL e intestazioni corrispondenti a un’espressione regolare per invalidare gli
oggetti inseriti nella cache. Dato che per le applicazioni può essere difficile mappare gli URL
con i dati sottostanti utilizzati per generare tali URL, nella versione 9.0.4 l’invalidazione della
Web cache è stata estesa in modo da supportare le chiavi di ricerca. Gli oggetti inseriti nella
cache ora possono essere associati con più chiavi di ricerca specificate dall’applicazione, con la
chiave basata sull’URL che funge da chiave primaria.
■ Compressione Il motore di compressione di Web Cache ora supporta i criteri di compres-
sione con auto-descrizione e contenuto più comprimibile comprimendo documenti che conten-
gono URL codificati per la sessione, tag ESI tag o i tag <!--WEBCACHETAG--> e <!--
WEBCACHEEND-->.
■ Bilanciamento del carico e instradamento delle richieste Il supporto per il binding delle
sessioni in un cluster di cache cluster consente a Web Cache di legare la sessione di un utente a
un particolare Web server di origine. Questa caratteristica viene usata per instradare in modo
consecutivo le richieste di un’unica sessione allo stesso server di origine, consentendo un
bilanciamento del carico con conservazione dello stato.
■ Supporto del protocollo HTTP OracleAS Web Cache ora supporta la codifica dei trasferi-
menti parziali. Nelle versioni precedenti di Web Cache veniva utilizzato HTTP 1.0 (con keep-
alive della connessione), che causava problemi per i server che generavano contenuto dinamico
con lunghezza del contenuto sconosciuta. Il supporto di HTTP 1.1 da parte di OracleAS consen-
te di avere una connessione permanente alla Web cache, anche quando la lunghezza del contenu-
to è indeterminata.
■ Usabilità e gestibilità OracleAS Web Cache ora include delle funzioni migliori per la
registrazione degli accessi, la registrazione degli eventi e la diagnostica, il reporting sui mancati
ritrovamenti di corrispondenze nella cache più comuni, l’integrazione con Oracle Process Ma-
nagement and Notification (OPMN) e la configurazione dinamica dei parametri di selezione.
La Figura 45.9 mostra la schermata di amministrazione per il Web Cache server. La Database
Cache, introdotta in Oracle9iAS Release 1, non viene più proposta.
browser. Esistono tre modi fondamentali per mettere a disposizione la propria applicazione,
ognuno dei quali influirà sulle decisioni di sviluppo che sarà necessario prendere:
■ Intranet In questo ambiente un utente accede all’applicazione attraverso una rete interna a
una società o organizzazione, che utilizza software come quello usato su Internet ma concepito
solo per uso interno e non accessibile al pubblico. Questa opzione offre la massima flessibilità
nelle decisioni di sviluppo perché c’è una buona probabilità che gli utenti dell’applicazione
disporranno di connessioni di rete veloci e di un solo browser.
■ Extranet In questo ambiente, l’utente accede all’applicazione su una rete privata che utiliz-
za i protocolli Internet e il sistema di telecomunicazioni pubblico per condividere le informazio-
ni, i dati o le operazioni di un’azienda con fornitori o clienti esterni. Una extranet può essere
considerata come la parte esterna di una intranet aziendale. Qui le opzioni di sviluppo iniziano a
ridursi perché ci saranno questioni relative ai tipi di browser e problemi di firewall, che possono
bloccare certi tipi di comunicazioni tra i client e il server.
■ Internet In questo ambiente gli utenti possono accedere all’applicazione da qualunque
punto nel mondo. Questa opzione presenta la flessibilità minore in termini di decisioni di svilup-
po, perché l’applicazione dovrà essere abbastanza “generica” da supportare tutti i tipi di browser
e di accesso (tramite modem, a banda larga e così via). Sarà quasi impossibile offrire un’applica-
zione basata su applet con questo metodo.
Oracle Forms
Oracle Forms è uno dei più vecchi e più maturi prodotti di sviluppo di Oracle. Tradizionalmente
viene impiegato per la creazione di applicazioni client/server. Come progetto e filosofia è simile
all’ambiente di sviluppo Visual Basic di Microsoft. Oggi nel mondo esistono innumerevoli ap-
plicazioni basate su Forms che sono tuttora adottate negli ambienti di produzione.
Quando il lavoro di sviluppo ha iniziato a spostarsi verso le distribuzioni basate su Web e
browser, la richiesta di creare un ambiente che continui a supportare lo sviluppo basato su Forms
(preservando il codice legacy e le conoscenze acquisite) e introduca la distribuzione sul Web
(eliminando i costi elevati del mantenimento di client con più sistemi operativi, configurazioni
non standard e così via) ha iniziato a crescere.
Oracle Application Server 10g include un servizio chiamato Forms Server che viene instal-
lato con l’opzione Business Intelligence and Forms; questo servizio gestisce la messa disposi-
zione di moduli Oracle Forms sul Web, la raccolta di misurazioni per aiutare l’amministrazione
e l’ottimizzazione, e l’integrazione con le caratteristiche di Oracle Identity Management. Esisto-
no molti parametri di configurazione con i quali è possibile modificare qualunque aspetto del-
l’ambiente di Forms sul Web.
A partire da Oracle Forms 9i (la versione corrente è Oracle Forms 10g), Oracle non fornisce
più l’ambiente runtime di Forms per la distribuzione di moduli Forms in un ambiente client-
server tradizionale. L’unico modo per collaudare un modulo Oracle Forms sviluppato è eseguir-
lo come modulo Web attraverso un Forms Server fornito con l’ambiente di sviluppo di Oracle
Forms 10g.
Oracle Reports
Molto di ciò che si è detto di Oracle Forms si applica anche a Oracle Reports. È un prodotto
stabile e maturo che consente agli sviluppatori di creare report in modo rapido e facile. Esso
soffre anche dei costi amministrativi di distribuzione, perché le librerie runtime di Reports devo-
no essere installate e mantenute su tutte le macchine che devono eseguire Oracle Report.
Il Reports Server può essere configurato per integrarsi con le funzionalità Identity Manage-
ment di Oracle per sicurezza. Come per Oracle Forms 9i, tutte le versioni di Oracle Reports a
partire dalla 9i (la versione corrente è Oracle Reports 10g), non forniscono più l’ambiente runtime
di Reports eseguire per report Oracle Reports in un ambiente client-server tradizionale. L’unico
modo per collaudare un report sviluppato è eseguirlo come report Web attraverso un Reports
Server fornito con l’ambiente di sviluppo di Oracle report 10g.
È possibile definire più Reports Server per ciascun livello intermedio in Oracle Application
Server 10g. Questo offre un altro livello di scalabilità per il proprio ambiente. Se si desidera
integrare Reports con Oracle Portal, è possibile creare dei calendari in Portal per limitare gli
orari di accesso per certi report, Report Server e stampanti. È anche possibile utilizzare il model-
lo di protezione di Portal per limitare l’accesso a qualunque di questi componenti.
Oracle Discoverer
Come si è accennato in precedenza nel capitolo, Oracle Discoverer Server contiene un compo-
nente per visualizzare e interagire con fogli di lavoro di Discoverer sul Web (Discoverer Viewer)
e un componente per creare e modificare i fogli di lavoro (Discoverer Plus). Le capacità ad hoc
di Oracle Discoverer possono consentire al proprio staff di sviluppo di demandare la progetta-
zione e la generazione di report agli utenti avanzati. Mettendo a disposizione sul Web tutte le
GUIDA A ORACLE APPLICATION SERVER 10g 833
capacità del desktop di Discoverer, Oracle rende facile l’implementazione di Discoverer per la
maggior parte delle organizzazioni.
Discoverer inoltre si integra perfettamente con Oracle Portal tramite un portlet interno for-
nito da Oracle e chiamato il portlet di Discoverer. Questo portlet consente di definire la cartella
e il foglio di lavoro da visualizzare, qualunque parametro da passare al foglio di lavoro e
l’impostazione delle Refresh Options che consente di specificare per quanto tempo un report
particolare sarà inserito nella cache (quella di Portal, non nella Web cache). Il foglio di lavoro di
Discoverer diventa un portlet e ad esso è possibile applicare qualunque proprietà di protezione e
di visualizzazione di Portal.
Strumenti Java
In un ambiente di sviluppo integrato (IDE), gli strumenti sono stati integrati in modo da collabo-
rare un con l’altro (per esempio, l’output di uno strumento può essere impiegato come input per
un altro strumento). Il tentativo di realizzare applicazioni Java senza un IDE utilizzando il com-
pilatore Java gratuito fornito con il Java Software Development Kit di Sun è possibile, ma si
tratta di un ambiente meno che ottimale. L’IDE Java di Oracle, JDeveloper, ha così tanti stru-
menti essenziali che solo i programmatori Java più arditi tenterebbero di realizzare applicazioni
java di qualità senza di esso. Ecco un breve elenco delle caratteristiche più salienti di JDeveloper:
■ Tre modalità di profiling Queste modalità permettono di caricare un’analisi statistica delle
prestazioni della propria applicazione in termini di funzionalità, sia al momento della compi-
lazione sia in fase di esecuzione, del suo uso della memoria nello heap Java e dell’occorrenza e
durata di vari eventi.
■ Un Extension SDK pubblico Consente di estendere e personalizzare l’ambiente di sviluppo.
■ Supporto nativo per SQL, PL/SQL e XML Questo supporto include evidenziazione della
sintassi e analisi del codice, oltre a sviluppo PL/SQL, debug PL/SQL e ottimizzazione di SQL.
In aggiunta JDeveloper fornisce accesso diretto al database, consentendo di creare, visualizzare,
modificare ed eliminare tabelle, viste, trigger, indici, sequenze e altro ancora.
■ Robusto supporto di debug per Java e PL/SQL Il debug in questi due ambienti è perfet-
tamente integrato quando viene usato un database Oracle9i o versioni successive, offrendo la
possibilità di passare direttamente dal codice Java al codice PL/SQL nella stessa sessione di
debug.
■ Diagrammi di classi L’obiettivo del modellamento delle classi è visualizzare classi o com-
ponenti, e la relazione tra loro, che compongono tutto o parte del progetto di un sistema. Le
classi e i componenti modellati su un diagramma di classe sono sincronizzati per garantire che le
modifiche apportate agli elementi modellati si riflettano nei loro file di implementazione e che i
cambiamenti di questi ultimi siano visualizzati nel diagramma.
■ Diagrammi di attività I processi che hanno luogo in un’azienda o in un sistema possono
essere visualizzati utilizzando le attività modellate, i flussi e gli stati sui diagrammi di attività.
Un’attività rappresenta un singolo processo, o può rappresentare un modello di attività seconda-
ria (ossia l’attività può essere suddivisa in un insieme di attività secondarie, che formano esse
stesse un modello di attività).
■ Tutti gli aspetti dello sviluppo di EJB, dalla concezione all’implementazione Il suppor-
to per EJB include diversi aspetti: la modellazione e lo sviluppo basato su procedure guidate di
sessioni EJB; bean guidati da entità e messaggi; la capacità di aggiungere, modificare ed elimi-
nare EJB e proprietà di EJB utilizzando l’EJB Module Editor; il reverse-engineering di tabelle
del database e le relazioni a chiave esterna come bean di entità CMP (Container-Managed
834 CAPITOLO 45
HTML DB
HTML DB occupa uno spazio unico nel mondo dello sviluppo Web di Oracle. È uno strumento
di sviluppo Web, ma non fa parte del gruppo di prodotti di Oracle Application Server 10g. Il
motore di Oracle HTML DB è memorizzato nel database ed è accessibile tramite il server HTTP
fornito come standard con il database Oracle10g. È concepito principalmente per applicazioni
Web semplici che non richiedono le caratteristiche sofisticate fornite con Oracle Application
Server 10g. HTML DB è composto di tre elementi principali:
■ Application Builder Consente di assemblare un’interfaccia utente HTML sopra agli og-
getti del database. Il motore di Oracle HTML DB si preoccupa della presentazione dell’applica-
zione utilizzando modelli ed elementi di interfaccia utente.
■ SQL Workshop Consente di interagire con il database attraverso un browser Web. Con
esso è possibile visualizzare o creare oggetti del database, eseguire comandi SQL ed eseguire
query by example.
GUIDA A ORACLE APPLICATION SERVER 10g 835
■ Data Workshop Aiuta a importare dati di testo e di fogli di calcolo in tabelle del database
e di esportare dati dalle tabelle.
Tutte le applicazioni HTML DB vengono visualizzate nel browser a partire dai dati interro-
gati dal database, chiamati definizioni delle applicazioni. Questi metadati forniscono informa-
zioni sulla propria applicazione al motore HTML DB, pertanto non viene generato alcun codice
(o è necessario). Il motore di rendering di Oracle HTML DB legge la definizione dell’applica-
zione e visualizza l’applicazione di conseguenza.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 46
Guida all’amministrazione
del database
I
n questo capitolo verranno introdotti i passaggi fondamentali
coinvolti nell’amministrazione di un database Oracle Database 10g. Nel lavoro di amministrato-
re del database (DBA) rientrano diversi componenti ed esistono numerosi libri scritti apposita-
mente per i DBA. Questo capitolo offrirà una panoramica delle attività svolte da un DBA, insie-
me ad alcuni consigli sull’uso degli strumenti standard per DBA. Ciò che tuttavia il lettore non
troverà è una descrizione completa e dettagliata di tutte le attività di un DBA.
Nei capitoli precedenti sono già state illustrate molte funzioni di un DBA, come la creazione
di tabelle, indici, viste, utenti, sinonimi, database link e package. Gli argomenti trattati in questo
capitolo faranno quindi riferimento alle funzioni di controllo della produzione relative al ruolo
di DBA.
■ Creazione di un database.
■ Avvio e arresto del database.
■ Dimensionamento e gestione delle aree di memoria per il database.
■ Allocazione e gestione dello spazio per gli oggetti.
■ Creazione e gestione degli undo.
■ Esecuzione dei backup.
Per ciascuno di questi argomenti, gli sviluppatori e i DBA avranno a disposizione diverse
opzioni. I prossimi paragrafi di questo capitolo dovrebbero fornire informazioni sufficienti per
iniziare, e per imparare quali domande rivolgere ai DBA e agli amministratori del sistema. Per
ulteriori dettagli su questi argomenti, si consiglia di consultare l’Oracle DBA Handbook.
838 CAPITOLO 46
Oracle supporta il Simple Network Messaging Protocol (SNMP), e questo supporto consen-
te ai prodotti Oracle di integrarsi agevolmente negli strumenti di monitoraggio per i sistemi e le
reti.
Anche se l’impiego di OEM non è necessario, esso fornisce un’interfaccia grafica comune
utile per la gestione dei database. Man mano che l’azienda cresce in dimensioni (e nel numero di
database e DBA), la coerenza dell’interfaccia del DBA consentirà implementazioni coerenti dei
processi di controllo delle modifiche e di controllo della produzione.
OEM consente di gestire ambienti Real Application Clusters (RAC) e ambienti Grid. Con
l’offerta di un’interfaccia grafica per l’amministrazione o per il database, OEM semplifica il
processo di apprendimento per i nuovi DBA e consente di svolgere in modo facile funzioni
molto complesse.
Quando il MOUNT del database è stato eseguito ma il database non è ancora aperto, è
possibile gestirne i file. Per esempio, se alcuni file del database sono stati rimossi mentre il
database era chiuso, Oracle dovrà sapere dove potrà trovarli prima che il database venga riavviato.
Per assegnare le nuove posizioni dei file, è possibile eseguire il MOUNT del database (come
mostrato nel listato precedente), e poi usare il comando alter database per rinominare i vecchi
file nelle loro nuove posizioni. Dopo aver comunicato a Oracle le nuove posizioni per i file, si
potrà aprire il database tramite il comando alter database open.
Per chiudere il database sono disponibili quattro opzioni principali. In una chiusura normale
(quella predefinita), Oracle attende che tutti gli utenti si siano disconnessi dal database prima di
chiuderlo. In uno shutdown transactional, Oracle attende che le transazioni attive siano state
completate prima di chiudere il database. In una chiusura immediata, Oracle annulla tutte le
transazioni esistenti non ancora confermate e disconnette qualunque utente ancora connesso. In
una chiusura con interruzione, il database si arresta immediatamente e tutte le transazioni non
confermate andranno perse.
NOTA Durante la fase di avvio o arresto del database non sono consentite nuove
connessioni.
Per eseguire una chiusura normale, si utilizza il comando shutdown. Per uno shutdown
transactional, si usa shutdown transactional. Una chiusura immediata, come mostrato nel listato
seguente, usa la versione shutdown immediate del comando shutdown. Per terminare il database,
si utilizza la versione shutdown abort.
NOTA La cache per la dimensione di blocco deve esistere prima della creazione
di una tablespace che usa tale dimensione.
Le aree della cache differenti possono essere ridimensionate durante l’esecuzione del database.
Le cache dovranno essere aumentate o ridotte in unità minime. Per un database con una SGA
minore di 128M, la dimensione minima sarà 4M, quindi DB_8K_CACHE_SIZE potrà avere
come valori 4M, 8M, 12M e così via. Se si cerca di usare qualsiasi altra impostazione, Oracle la
arrotonderà per difetto (alla dimensione minima più vicina). Il listato seguente mostra l’impo-
stazione del parametro DB_8K_CACHE_SIZE.
Se si crea una tablespace che utilizza una dimensione di blocco di database non predefinita,
occorre essere certi che il parametro corrispondente per la dimensione della cache (per esempio
GUIDA ALL’AMMINISTRAZIONE DEL DATABASE 841
DB_8K_CACHE_SIZE) sia stato aggiornato nel file dei parametri del database. Se si usa un file
init.ora, lo si dovrà aggiornare con il nuovo valore. Se invece si utilizza un file dei parametri di
sistema (il metodo preferito), questo verrà aggiornato automaticamente quando si esegue il co-
mando alter system con la clausola scope=both.
Oracle gestirà lo spazio delle buffer cache tramite un algoritmo che mantiene il più a lungo
possibile nella memoria i blocchi utilizzati con maggior frequenza. Quando nella cache è neces-
sario dello spazio libero, i nuovi blocchi di dati utilizzeranno lo spazio occupato da blocchi cui
si accede raramente oppure quello occupato da un blocco modificato dopo che è stato copiato sul
disco.
Se la SGA non è abbastanza grande per contenere i dati più utilizzati, oggetti diversi si
contenderanno lo spazio all’interno della buffer cache del blocco di dati. Il conflitto è più proba-
bile che si verifichi quando più applicazioni usano il medesimo database e quindi condividono la
stessa SGA. In questo caso, le tabelle e gli indici utilizzati con maggiore frequenza da ciascuna
applicazione si contendono costantemente lo spazio nella SGA con gli oggetti utilizzati più di
recente presi dalle altre applicazioni. Di conseguenza, le richieste di dati dalla buffer cache del
blocco di dati comporteranno un rapporto inferiore tra “accessi riusciti” e “accessi non riusciti”.
La buffer cache del blocco di dati manca il risultato negli I/O fisici per quanto riguarda le letture
dei dati, portando così a un calo delle prestazioni.
Lo shared pool memorizza la cache del dizionario dati (informazioni relative alle strutture di
database) e la library cache (informazioni su istruzioni che vengono eseguite sul database).
Mentre la buffer cache del blocco di dati e la cache del dizionario dati abilitano la condivisione
di informazioni strutturali e di informazioni sui dati tra gli utenti nel database, la library cache
consente la condivisione di istruzioni SQL utilizzate comunemente.
Lo shared pool contiene il piano di esecuzione e la struttura di analisi per le istruzioni SQL
eseguite sul database. Quando un utente qualsiasi esegue per la seconda volta la medesima istru-
zione SQL, Oracle potrà sfruttare le informazioni di analisi disponibili nello shared pool per
velocizzare l’esecuzione dell’istruzione. Come accade per la buffer cache del blocco di dati,
anche lo shared pool è gestito tramite un algoritmo LRU. Via via che lo shared pool si riempie,
i percorsi di esecuzione e le strutture di analisi utilizzati meno recentemente verranno rimossi
dalla library cache per far spazio alle nuove voci. Se lo shared pool è troppo piccolo, le istruzioni
verranno ricaricate continuamente nella library cache, influendo così sulle prestazioni.
La dimensione (in byte) dello shared pool viene impostata tramite il parametro di
inizializzazione SHARED_POOL_SIZE. Come per le altre cache, anche la dimensione dello
shared pool può essere alterata mentre il database è aperto.
A partire da Oracle Database 10g, è possibile utilizzare la funzione Automatic Shared Memory
Management (ASMM). Per attivare ASMM, occorre impostare un valore diverso da zero per il
parametro di inizializzazione del database SGA_TARGET. Dopo aver impostato SGA_TARGET
alla dimensione della SGA desiderata (ossia alla somma di tutte le cache), si imposta a 0 ciascu-
no degli altri parametri relativi alla cache (DB_CACHE_SIZE, SHARED_POOL_SIZE,
JAVA_POOL_SIZE e LARGE_POOL_SIZE). Perché queste modifiche diventino effettive oc-
corre arrestare e riavviare il database; quest’ultimo inizierà poi a gestire attivamente le dimen-
sioni delle diverse cache. È possibile monitorare le dimensioni delle cache in qualunque mo-
mento tramite la vista di prestazioni dinamica V$SGASTAT.
Quando il carico cambia, il database modificherà le dimensioni delle cache per riflettere le
necessità dell’applicazione. Per esempio, se di notte si ha un forte carico dovuto alle elaborazio-
ni batch e un carico più intensivo legato alle transazioni in linea durante il giorno, il database
potrebbe modificare le dimensioni delle cache al variare del carico. Questi cambiamenti avven-
gono automaticamente, senza intervento del DBA. Se si specifica un valore per un pool nel
proprio file dei parametri di inizializzazione, Oracle lo utilizzerà come valore minimo per quel
pool.
NOTA I DBA possono creare nella buffer cache dei pool KEEP e RECYCLE, che
non risentono del dimensionamento dinamico delle cache.
Da OEM è possibile vedere se la gestione dinamica della memoria è abilitata facendo clic
sull’opzione Memory Parameters; il pulsante Automatic Shared Memory Management può es-
sere impostato su Enabled o Disabled.
specifiche. In questa tablespace si genera un segmento per contenere i dati associati a quell’og-
getto.
Un segmento è costituito da sezioni chiamate extent, ossia gruppi attigui di blocchi Oracle.
Quando gli extent esistenti non possono più contenere dati nuovi, il segmento otterrà un altro
extent. Se un segmento è composto da più extent, non esiste garanzia alcuna che questi extent
siano contigui.
È possibile creare le tablespace in modo che vengano gestite a livello locale (impostazione
predefinita) oppure gestite a livello di dizionario. In una tablespace gestita a livello di dizionario,
le informazioni sulla posizione degli extent verranno memorizzate nel dizionario, mentre in una
tabella gestita a livello locale, questi dati verranno memorizzati nelle intestazioni del file di dati.
Oracle incoraggia l’uso delle tablespace gestite a livello locale. Per riassumere, i database hanno
una o più tablespace, le quali sono costituite da uno o più file di dati. All’interno di queste
tablespace, Oracle memorizza segmenti per gli oggetti di database. Ciascun segmento può avere
più extent.
La gestione dello spazio utilizzato dalle tablespace, dai file di dati, dai segmenti e dagli
oggetti di database è una delle funzioni base del DBA. Lo scopo di questa introduzione generale
è aiutare nella pianificazione della loro memorizzazione fisica. Come si vedrà, Oracle Database
10g aggiunge nuove caratteristiche che agevolano la pianificazione e la gestione dello spazio.
Quando si crea una tabella, un indice oppure un altro segmento, è possibile utilizzare i valori
predefiniti di una tablespace gestita a livello locale (opzione consigliata), oppure si può specifi-
care una clausola storage nel comando create. Inoltre è possibile specificare anche una clausola
tablespace con la quale si potrà indicare a Oracle di memorizzare i dati in una determinata
tablespace. Per esempio, un comando create table in una tablespace gestita a livello di dizionario
potrebbe includere le clausole seguenti:
tablespace USERS
storage (initial 1M next 1M pctincrease 0
minextents 1 maxextents 200)
tablespace USERS
vo), maxextents (il numero massimo di extent) e minextents (il numero minimo di extent). Dopo
aver creato il segmento, i valori iniziale e minextents non potranno essere modificati a meno che
non si esegua una riorganizzazione dell’oggetto. Nelle viste DBA_TABLESPACE e USERS_TA-
BLESPACE sono disponibili i valori predefiniti dei parametri di memorizzazione per ciascuna
tablespace.
Quando si crea una tablespace, se ne specificano anche i parametri di memorizzazione
predefiniti. Il comando seguente crea una tablespace gestita a livello di locale e ne specifica i
parametri di memorizzazione predefiniti. Per la sintassi di create tablespace si rimanda al Capi-
tolo 48.
Quando si crea un segmento, questo acquisirà almeno un extent. L’extent iniziale servirà per
memorizzare i dati fino a quando non avrà più spazio libero disponibile (la clausola pctfree può
essere utilizzata per riservare una certa percentuale di spazio libero all’interno di ciascun blocco
nel segmento, in modo che sia disponibile per gli aggiornamenti delle righe già esistenti). Se si
crea una tablespace gestita a livello di dizionario, le dimensioni degli extent potrebbero non
essere uniformi; il segmento si estenderà ottenendo un secondo extent con una dimensione spe-
cificata dal parametro next. Per default, le tablespace verranno create con la gestione locale degli
extent.
Partendo dal presupposto che in questo esempio la dimensione del blocco per il database in
cui è stata creata questa tablespace sia pari a 4KB, la tablespace è stata creata con una gestione
degli extent dichiarata come local e con una dimensione uniforme pari a 256KB. Ciascun bit
nella bitmap descrive 64 blocchi (256/4). Se la clausola uniform size viene omessa, l’impostazione
predefinita sarà autoallocate. La dimensione predefinita per uniform è 1MB.
Le tablespace gestite a livello locale sono in grado di assumere alcune delle attività di ge-
stione dello spazio svolte dai DBA nelle tablespace gestite a livello di dizionario. Considerata la
loro architettura, sono più difficili da frammentare ed è raro che i loro oggetti presentino proble-
mi di spazio.
Esiste la possibilità di creare un insieme di tablespace gestite a livello locale con un numero
ridotto di parametri di memorizzazione e risolvere così la maggior parte delle richieste di spazio
nel database. Per esempio, si potrebbero creare tre tablespace DATI, come mostrato di seguito:
In questo esempio, la tablespace DATI_PICCOLA crea degli oggetti con dimensioni di extent
pari a 1MB; DATI_MEDIA utilizza dimensioni dell’extent pari a 4MB, mentre DATI_GRANDE
usa dimensioni di extent pari a 16 MB. Se si ha una tabella di piccole dimensioni, sarà sufficiente
inserirla nella tablespace DATI_PICCOLA. Se la sua dimensione aumenta in maniera significa-
tiva, la si potrà spostare nelle tablespace DATI_MEDIA o DATI_GRANDE.
In ciascuna di queste tablespace di esempio, tutti gli oggetti avranno gli stessi parametri di
memorizzazione, semplificando così qualunque operazione di gestione. L’uso di dimensioni
coerenti dell’extent migliora anche il riutilizzo dello spazio dopo che un oggetto è stato elimina-
to o rimosso dalla tablespace.
I prossimi paragrafi descrivono la gestione dello spazio per ciascuno dei principali tipi di
oggetti. Si osservi che con le tablespace gestite a livello locale, molti dei problemi legati alle
clausole storage non si verificheranno; si farà affidamento sulla tablespace per gestire lo spazio
basato sui parametri definiti a livello della tablespace. Anche se ciò potrebbe comportare una
certa allocazione eccessiva di spazio, semplificherà enormemente le operazioni per la gestione
dello spazio nel database.
Segmenti di tabella
I segmenti di tabella, chiamati anche segmenti di dati, memorizzano le righe di dati associati alle
tabelle o ai cluster. Ciascun segmento di dati contiene un blocco di intestazioni che funge da
directory di spazio per il segmento.
Dopo aver acquisito un extent, un segmento di dati manterrà questo extent fino a quando non
verrà eliminato, troncato (con truncate) o compresso con le opzioni di Oracle Database 10g. La
cancellazione di alcune righe da una tabella tramite il comando delete non influisce sulla quan-
tità di spazio che è stata allocata per quella tabella. Il numero di extent continuerà ad aumentare
fino a quando (1) non si raggiungerà il valore maxextents (se ne è stato impostato almeno uno),
(2) non si raggiungerà la quota dell’utente nella tablespace oppure (3) la tablespace esaurirà lo
spazio disponibile (nel caso in cui i file di dati non siano in grado di estendersi da soli).
Per ridurre al minimo la quantità di spazio sprecato in un blocco di dati, è possibile regolare
il parametro pctfree, che specifica quanto spazio verrà mantenuto libero all’interno di ogni
blocco di dati. Questo spazio libero potrà quindi essere impiegato quando le colonne con valore
NULL verranno aggiornate per contenere dei valori, oppure quando aggiornamenti di altri valori
nella riga comporteranno l’aumento della lunghezza totale della riga. L’impostazione corretta di
pctfree è specifica dell’applicazione, poiché dipende dalla natura degli aggiornamenti effettuati.
Il comando alter table può servire per alterare moltissimi parametri di memorizzazione di
una tabella già esistente. L’opzione move del comando alter table può essere utilizzata per modi-
ficare l’assegnamento della tablespace per una tabella.
Segmenti di indice
Come i segmenti di tabella, anche i segmenti di indice contengono lo spazio in essi allocato fino
a quando non vengono rimossi; tuttavia, possono essere rimossi anche indirettamente se la tabel-
la o il cluster che indicizzano vengono rimossi. Per ridurre al minimo il conflitto, gli indici
dovrebbero essere memorizzati in una tablespace diversa da quella che contiene le loro tabelle
associate.
846 CAPITOLO 46
I segmenti di indice contenuti nelle tablespace gestite a livello di dizionario hanno delle
clausole storage che ne specificano i valori iniziale (initial), successivo (next), minextents,
maxextents e pctincrease e sono meno soggetti a frammentazioni rispetto alle loro tabelle.
L’opzione rebuild del comando alter index può essere utilizzata per alterare le impostazioni
storage e tablespace di un indice. Nel listato seguente viene ricostruito l’indice JOB_PK nella
tablespace INDEX.
Successivamente, nel file dei parametri di sistema o nel file init.ora si dovrà impostare il
parametro di inizializzazione UNDO_MANAGEMENT a AUTO. Si specifichi la tablespace di
undo tramite il parametro di inizializzazione UNDO_TABLESPACE. All’interno della tablespace
di undo non sarà necessario creare o gestire segmenti di rollback.
UNDO_RETENTION=600
GUIDA ALL’AMMINISTRAZIONE DEL DATABASE 847
Oracle farà del suo meglio per conservare nel database tutti i dati di undo su cui è stato eseguito
il commit per almeno 600 secondi. Con un’impostazione di questo genere, qualsiasi query che
richieda meno di 10 minuti non dovrebbe comportare un errore ORA-1555 (“Snapshot too old”).
Durante l’esecuzione del database, è possibile modificare il valore del parametro UNDO_RETEN-
TION con il comando alter system. A partire da Oracle Database 10g, è possibile utilizzare i
comandi create tablespace e alter tablespace per costringere Oracle a garantire che la conserva-
zione degli undo richiesta venga mantenuta anche a spese delle transazioni correnti.
In un database già esistente, è possibile utilizzare il comando create tablespace per creare
una tablespace di undo:
Per la sintassi completa del comando create tablespace, si rimanda al Capitolo 48.
Dopo aver creato una tablespace di undo, la si potrà gestire con il comando alter tablespace.
Per esempio, si potranno aggiungere dei file di dati alla tablespace di undo oppure rinominare i
file di dati già esistenti, come si farebbe per qualsiasi altra tablespace. Per bloccare l’uso di una
tablespace come tablespace di undo, si usa il comando alter system per impostare un nuovo
valore per il parametro di inizializzazione UNDO_TABLESPACE, oppure si modifica questo
parametro durante una procedura di chiusura/avvio del database.
Segmenti temporanei
I segmenti temporanei memorizzano dati temporanei durante le operazioni di ordinamento (come
query di grandi dimensioni, creazioni di indici e unioni). Ciascun utente possiede una tablespace
temporanea che viene specificata quando si crea l’account tramite create user, oppure lo si altera
tramite alter user. La tablespace temporanea dell’utente dovrà essere una tablespace designata
come tablespace temporanea; a partire da Oracle9i, le tablespace permanenti non possono più
essere utilizzate per questo scopo.
Quando si crea un database, è possibile specificare una tablespace temporanea predefinita
per tutti gli utenti. Per un database già esistente, si potrà modificare la tablespace predefinita con
il comando alter database, come mostrato nel listato seguente:
Quando si altera l’assegnamento della tablespace temporanea predefinita del database, gli
utenti cui era stata assegnata la vecchia tablespace temporanea predefinita verranno reindirizzati
alla nuova tablespace temporanea predefinita. Per visualizzare la corrente tablespace tempora-
nea predefinita si esegua la query seguente:
848 CAPITOLO 46
select Property_Value
from DATABASE_PROPERTIES
where Property_Name = 'DEFAULT_TEMP_TABLESPACE';
Con il comando create temporary tablespace è possibile specificare una tablespace come
“temporanea”. Una tablespace temporanea non può essere utilizzata per contenere segmenti per-
manenti, ma solo segmenti temporanei creati durante le operazioni. La prima operazione di
ordinamento che utilizza la tablespace temporanea alloca un segmento temporaneo nella tablespace
temporanea; quando la query è completata, lo spazio usato dal segmento temporaneo non viene
rimosso. Al contrario, lo spazio utilizzato dal segmento temporaneo potrà essere usato da altre
query, permettendo così all’operazione di ordinamento di evitare i costi di allocazione e rilascio
dello spazio per i segmenti temporanei. Se l’applicazione ricorre di frequente ai segmenti tem-
poranei per le operazioni di ordinamento, il processo di ordinamento dovrebbe dare risultati
migliori se si utilizza una tablespace temporanea dedicata.
A partire da Oracle Database 10g, è possibile creare più tabelle temporanee e raggrupparle.
Per prima cosa, è necessario assegnare le tablespace temporanee a gruppi di tablespace attraver-
so la clausola tablespace group del comando create temporary tablespace o alter tablespace.
Quindi si può specificare il gruppo come tablespace predefinita di un utente. I gruppi di tablespace
possono aiutare a supportare operazioni parallele che implicano ordinamenti. Per dedicare una
tablespace già esistente ai segmenti temporanei, si specifica la clausola temporary dei comandi
create tablespace o alter tablespace, come mostrato nel listato seguente:
Per permettere alla tablespace TEMP di memorizzare oggetti permanenti (non temporanei),
occorre utilizzare la clausola permanent dei comandi create tablespace o alter tablespace, come
mostrato nel listato seguente:
La colonna Contents nella vista del dizionario dati DBA_TABLESPACE visualizza lo stato
della tablespace come “TEMPORARY” o “PERMANENT”.
Spazio libero
Un extent libero in una tablespace è una collezione di blocchi liberi adiacenti nella tablespace.
Una tablespace potrebbe contenere più extent di dati ed extent liberi. Quando un segmento viene
rimosso, l’allocazione dei suoi extent non viene annullata per default e questi ultimi non vengo-
no contrassegnati come liberi. A partire da Oracle Database 10g, il comportamento predefinito
prevede la conservazione dello spazio mentre l’oggetto si sposta nel cestino dell’utente. È possi-
bile recuperare quell’oggetto dal cestino tramite il comando flashback table to before drop (Ca-
pitolo 28). Lo spazio può essere liberato dal cestino con il comando purge (fare riferimento al
Capitolo 48).
Nelle tablespace gestite a livello di dizionario, non sempre gli extent liberi vengono
ricombinati con gli extent liberi adiacenti; le barriere tra questi extent potrebbero rimanere. Il
processo di background SMON (System Monitor) unisce periodicamente gli extent liberi adia-
centi, sempre che il parametro predefinito pctincrease per la tablespace sia diverso da zero.
GUIDA ALL’AMMINISTRAZIONE DEL DATABASE 849
Per spingere la tablespace a unire il suo spazio libero, si utilizza la clausola coalesce della
clausola alter tablespace, come mostrato nel listato seguente:
Il comando precedente obbligherà gli extent liberi vicini contenuti nella tablespace DATI a
unirsi in extent liberi più grossi. Il comando unirà un massimo di otto aree separate, proprio
come SMON.
NOTA Il comando alter tablespace non unirà extent liberi che siano separati da
extent di dati.
Le tablespace gestite a livello locale non richiedono lo stesso grado di gestione dello spazio
libero. Dato che esiste la possibilità di configurare le tablespace gestite a livello locale in modo
che abbiano dimensioni di extent coerenti per tutti i segmenti, gli extent rimossi vengono facil-
mente riutilizzati.
Quando si alloca un nuovo extent, Oracle non unirà gli extent liberi adiacenti, a meno che
non si tratti dell’unica alternativa possibile. Nelle tabelle gestite a livello di dizionario, questo
può far sì che un extent di grandi dimensioni collocato verso il fondo della tablespace venga
utilizzato, mentre gli extent liberi più piccoli, posizionati all’inizio della tablespace, non venga-
no quasi mai utilizzati. Nella tablespace, gli extent liberi di piccole dimensioni diventano così
dei “riduttori di velocità”, in quanto non hanno una dimensione adeguata per essere utili. Man
mano che questo modello di uso avanza, la quantità di spazio sprecato nella tablespace aumenta.
In un database ideale, tutti gli oggetti sono creati della loro dimensione appropriata, e tutto
lo spazio libero viene sempre memorizzato insieme, un gruppo di risorse pronto all’uso. Se si
riesce a evitare l’allocazione dinamica di spazio durante l’utilizzo dell’applicazione, si elimine-
ranno un impatto sulle prestazioni e una fonte di potenziali errori dell’applicazione.
RowID, il numero di extent nella tabella non dev’essere considerato come fattore nelle presta-
zioni di lettura. Oracle leggerà ogni riga dalla sua posizione fisica (come specificato in RowID)
e recupererà i dati.
Per evitare che le dimensioni di extent provochino cali di prestazioni, si dovrà scegliere tra
una delle strategie seguenti:
1. Creare extent che siano molto più grandi della dimensione del buffer di I/O del proprio
sistema operativo. Se gli extent sono molto grandi, le letture aggiuntive necessarie saranno davvero
poche anche se la dimensione di extent non è un multiplo della dimensione del buffer di I/O.
2. Impostare DB_FILE_MULTIBLOCK_READ_COUNT in modo da sfruttare pienamente la
dimensione del buffer di I/O a favore del sistema operativo. Un’impostazione troppo alta di
questo valore potrebbe indurre l’ottimizzatore a pensare che le scansioni intere di tabelle siano
più efficienti di quello che in realtà sono, provocando così dei cambiamenti ai piani di esecuzio-
ne già esistenti.
3. Se si devono creare extent di piccole dimensioni, si scelgano dimensioni di extent che siano
multipli della dimensione del buffer di I/O del sistema operativo.
Per massimizzare il riutilizzo degli extent liberi rimossi nelle tablespace gestite a livello di
dizionario, si utilizza un insieme di dimensioni di extent che soddisfa il criterio seguente: ogni
dimensione di extent conterrà un multiplo intero per ogni dimensione di extent più piccola.
L’implementazione più semplice di questa regola consiste nel creare dimensioni di extent che
aumentano esattamente del doppio: 1MB, 2MB, 4MB, 8MB, 16MB, 32MB. Per ridurre il nume-
ro delle dimensioni di extent da gestire, si possono quadruplicare i valori invece di raddoppiarli:
1MB, 4MB, 16MB e così via. L’uso di questi valori per le dimensioni di extent eliminerà i
problemi di I/O e migliorerà le possibilità di riutilizzare gli extent rimossi.
In questo esempio, vengono create tre tablespace DATI separate, con dimensioni di extent
pari a 1MB, 4MB e 16MB. Se si deve generare una tabella con una dimensione di 3MB, la si
potrà creare utilizzando tre extent da 1MB in DATI_1M oppure con un extent da 4MB in
DATI_4M. Una tabella che raggiungerà i 10MB potrà essere inserita in DATI_16M.
Man mano che le dimensioni delle tabelle aumentano, le clausole di memorizzazione
predefinite cresceranno in modo coerente, seguendo le regole di spazio e gli standard per le
dimensioni di extent. Sarà la volta di DATI_64M, seguito da DATI_256M e DATI_1G. Si utiliz-
852 CAPITOLO 46
zano le stesse dimensioni di extent tra i database per semplificare la gestione dello spazio del-
l’intero ambiente di database.
Mentre le dimensioni di extent crescono, la distribuzione delle medesime nelle tablespace
comporterà una separazione dei tipi di tabelle: le tabelle statiche di piccole dimensioni verranno
isolate nelle tablespace con dimensioni di extent piccole, mentre le tabelle per l’elaborazione di
grandi transazioni (o le loro partizioni) verranno segregate nelle tabelle con dimensioni di extent
elevate, semplificando le future attività di gestione e messa a punto.
■ Il carico di lavoro dell’I/O verrà distribuito in modo dinamico tra i dischi disponibili, senza
intervento del DBA.
■ La larghezza dello stripe di I/O verrà mantenuta a diversi livelli per diversi tipi di file, tutti
mantenuti dal database.
■ È possibile abilitare il mirroring software se non si è adottata la soluzione del mirroring
hardware.
Configurazione di ASM
Per utilizzare ASM, è necessario configurare un’istanza di ASM. Innanzi tutto occorre specifica-
re ‘ASM’ come valore per il parametro di inizializzazione INSTANCE_TYPE (il valore predefinito
è ‘RDBMS’):
INSTANCE_TYPE = ASM
Si può quindi utilizzare il comando create diskgroup con i dischi disponibili. Per esempio, i
dischi disponibili potrebbero essere quattro:
La clausola external redundancy significa che il gruppo dei dischi adotta una soluzione di
mirroring hardware. Per utilizzare il mirroring software, occorre usare la clausola normal
redundancy e specificare i dischi appartenenti al gruppo mirror con la clausola failgroup. Con il
mirroring software, Oracle utilizza il gruppo mirror come gruppo di dischi, non come mirror uno
a uno dei dischi del gruppo.
Per vedere i dischi che costituiscono un gruppo di dischi, è possibile interrogare la vista
dinamica V$ASM_DISK.
Ora che il gruppo di dischi è disponibile, occorre creare una tablespace che lo utilizzi, come
illustrato nell’esempio seguente:
Oracle Creerà il file di dati per la tablespace USERS2 nel gruppo di dischi specificato e
gestirà i suoi requisiti di I/O tra i dischi disponibili. Se s devono aggiungere altri dischi al grup-
po, occorre usare il comando alter diskgroup:
opzioni possono essere utilizzate per recuperare lo spazio inutilizzato nei segmenti, valutare le
esigenze di spazio future e riorganizzare le tabelle in linea.
Se la propria applicazione cancella di frequente righe da una tabella, i blocchi di quella
tabella potrebbero essere solo parzialmente riempiti di righe. È possibile comprimere manual-
mente lo spazio nella tabella con il comando alter table. Per prima cosa, si devono abilitare gli
spostamenti di righe nella tabella:
Poi occorre indicare a Oracle di spostare le righe nella tabella per comprimere l’allocazione
delle righe nei blocchi:
L’operazione shrink space compact riorganizzerà le righe della tabella in modo che possano
essere memorizzate in modo più compatto. Tuttavia, l’high watermark per la tabella, ossia il
numero massimo di blocchi in cui le righe sono mai state scritte, rimane inalterato. Dal momento
che tutte le scansioni complete della tabella leggeranno tutti i blocchi fino all’high watermark, è
necessario regolare quel valore. Con le versioni precedenti a Oracle Database 10g, è possibile
modificare l’high watermark solo ricostruendo o troncando una tabella. A partire da Oracle
Database 10g, è possibile regolare il valore dell’high watermark con la clausola shrink space del
comando alter table. Per esempio:
È possibile far ricadere a cascata gli effetti di questa modifica sugli indici della tabella con
l’opzione shrink space cascade.
Per prevedere l’uso dello spazio, è possibile utilizzare la funzione
OBJECT_GROWTH_TREND del package DBMS_SPACE, passandole come parametri il nome
dello schema, il nome dell’oggetto e il tipo di oggetto, come illustrato nel listato seguente. Que-
sto comando dev’essere eseguito come utente con privilegi SYSDBA.
select * from
table(DBMS_SPACE.OBJECT_GROWTH_TREND
('PRACTICE','BIBLIOTECA_PRESTITO','TABLE'));
è indispensabile spostare la tablespace con le tabelle base degli indici come parte integrante del
medesimo insieme di tablespace trasportabile. Meglio si organizzano e si distribuiscono gli og-
getti tra le tablespace, più facile sarà creare un insieme autonomo di tablespace da trasportare.
Per trasportare le tablespace, è necessario generare un insieme di tablespace, copiarlo o
spostarlo nel database nuovo e infine inserirlo nel nuovo database. I database devono trovarsi
sullo stesso sistema operativo, con la medesima versione di Oracle e lo stesso set di caratteri.
execute DBMS_TTS.TRANSPORT_SET_CHECK('AGG_DATA,AGG_INDEXES',FALSE);
modalità di lettura e scrittura nel loro database corrente. Dopo aver generato il gruppo di tablespace
trasportabili, è possibile spostare i suoi file (compresa l’esportazione) in un’area cui il database
di destinazione può accedere.
Nell’importazione, si specificano i file di dati che fanno parte del gruppo di tablespace
trasportabili. Facoltativamente è possibile specificare le tablespace (con il parametro
TABLESPACES) e i proprietari degli oggetti (con il parametro OWNERS).
Una volta completata l’importazione, tutte le tablespace del gruppo rimangono in modalità
di sola lettura. È possibile impartire il comando alter tablespace read write nel database di desti-
nazione per portare le nuove tablespace in modalità di lettura e scrittura.
NOTA Per il resto del capitolo i termini Export e Import faranno riferimento alle
versioni precedenti di queste utility, non alle versioni Data Pump.
Export e Import
L’utility Export di Oracle esegue una query sul database, compreso il dizionario dati, e scrive
l’output su un file binario che prende il nome di file di dump di esportazione. È possibile espor-
tare l’intero database, utenti specifici oppure tabelle specifiche. Durante le operazioni di espor-
tazione, si potrà decidere se esportare o meno le informazioni del dizionario dati associate alle
tabelle, come concessioni, indici e vincoli a esse associati. Il file scritto da Export conterrà i
comandi necessari per ricreare completamente tutti gli oggetti e i dati scelti.
È possibile effettuare esportazioni a livello di tablespace per esportare tutti gli oggetti con-
tenuti in una tablespace. Qualunque indice specificato sulle tabelle esportate verrà esportato. Le
esportazioni a livello di tablespace utilizzano la clausola tablespaces dell’utility Export, come
verrà descritto più avanti in questo capitolo.
Dopo essere stati esportati, i dati possono essere importati tramite l’utility Import di Oracle.
L’utility Import legge il file di dump di esportazione binario creato da Export ed esegue i coman-
di che trova in questo file. Per esempio, questi comandi potrebbero includere create table segui-
to da un comando insert per caricare dei dati nella tabella.
La consuetudine di generare un file di dump di esportazione non implica che i dati esportati
debbano essere importati obbligatoriamente nel medesimo database, o nello stesso schema. Il
file di dump di esportazione potrebbe servire per creare un gruppo di duplicati degli oggetti
esportati in uno schema differente o in un database separato.
Si possono importare tutti i dati esportati oppure solo una parte di essi. Se si importa l’intero
file di dump di esportazione da un’esportazione Full, allora tutti gli oggetti di database, tra cui le
tablespace, i file di dati e gli utenti verranno creati durante l’importazione. Tuttavia, spesso è
858 CAPITOLO 46
utile creare in anticipo tablespace e utenti per specificare la distribuzione fisica degli oggetti nel
database.
Se invece si importerà solo una parte dei dati dal file di dump di esportazione, le tablespace,
i file di dati e gli utenti che possiederanno e memorizzeranno questi dati dovrebbero essere
configurati prima dell’importazione.
I dati esportati potrebbero essere importati in un database creato in una versione successiva
del software Oracle. Si rimanda al Capitolo 3 per indicazioni sulle versioni di Export da utilizza-
re per l’aggiornamento o il downgrade delle versioni del software Oracle. I file README.doc
che accompagnano le release di Oracle descrivono in dettaglio i requisiti per l’utilizzo di Export
e Import tra le varie versioni specifiche.
Export
L’utility Export ha quattro livelli di funzionalità, definiti dalle modalità Full, Tablespace, User e
Table. Si possono esportare delle partizioni tramite una versione modificata delle esportazioni di
modalità Table.
Nella modalità Full, viene esportato l’intero database. L’intero dizionario dati viene letto e il
DDL necessario per ricreare l’intero database viene scritto nel file di dump di esportazione.
Questo file comprende comandi di creazione per tutte le tablespace, tutti gli utenti, tutti gli
oggetti, i dati e i privilegi contenuti nei loro schemi.
Nella modalità Tablespace, verranno esportati tutti gli oggetti contenuti nelle tablespace
specificate, compresa la definizione degli indici relativi agli oggetti contenuti, anche se questi si
trovano in un’altra tablespace.
Nella modalità User, vengono esportati gli oggetti di un utente, così come i dati in essi
contenuti. Inoltre, vengono esportati anche tutti gli indici e le concessioni creati dall’utente sui
propri oggetti. Le concessioni e gli indici creati da utenti che non sono i proprietari non vengono
esportati.
Nella modalità Table viene esportata una tabella specificata. La struttura, gli indici e le
concessioni della tabella vengono esportati con o senza i suoi dati. La modalità Table può espor-
tare anche l’intero gruppo di tabelle possedute da un utente (specificando il possessore dello
schema ma non i nomi delle tabelle). Inoltre, si possono specificare partizioni di una tabella da
esportare.
Export può essere eseguita in modo interattivo tramite Oracle Enterprise Manager oppure
con i file dei comandi. Le opzioni runtime che possono essere specificate per Export sono elen-
cate nella Tabella 46.1, insieme ai loro valori predefiniti in Oracle Database 10g.
Alcuni parametri sono in reciproco conflitto oppure potrebbero portare a istruzioni incoe-
renti per Export. Per esempio, l’impostazione full=Y e owner=HR fallirebbe, perché il parametro
full chiama un’esportazione Full, mentre il parametro owner specifica un’esportazione User.
exp help=Y
L’opzione compress=Y altera il parametro initial della clausola storage per quei segmenti
che hanno più extent. Durante una successiva importazione, lo spazio totale allocato per quel
segmento verrà compresso in un unico extent. Riguardo a questa funzionalità ci sono due consi-
derazioni importanti da fare.
GUIDA ALL’AMMINISTRAZIONE DEL DATABASE 859
buffer Dimensioni del buffer utilizzato per prelevare i dati. Il valore predefinito dipende dal sistema; di solito a
questo parametro viene assegnato un valore alto (maggiore di 64000).
compress Un flag Y/N per indicare se l’esportazione deve comprimere i segmenti frammentati in un unico extent.
Questo ha un effetto sulle clausole di memorizzazione storage che vengono salvate nel file di esportazio-
ne per questi oggetti. Il valore predefinito è Y. Avere i dati in un solo extent di grandi dimensioni non
sempre è la soluzione ideale. Per le tabelle di grandi dimensioni si dovrebbe utilizzare compress =N.
grants Un fiag Y/N per indicare se devono essere esportate anche le concessioni (grant) sugli oggetti del
database). Il valore predefinito è Y.
indexes Un flag Y/N per indicare se devono essere esportati anche gli indici delle tabelle. Il valore predefinito è Y.
direct Un flag Y/N per indicare se dev’essere effettuata un’esportazione diretta. Un’esportazione diretta aggira
la buffer cache durante l’esportazione, producendo un significativo aumento delle prestazioni del pro-
cesso di esportazione. Il valore predefinito è N.
log Nome del file nel quale verrà scritto il log dell’esportazione.
rows Un fiag Y/N per indicare se le righe devono essere esportate. Se si usa N, nel file di esportazione viene
creato solo il codice DDL relativo agli oggetti del database. Il valore predefinito è Y.
consistent Un fiagY/N per indicare se dev’essere mantenuta una versione coerente di tutti gli oggetti esportati.
Questo parametro è necessario quando delle tabelle correlate fra loro potrebbero venire modificate dagli
utenti durante il processo di esportazione.
object_consistent Un fiagY/N per indicare se dev’essere mantenuta una versione coerente degli oggetti esportati a livello di
oggetto, anche tra partizioni diverse. L’impostazione predefinita è N.
owner Un elenco di account del database da esportare; dopodiché possono essere effettuate esportazioni in
modalità utente di questi account.
tables Un elenco delle tabelle da esportare; quindi possono essere effettuate esportazioni in modalità a tabella
di queste tabelle. A partire da Oracle9i questo parametro accetta l’uso del caratteri jolly % e _ per il
pattern matching.
recordlength La lunghezza, in byte, dei record dei file di dump di Export. Di solito viene impiegato il valore standard,
tranne quando si devono trasferire i file da un sistema operativo a un altro.
triggers Un fiagY/N per indicare se i trigger devono essere esportati. Il valore predefinito è Y.
statistics Un parametro per indicare se sul file di dump di Export devono essere scritti i comandi analyze relativi
agli oggetti esportati. I valori validi sono “COMPUTE”, “ESTìMATE,” (l’impostazione standard) è N. Nelle
precedenti versioni di Oracle questo parametro era chiamato “analyze”.
parfile lì nome di un file di parametri da passare a Export. Questo file può contenere tutti i parametri elencati in
questa tabella.
constraints Un flag Y/N per indicare se devono essere esportate le restrizioni sulle tabelle. Il valore predefinito è Y.
(segue)
860 CAPITOLO 46
filesize La massima dimensione del file di dump di esportazione. Se sono elencati più file nella voce “file”,
l’esportazione sarà indirizzata a tali file in relazione alla dimensione di filesize.
flashback_scn Specifica l’SCN che Export utilizzerà per attivare il flashback. L’esportazione avverrà con i darti coerenti
a partire da questo SCN.
flashback_time Tempo usato per prendere l’SCN più vicino all’ora specificata. L’esportazione avverrà con i dati coerenti
a partire da questo SCN.
query Una clausola where che verrà applicata a ogni tabella durante l’esportazione.
resumable Un fiag YIN per indicare se la sessione può essere recuperata in seguito a degli errori. Il valore predefinito
è N.
resumable_name Il valore specificato viene inserito nella vista DBA_RESUMABLE per aiutare a identificare l’istruzione
recuperabile.
tts_full_check Effettua un controllo delle dipendenze completo o parziale per individuare le tablespace trasportabili.
tablespaces In Oracle9i le tablespace le cui tabelle dovrebbero essere esportate, comprese tutte le tabelle che non
hanno una partizione situata nelle tablespace specificate.
transpor_tablespace Impostata a Y se si usa l’opzione pluggable tablespace disponibile a partire da Oracle8i. Da utilizzare
insieme alla parola riservata tablespaces. Il valore predefinito è N.
■ Innanzi tutto, è lo spazio allocato e non quello utilizzato che viene compresso. Una tabella
vuota per la quale sono stati allocati 300MB in tre extent da 100MB verrà compressa in un unico
extent vuoto di 300MB. Non verrà reclamato dello spazio.
■ In secondo luogo, se la tablespace ha più file di dati, un segmento potrebbe allocare uno
spazio maggiore rispetto alla dimensione del file di dati più grande. In questo caso, l’uso di
compress=Y modificherebbe la clausola storage in modo che abbia una dimensione di extent
iniziale maggiore di qualsiasi dimensione del file di dati. Se il file di dati non può estendere se
stesso, la creazione dell’oggetto fallirà durante l’importazione.
Nell’esempio seguente, viene utilizzata l’opzione compress=Y mentre i proprietari HR e
THUMPER vengono esportati:
Esportazioni coerenti
Durante la scrittura dei dati di database nel file di dump di esportazione, Export legge una tabella
per volta. Quindi, anche se Export iniziasse a un orario ben specifico, ciascuna tabella verrebbe
letta a orari diversi. Ciò che verrà esportato sono i dati così come si trovano in ogni tabella nel
GUIDA ALL’AMMINISTRAZIONE DEL DATABASE 861
momento in cui Export inizia a leggere quella tabella. Considerata la correlazione che lega la
maggior parte delle tabelle ad altre tabelle, si potrebbero verificare esportazioni di dati incoeren-
ti se gli utenti modificano i dati durante l’esportazione. Il file di dump di esportazione potrebbe
contenere dei dati incoerenti, come record di chiave esterna presi da una tabella senza record di
chiave primaria corrispondenti presi da una tabella correlata.
Per evitare incoerenze nelle esportazioni esistono due possibilità:
■ Innanzi tutto, si dovrebbero programmare le esportazioni in modo che avvengano quando
nessuno sta apportando modifiche alle tabelle. Se fattibile, si può utilizzare l’opzione startup
restrict per assicurarsi che solo i DBA siano connessi mentre avviene l’esportazione.
■ In secondo luogo, si può usare il parametro consistent. Questo parametro è disponibile solo
per esportazioni complete. Durante un’esportazione coerente, Oracle cercherà di creare una ver-
sione a lettura coerente dei dati esportati a partire dal momento in cui è iniziata l’esportazione.
Se Oracle non è in grado di ricreare la versione a lettura coerente delle tabelle, compariranno
errori “snapshot too old”. Per essere certi di non incontrare errori di questo genere, si dovranno
creare segmenti di rollback molto grandi oppure una tablespace di undo di grandi dimensioni,
perché Oracle sovrascriverà le voci dei vecchi segmenti di rollback ignorando l’impostazione
consistent=Y.
■ In terzo luogo, si potrebbe rendere inattivo il database, operazione che limita le connessioni
ai soli utenti con privilegi SYSDBA. Mentre il database è quiescente, tutte le transazioni e le
query in corso sembra che siano in attesa, e non sono ammesse connessioni di nuovi utenti.
Ogni volta che è possibile, si garantisca la coerenza dei dati esportati eseguendo le esporta-
zioni mentre il database non è utilizzato, oppure quando è aperto in modalità limitata. Se ciò non
è possibile, si limiti l’utilizzo del database durante la fase di esportazione e si esegua un’espor-
tazione consistent=Y.
Un’altra possibilità è la creazione di due file dei parametri (parfile). Un file conterrà i nomi
della maggior parte delle tabelle presenti nel database oppure nello schema; si potrà ricorrere a
questo file per la prima esportazione con l’impostazione predefinita consistent=N. Il secondo
file, contenente i nomi delle tabelle per cui si dovrà mantenere la coerenza, serve per eseguire
un’esportazione con l’opzione consistent=Y. Con questo approccio, la dimensione dei segmenti
di rollback non dovrà essere così grande, e le prestazioni del sistema non soffriranno troppo.
Se una tabella ha una partizione nella tablespace specificata, verrà esportata l’intera tabella.
Se si imposta indexes=Y, gli indici associati della tabella verranno esportati indipendentemente
dalla loro posizione nella tablespace.
Esportazione di partizioni
Quando si eseguono esportazioni Table, è possibile fare riferimento alle partizioni e alle partizioni
secondarie all’interno delle tabelle. Per esempio, se la tabella VENDITE nello schema THUMPER
862 CAPITOLO 46
è suddivisa in PARTE1, PARTE2 e PARTE3, allora si potrà esportare l’intera tabella oppure le
sue porzioni.
Per esportare l’intera tabella, si utilizza il parametro tables di Export:
Per esportare una porzione o una porzione secondaria specifica, si elenca il nome della
porzione o della porzione secondaria dopo il nome della tabella. Il nome della tabella e quello
della porzione dovrebbero essere separati da un segno di due punti (:). Nel listato seguente, viene
esportata la porzione PARTE1:
Se si esporta una porzione, verranno esportate anche tutte le sue porzioni secondarie.
Import
L’utility Import legge il file di dump di esportazione ed esegue i comandi in esso memorizzati.
Import potrebbe servire per restituire in modo selettivo gli oggetti o gli utenti dal file di dump di
esportazione.
Import può essere eseguita in modo interattivo oppure tramite i file di comandi. Le opzioni
runtime che possono essere specificate per Import e i loro valori predefiniti sono elencate nella
Tabella 46.2.
Alcuni parametri di Import sono in conflitto reciproco oppure potrebbero portare a istruzio-
ni incoerenti per Import. Per esempio, le impostazioni full=Y e fromuser=HR fallirebbero poiché
il parametro full chiama un’importazione Full, mentre il parametro fromuser chiama un’importa-
zione User.
Quanto dovrebbe essere grande buffer? La sua dimensione dovrebbe essere sufficiente a
contenere la singola riga più grande da importare. Se non si conosce la lunghezza della riga più
grande esportata, si incominci con un valore discreto (come 50.000) e si esegua l’importazione.
Se si riceve un errore IMP-00020, significa che la dimensione del buffer non è sufficiente. La si
aumenti e si esegua nuovamente l’importazione.
Quando si usa commit=Y, si dovrà tenere a mente che per ogni array del buffer viene eseguito
un commit. Questo implica che, nel caso in cui l’importazione di una tabella fallisca, è possibile
che alcune righe in quella tabella siano già state importate e che il loro commit sia già stato
effettuato. Quindi, il caricamento parziale potrebbe essere utilizzato o cancellato prima di ese-
guire nuovamente l’importazione.
GUIDA ALL’AMMINISTRAZIONE DEL DATABASE 863
buffer Dimensioni del buffer utilizzato per prelevare le righe di dati. Il valore standard dipende dal sistema; di
solito a questo parametro viene assegnato un valore alto (maggiore di 100.000).
show Un flag Y/N per specificare se i contenuti del file devono essere solo visualizzati. Il valore predefinito è N.
ignore Un flag Y/N per indicare se lmport deve ignorare gli errori verificatisi durante l’esecuzione dei comandi
create. Si utilizza se gli oggetti da importare esistono già. Il valore predefinito è N.
grants Un flag Y/N per indicare se devono essere importate le concessioni (grant) sugli oggetti del database. Il
valore predefinito è Y.
indexes Un flag Y/N per indicare se devono essere importati gli indici delle tabelle. Il valore predefinito è Y.
rows Un flag Y/N per indicare se devono essere importate le righe. Se si specifica “N” viene eseguito solo il
codice DDL per gli oggetti del database. Il valore predefinito è Y.
log Nome del file nel quale verrà scritto il log di importazione.
full Un flag Y/N; se posto a “Y” viene importato l’intero file di dump. Il valore predefinito è N.
fromuser Un elenco di account del database i cui oggetti devono essere letti dal file di dump (quando FULL=”N”).
touser Un elenco di account del database nei cui oggetti deve essere importato il file di dump. fromuser e
touser non devono avere lo stesso valore.
tables L’elenco delle tabelle da importare. A partire da Oracle9i è accettato l’uso del caratteri jolly % e _ per i
nomi delle tabelle.
recordlength La lunghezza in byte del record del file di dump. Di solito si utilizza il valore predefinito, a meno che non
si debba trasferire il file da un sistema operativo a un altro.
commit Un flag Y/N per indicare se lmport deve eseguire un comando commit dopo il caricamento di ogni array
(le cui dimensioni sono specificate in BUFFER). Se viene impostato a “N”, il comando commit viene
impartito dopo ogni tabella. Per tabelle di grandi dimensioni, commit=N richiede l’uso di segmenti di
undo altrettanto grandi.
parfile lì nome di un file di parametri da passare a lmport. Questo file può contenere tutti i parametri elencati in
questa tabella.
constraints Un flag Y/N che indica se devono essere importati anche i vincoli presenti nelle tabelle. Il valore predefinito è Y.
destroy Un flag Y/N per indicare se devono essere eseguiti i comandi create tablespace che si trovano nei file
dump di esportazioni complete (distruggendo cosi i file di dati del database di destinazione). Il valore
predefinito è N.
indexfile Questa opzione scrive tutti i comandi create table, create cluster e create index su un file invece di
eseguirli. Tutti i comandi tranne create index vengono trasformati in commenti. Se è stato impostato
constraint=Y, nel file verranno scritti anche i vincoli. Questo file può poi essere eseguito (con lievi
modifiche) dopo un’importazione con indexes=N. È molto utile per suddividere le tabelle e gli indici in
tablespace separate.
(segue)
864 CAPITOLO 46
feedback Il numero di righe dopo cui visualizzare la progressione dell’importazione delle tabelle. lì valore standard
è 0, che non mostra alcuna informazione finché una tabella non sia stata completamente importata.
filesize Il valore massimo di dimensione del file di dump che è stato specificato in esportazione.
statistics Un flag per indicare se devono essere importate le statistiche precalcolate. Il valore predefinito è ALWAYS;
gli altri valori sono NONE, SAFE (per le statistiche non discutibili) e RECALCULATE (ricalcola durante
l’importazione).
resumable Un flag YIN per indicare se la sessione può essere recuperata in seguito a degli errori. Il valore predefinito
è N.
resumable_name Il valore specificato viene inserito nella vista DBA_RESUMABLE per aiutare a identificare l’istruzione
recuperabile.
streams_configuration Un flag YIN per indicare se i dati di configurazione di Oracle Strams trovati nel file di dump di esportazio-
ne devono essere importati. Il valore predefinito è Y.
streams_instantiation Un flag YIN per indicare se i metadati di istanziazione di Oracle Strams devono essere importati se
presenti nel file di dump di esportazione. Il valore predefinito è N.
compile Un flag YIN per indicare se procedure, funzioni e package devono essere ricompilati durante l’importa-
zione. Il valore predefinito è Y.
transport_tablespace Un flag Y/N per indicare che nel database devono essere importati i metadati della tablespace trasportabili.
Il valore predefinito è N.
tablespaces Il nome o l’elenco delle tablespace che devono essere trasportate nel database.
datafiles L’elenco dei file di dati che devono essere trasportati nel database.
tts_owner L’elenco dei proprietari dei dati contenuti nella tablespace trasportabile.
Nelle tabelle con le colonne BFILE, LONG, LOB, REF, ROWID e UROWID, le righe ven-
gono inserite separatamente. Il valore del buffer non deve soddisfare le porzioni LONG e LOB
della riga, Import cercherà di allocare altre aree di buffer in base alle esigenze di queste porzioni.
Per ulteriori dettagli su Export e Import, insieme a esempi sul recupero dei dati, fare riferi-
mento alla guida Oracle Database Utilities 10g Release 1.
Backup in linea
I backup in linea possono essere utilizzati per qualsiasi database eseguito in modalità
ARCHIVELOG. In questa modalità, vengono archiviati i redo log in linea creando un log com-
pleto di tutte le transazioni all’interno del database.
Oracle scrive nei redo log file in linea in modo ciclico; dopo aver riempito il primo file di
log, Oracle inizia a scrivere nel secondo log fino a quando non lo ha riempito, quindi inizia a
scrivere nel terzo. Una volta riempito l’ultimo redo log file in linea, il processo in background
LGWR (Log Writer) inizia a sovrascrivere il contenuto del primo redo log file.
Quando Oracle viene eseguito in modalità ARCHIVELOG, il processo in background ARC0-
ARC9 (Archiver) crea una copia per ogni redo log file prima di sovrascriverlo. Solitamente,
questi redo log file archiviati vengono scritti in una periferica di disco. I redo log file archiviati
potrebbero essere scritti direttamente in una periferica a nastro, tuttavia questa operazione tende
a essere molto impegnativa.
È possibile eseguire i backup di file system di un database mentre questo database è aperto,
a condizione che il database venga eseguito in modalità ARCHIVELOG. Un backup in linea
richiede l’impostazione di ogni tablespace (o dell’intero database) in uno stato di backup, l’ese-
cuzione del backup dei file di dati correlati e infine il ripristino delle tablespace nel loro stato
normale.
NOTA Quando si utilizza l’utility RMAN fornita da Oracle, non è necessario col-
locare ogni tablespace in uno stato di backup. L’utility metterà e leverà automaticamente la
tablespace dallo stato di backup.
Il database può essere recuperato completamente da un backup in linea e, tramite i redo log
archiviati, il rollforward può essere effettuato in un qualsiasi momento. Quando si aprirà il
database, le transazioni eseguite presenti nel database in quel momento saranno state recuperate
e il rollback delle transazioni non eseguite sarà già stato effettuato.
Mentre il database è aperto, viene effettuato il backup per i file seguenti:
■ Tutti i file di dati.
■ Tutti i redo log file archiviati.
■ Un control file, con il comando alter database.
Le procedure dei backup in linea sono molto potenti per due motivi. In primo luogo, forni-
scono un recupero puntuale completo. I database non eseguiti in modalità ARCHIVELOG po-
tranno essere recuperati solamente nel momento in cui avviene il backup. In secondo luogo,
permettono al database di rimanere aperto durante il backup di file system. Quindi, persino i
database che non possono essere chiusi per requisiti dell’utente potranno comunque avere dei
backup di file system.
Primi passi
Per sfruttare la capacità di ARCHIVELOG, per prima cosa si dovrà collocare il database in
modalità ARCHIVELOG. Il listato seguente mostra i passaggi necessari per mettere un database
in modalità ARCHIVELOG. Si esegua SQL*Plus e si esegua anche il MOUNT del database (in
questi esempi si inserisca il suo nome al posto di “mydb”), infine lo si modifichi come mostrato
di seguito:
NOTA Per visualizzare il redo log in linea attualmente attivo e il suo numero di
sequenza, occorre eseguire una query sulla vista dinamica V$LOG.
log_archive_dest_1 = /db01/oracle/arch/CC1/arch
log_archive_dest_state_1 = ENABLE
log_archive_format = arch%s.arc
In questo esempio, i redo log file archiviati sono stati scritti nella directory /db01/oracle/
arch/CC1. I redo log file archiviati inizieranno tutti con le lettere“arch”, seguite da un numero di
sequenza. Per esempio, la directory dei redo log file archiviati potrebbe contenere i file seguenti:
arch_170.arc
arch_171.arc
arch_172.arc
Ciascuno di questi file contiene i dati tratti da un solo redo log in linea. Questi sono numerati
in modo sequenziale, nell’ordine in cui sono stati creati. La dimensione dei redo log file archiviati
varia, tuttavia non supera la dimensione dei redo log file in linea. Nell’impostazione di
LOG_ARCHIVE_FORMAT le variabili disponibili sono le seguenti:
VARIABILE DESCRIZIONE
%s Numero di sequenza del log.
%a ID di attivazione.
%d ID del database.
%r ID di resetlog che garantisce che vengono costruiti nomi unici per i file log archiviati tra più incarnazioni
del database.
868 CAPITOLO 46
Se la directory di destinazione dei redo log file archiviati esaurisce lo spazio, ARCH termi-
nerà l’elaborazione dei dati redo log e il database rimarrà temporaneamente in attesa. Questa
situazione può essere risolta aggiungendo più spazio al disco di destinazione dei redo log file
archiviati oppure eseguendo il backup dei redo log file archiviati rimuovendoli poi da questa
directory.
NOTA I redo log file non devono mai essere eliminati fino a quando non si sarà
eseguito un loro backup e non si sarà verificata la possibilità di recuperarli correttamente.
È possibile creare uno script per effettuare i backup, tuttavia è preferibile utilizzare RMAN.
Quando si esegue il backup dei file di dati, è possibile effettuarlo direttamente nel nastro o
nel disco. Se lo spazio libero su disco è sufficiente, è consigliabile scegliere la seconda opzione,
in quanto ridurrà moltissimo il tempo necessario a completare le procedure di backup.
Recovery Manager
Con il database Oracle viene fornita una utility di gestione dei recuperi (Recovery Manager),
chiamata anche RMAN, per permettere agli utenti di eseguire il backup e di recuperare i database
in modo automatizzato utilizzando la modalità a linea di comando oppure Recovery Manager da
Oracle Enterprise Manager. Per eseguire il backup, ripristinare e recuperare i file di database si
possono usare entrambi gli approcci.
Recovery Manager tiene traccia dei backup tramite un Recovery Catalog oppure inserendo
le informazioni necessarie nel control file del database per il quale si esegue il backup. Recovery
Manager aggiunge nuove capacità di backup che non sono disponibili nelle altre utility di backup
di Oracle. Recovery Manager contiene quattro componenti: l’eseguibile RMAN, uno o più
database di destinazione, il database con il catalogo dei recuperi e il software di gestione dei
supporti. Gli unici componenti necessari sono l’eseguibile RMAN e un database di destinazione.
Recovery Manager consente di eseguire backup fisici incrementali dei file di dati. Durante il
backup completo di un file di dati (chiamato livello 0), viene eseguito il backup di tutti i blocchi
utilizzati nel file dati. Durante il backup cumulativo di un file di dati (livello 1), viene eseguito il
backup di tutti i blocchi che sono stati utilizzati dall’ultimo backup completo del file di dati. Il
backup incrementale di un file di dati (livello 2) esegue il backup solo di quei blocchi che sono
cambiati dall’ultimo backup cumulativo o completo. È possibile definire i livelli utilizzati per I
backup incrementali.
La possibilità di effettuare backup incrementali e cumulativi dei file di dati può migliorare
significativamente le prestazioni dei backup. I miglioramenti maggiori nelle prestazioni li otter-
ranno i database di grandi dimensioni in cui solamente un piccolo sottoinsieme di una grande
tablespace cambia. Con i metodi di backup tradizionali, si dovrebbe eseguire il backup di tutti i
file di dati contenuti nella tablespace, mentre con Recovery Manager si esegue il backup dei
blocchi che sono cambiati rispetto l’ultimo backup.
Durante il recupero del database con Recovery Manager, è necessario sapere quali file sono
correnti, quali ripristinati e il metodo di backup che si intende utilizzare. Se si usa il catalogo dei
recuperi, Recovery Manager memorizza il suo catalogo di informazioni in un database Oracle,
quindi si dovrà eseguire il backup di questo database, altrimenti si potrebbe correre il rischio di
perdere l’intero catalogo di informazioni relative al backup e al recupero.
Recovery Manager è utilizzato solamente dai DBA, che devono prendere delle decisioni
relative alla sua architettura in relazione all’ambiente (per esempio, decidere l’ubicazione del
catalogo dei recuperi). Per comprendere le opzioni di recupero usate e le implicazioni che esse
hanno sulla disponibilità di database e il tempo di recupero, si dovrebbe lavorare con il proprio
DBA.
Oracle a questo punto creerà un file binario da usare per tenere traccia delle modifiche. Questa
registrazione può essere disabilitata con il comando alter database disable block change tracking.
Interrogando V$BLOCK_CHANGE_TRACKING è possibile vedere lo stato corrente.
■ Backup uniti. Invece di mantenere più livelli di backup su più giorni, è possibile fare in
modo che i backup incrementali vengano uniti in modo dinamico con i backup precedenti. Per-
tanto, se si effettua un backup completo un giorno e uno incrementale il giorno seguente, l’even-
tuale recupero risulterà più facile se si utilizzano le nuove capacità di unione, in quanto sarà
sufficiente un solo backup (unito) per effettuare il ripristino. L’unione avviene come parte del
comando backup in RMAN, che farà una copia del backup precedente e la unirà alle nuove
modifiche incrementali.
■ Backup compressi. RMAN può comprimere i file di backup mentre vengono scritti, riducen-
do notevolmente i requisiti di spazio su disco per i backup destinati al disco.
46.10 Riepilogo
In questo capitolo, è stata presentata un’introduzione esauriente delle questioni che i DBA af-
frontano ogni giorno. Oltre agli argomenti trattati in questa sede, esistono i database di controllo
dei DBA, la messa a punto dei database, l’installazione del software, la gestione della connettività
di database e molti altri ancora. Per ulteriori informazioni su queste attività, fare riferimento alla
documentazione Oracle o all’Oracle DBA Handbook. Maggiori sono le conoscenze degli
sviluppatori sull’amministrazione del database, maggiori sono le probabilità di sviluppare appli-
cazioni che sfruttano le capacità inerenti del database.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 47
X
ML (eXtensible Markup Language) è una sintassi standar-
dizzata utilizzata per descrivere dati gerarchici. Più che un linguaggio di programmazione, XML
è un formato universale per documenti e dati strutturati. A chi conosce HTML (HyperText Markup
Language) risulterà certo familiare la sintassi di XML basata sulle tag, che conferisce a questo
linguaggio la flessibilità necessaria a gestire dati complessi. Mentre HTML comunica a un browser
Web come presentare i dati, XML comunica alle varie applicazioni il significato dei dati.
XML è adatto a risolvere problemi legati allo scambio dei dati tra sistemi eterogenei; grazie
a esso, l’accesso, la conversione e la memorizzazione dei dati contenuti nel database sono opera-
zioni molto semplici. Questo capitolo offrirà una panoramica dei metodi di accesso XML dispo-
nibili in Oracle Database 10g. XML e i suoi toolset sono in continua evoluzione, quindi per le
informazioni più recenti si consiglia di visitare il sito http://www.w3.org.
<libro>
<titolo>MY LEDGER/titolo>
<capitolo num="1">
<titolo>Beginning/titolo>
<testo>&chapter1;/testo>
</capitolo>
</libro>
872 CAPITOLO 47
In questo esempio, le tag <libro> e </libro> definiscono i punti iniziale e finale del gruppo
di informazioni. Il documento XML descrive un libro intitolato “MY LEDGER”. Questo libro
ha dei capitoli, e il titolo del primo capitolo è “Beginning”. Il testo del capitolo non è memoriz-
zato nel documento XML, in quanto viene creato un puntatore a un file esterno.
Oltre a essere una tag nel file, “titolo” è anche un elemento, che ha del contenuto, in questo
caso “MY LEDGER”. Come mostrato in questo esempio, è possibile impostare il contenuto
degli elementi inserendo dei valori tra le tag (per il titolo), oppure nelle tag (come nell’impo-
stazione del numero di capitolo). Gli elementi possono avere del contenuto, degli elementi figli
o entrambi, oppure potrebbero essere vuoti. Per lo scambio di dati, è consigliabile evitare di
creare elementi che contengono sia il contenuto sia gli elementi figli. Per creare un elemento
vuoto, la sua tag dovrebbe essere nel formato seguente:
<nome/>
Ogni elemento ha un solo padre, mentre un padre può avere un numero qualsiasi di figli. La
rigida natura gerarchica di XML prevede che se un elemento inizia all’interno di un altro ele-
mento (come un “capitolo” in un “libro”), la sua tag finale dovrà precedere la tag finale dell’ele-
mento padre.
Come mostrato nell’esempio del libro, gli elementi possiedono degli attributi. Per esempio,
l’elemento capitolo ha un attributo di nome num. Il valore dell’attributo è racchiuso tra virgolette:
<capitolo num="1">
NOTA Come i nomi degli elementi, anche i nomi degli attributi distinguono tra
maiuscole e minuscole.
<Cliente clientePreferito="">
<ID>12345</ID>
<Indirizzo>
<Nome>TUSC</Nome>
<Via>377 E BUTTERFIELD RD</Via>
<Citta>LOMBARD</Citta>
<Stato>IL</Stato>
<Paese>USA</Paese>
<CAP>60148</CAP>
<TELEFONO>630-960-2909</TELEFONO>
</Indirizzo>
<ValutazioneCredito>ECCELLENTE</ValutazioneCredito>
<IDRepVendite>/<IDRepVendite>
<IDRegione>5/<IDRegione>
<Commenti>QUESTO È UN DOCUMENTO XML DI PROVA</Commenti>
<MetodoConsegna>M</MetodoConsegna>
</Cliente>
</ElencoClienti>
La prima linea è una dichiarazione XML, che inizia con “<?” e termina con “?>”:
Per ora, l’attributo version dovrebbe essere impostato a 1.0. L’attributo encoding è facolta-
tivo; il suo valore predefinito è UTF-8. Si può impostare anche un terzo attributo, standalone. In
questo caso, il documento XML non è indipendente; ha una DTD correlata, come specificato
nella seconda linea:
Il file della DTD correlata Example1.dtd per questo esempio è visibile nel listato seguente:
Una DTD è simile alle specifiche del control file per le tabelle esterne. Essa infatti comunica
alle applicazioni cosa troveranno nel documento XML, i nomi degli elementi e la loro gerarchia.
Un documento XML può avere solamente una DTD.
874 CAPITOLO 47
in cui modello_contenuto specifica quali figli può o deve possedere un elemento e l’ordine in cui
compaiono. Il modello di contenuto più semplice è #PCDATA, il quale indica che l’elemento
può contenere solo dati carattere analizzati. Ecco un esempio:
Come mostrato nella specifica dell’elemento Indirizzo, è possibile specificare una sequenza
di più elementi separandoli con delle virgole:
Nella specifica si possono fornire più opzioni, separate dal carattere (|) barra verticale. Per
esempio, si potrebbe specificare un punto in un grafico bidimensionale tramite le sue coordinate
verticali e orizzontali, oppure tramite la sua distanza e l’angolo dal centro:
Nelle applicazioni reali, le DTD possono diventare in poco tempo molto complesse. Infatti,
in una DTD si possono avere liste di attributi, riferimenti esterni, attributi di entità, ID, inclusio-
ni condizionali e altre strutture. Per un riepilogo esauriente sulle strutture e le opzioni delle
DTD, si faccia riferimento alla documentazione relativa a XML.
NOTA Prima di creare una DTD per un’operazione aziendale standard, si verifi-
chi se ne esiste già una disponibile. Siti Web come http://www.xml.org/xml/registry.jsp fornisco-
no molti esempi di DTD. Questi registri sono una risorsa molto utile per la documentazione di
DTD standard aziendali e dei loro componenti.
<xsd:element name="Date">
Con gli attributi minOccurs e maxOccurs si possono specificare il numero minimo e massi-
mo di occorrenze per l’elemento:
Tra i tipi incorporati di XML Schema ci sono tipi primitivi (come stringhe, valori booleani,
numeri, valori in virgola mobile, data, ora e data/ora) e tipi derivati (come normalizedString,
valori interi, token e linguaggio). Al sito http://www.w3.org/TR/xmlschema -2/ si può trovare
l’elenco completo dei tipi.
Si possono creare e nominare tipi complessi, così come si possono creare tipi di dati astratti
in Oracle. Il codice seguente crea il tipo “Indirizzo”:
<xsd:complexType name="Indirizzo">
<xsd:sequenze>
<xsd:element name="Via1"/>
<xsd:element name="Via2"/>
<xsd:element name="Citta"/>
<xsd:element name="Stato"/>
<xsd:element name="CAP"/>
</xsd:sequenze>
</xsd:complexType>
<xsd:element name="Nome">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Primo"/>
<xsd:element name="InizialeIntermedia"/>
<xsd:element name="Ultimo"/>
</xsd:sequence>
</xsd:complexType
</xsd:element>
876 CAPITOLO 47
Gli attributi vengono dichiarati con xsd:attribute, come mostrato nell’esempio seguente:
<xsd:element name="Fattura">
<xsd:complexType>
<xsd:attribute name="pagato" use="facoltativo" default="True"/>
</xsd:complexType>
</xsd:element>
Oltre a creare gli attributi, si possono generare anche gruppi di attributi e gruppi di modelli.
I gruppi di modelli sono gruppi o definizioni di elementi, chiamati per essere riutilizzati. L’ele-
mento “gruppo” dev’essere il componente di uno schema di livello superiore (un figlio dell’ele-
mento “schema”). Per esempio, il listato seguente mostra la creazione di un gruppo Menu, cui fa
riferimento l’elemento “CenaAereo”.
<xsd:element name="CenaAereo">
<xsd:sequenze>
<xsd:element ref="Nome"/>
<xsd:group ref="Menu"/>
</xsd:sequenze>
</xsd:element>
<xsd:group name="Menu">
<xsd:choice>
<xsd:element name="Pesce" type="Pasto"/>
<xsd:element name="Carne" type="Pasto"/>
<xsd:element name="Vegetariano" type="Pasto"/>
</xsd:choice>
</xsd:group>
In genere gli attributi sono raggruppati insieme se gli elementi utilizzano spesso lo stesso
insieme di attributi. Ciò assomiglia all’approccio descritto nella Parte quinta di questo libro, in
cui gli attributi comuni vengono associati per formare nuovi tipi di dati. Per esempio, la defini-
zione seguente di un elemento “Prodotto” usa un gruppo di attributi che prende il nome di
dettagliProdotto. Altri elementi possono riutilizzare questo stesso gruppo di attributi, miglioran-
do così le capacità dell’utente di applicare una rappresentazione standardizzata di questi dati.
<xsd:element name="Prodotto"
<xsd:complexType>
<xsd:attributeGroup ref="dettagliProdotto"/>
</xsd:complexType>
</xsd:element>
<xsd:attributeGroup name="dettagliProdotto">
<xsd:attribute name="IDProdotto" use="required" type="xsd:ID"/>
<xsd:attribute name="nome" use="required" type="xsd:string"/>
<xsd:attribute name="descrizione" use="required" type="xsd:string"/>
<xsd:attribute name="unita" type="xsd:positiveInteger"/>
<xsd:attribute name="prezzo" use="required" type="xsd:decimal"/>
<xsd:attribute name="scorta" type="xsd:integer"/>
</xsd:attributeGroup>
GUIDA A XML IN ORACLE 877
<xsd:unique name="IDProdottoUnico">
<xsd:selector xpath="tc:Prodotto/"/>
<xsd:field xpath="tc:@IDProdotto"/>
</xsd:inique>
Per l’elemento “Prodotto”, l’univocità viene dichiarata allo stesso livello della definizione
del tipo complesso. Lo spazio di nomi tc: è per lo schema che si crea ed è dichiarato nell’elemen-
to xsd:schema. Il valore xsd:selector specifica gli elementi da vincolare (gli elementi “Prodot-
to”), mentre xsd:field specifica gli attributi da vincolare (IDProdotto).
xsd:key e xsd:keyref possono essere utilizzati per creare riferimenti tra gli elementi. Per
esempio, si può creare un elemento “Cliente” e poi fare riferimento a esso da più elementi “Fat-
tura”:
<xsd:key name="IDCliente">
<xsd:selector xpath="tc:DatiVendite/"/>
<xsd:field xpath="tc:Cliente/@IDCliente"/>
</xsd:key>
line varchar2(2000);
begin
xmlstr := dbms_lob.SUBSTR(result,32767);
loop
exit when xmlstr is null;
line := substr(xmlstr,1,instr(xmlstr,chr(10))-1);
dbms_output.put_line('| '||line);
xmlstr := substr(xmlstr,instr(xmlstr,chr(10))+1);
end loop;
end;
/
Ora che esiste la procedura PRINTCLOBOUT si esegua il seguente blocco PL/SQL anoni-
mo. Questo blocco effettua la query sulla tabella CLASSIFICAZIONE, quindi questa tabella
dovrà essere accessibile dallo schema (si faccia riferimento al CD-ROM allegato):
declare
queryCtx DBMS_XMLquery.ctxType;
result CLOB;
begin
-- configura il contesto di query...
queryCtx := DBMS_XMLQuery.newContext('select * from classificazione');
-- ottiene il risultato..
result := DBMS_XMLQuery.getXML(queryCtx);
-- Ora, si può utilizzare il risultato per inserirlo nelle tabelle/inviare come messaggi..
printClobOut(result);
DBMS_XMLQuery.closeContext(queryCtx); -- si deve chiudere la query..
end;
/
| <DESCRIZIONECLASSIFICAZIONE>LETTURA INDISPENSABILE</DESCRIZIONECLASSIFICAZIONE>
| </ROW>
| </ROWSET>
Ora i documenti XML possono essere passati alla procedura INSPROC sotto forma di valori
di input CLOB insieme al nome della tabella. INSPROC accetterà il documento XML e inserirà
i suoi valori nella tabella. Chiamando una procedura separata di nome UPDATEPROC, mostrata
nel listato seguente, si possono effettuare degli aggiornamenti:
I valori nuovi vengono passati come un documento XML in formato CLOB, e i valori della
tabella CLASSIFICAZIONE vengono aggiornati in base ai contenuti del documento XML.
Le operazioni di cancellazione funzionano in modo molto simile. La procedura seguente
accetta un documento XML come proprio input, imposta la colonna Classificazione come chia-
ve per la tabella CLASSIFICAZIONE ed esegue l’operazione di cancellazione basandosi sui
valori chiave contenuti nel documento di input. Si osservi che newContext accetta il nome della
tabella CLASSIFICAZIONE come proprio valore di input, mentre setKeyColumn accetta il nome
della colonna chiave (che in questo caso è sempre Classificazione).
880 CAPITOLO 47
XSU e Java
Se si preferisce, è possibile eseguire le operazioni DML di XSU chiamando delle classi Java al
posto delle procedure PL/SQL. Al posto del package DBMS_XMLQuery, si dovrebbe eseguire
la classe oracle.xml.sql.query.OracleXMLQuery. Al posto del package DBMS_XMLSave, oc-
corre usare oracle.xml.sql.dml.OracleXMLSave.
Per esempio, il campione di programma Java fornito da Oracle per le query XML è stato
leggermente personalizzato nel listato seguente. Esso si basa sulla gestione della connessione
eseguita in modo molto simile agli esempi JDBC (fare riferimento al Capitolo 38). Il programma
importa la classe oracle.xml.sql.query.OracleXMLQuery, permettendole di ottenere la stringa
XML; il metodo System.out.println di Java viene chiamato per visualizzare l’output.
import oracle.xml.sql.query.OracleXMLQuery;
import java.lang.*;
import java.sql.*;
try{
// Stabilisce la connessione
Connection conn = getConnection("practice","practice");
String password)
throws SQLException
{
// registra il driver JDBC..
DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
return conn;
}
}
Per dettagli sulla gestione delle connessioni e su Java, fare riferimento alla Parte sesta di
questo libro.
I dati verranno restituiti in formato CLOB, quindi il comando set long potrà servire per
impostare la lunghezza di visualizzazione massima (quella predefinita è di 80 caratteri). È pos-
sibile chiamare GET_XML dall’interno delle query SQL, come mostrato nel listato seguente:
GET_XML('SELECT*FROMCATEGORIA')
--------------------------------------------------
<?xml version = '1.0'?>
<ROWSET>
<ROW num="1">
<NOMECATEGORIA>CONSADULTI</NOMECATEGORIA>
<CATEGORIAPADRE>ADULTI</CATEGORIAPADRE>
<SOTTOCATEGORIA>CONSULTAZIONE</SOTTOCATEGORIA>
</ROW>
<ROW num="2">
<NOMECATEGORIA>NARRADULTI</NOMECATEGORIA>
<CATEGORIAPADRE>ADULTI</CATEGORIAPADRE>
882 CAPITOLO 47
<SOTTOCATEGORIA>NARRATIVA</SOTTOCATEGORIA>
</ROW>
<ROW num="3">
<NOMECATEGORIA>SAGGIADULTI</NOMECATEGORIA>
<CATEGORIAPADRE>ADULTI</CATEGORIAPADRE>
<SOTTOCATEGORIA>SAGGI</SOTTOCATEGORIA>
</ROW>
<ROW num="4">
<NOMECATEGORIA>ILLUSRAGAZZI</NOMECATEGORIA>
<CATEGORIAPADRE>RAGAZZI</CATEGORIAPADRE>
<SOTTOCATEGORIA>ILLUSTRATI</SOTTOCATEGORIA>
</ROW>
<ROW num="5">
<NOMECATEGORIA>NARRRAGAZZI</NOMECATEGORIA>
<CATEGORIAPADRE>RAGAZZI</CATEGORIAPADRE>
<SOTTOCATEGORIA>NARRATIVA</SOTTOCATEGORIA>
</ROW>
<ROW num="6">
<NOMECATEGORIA>SAGGIRAGAZZI</NOMECATEGORIA>
<CATEGORIAPADRE>RAGAZZI</CATEGORIAPADRE>
<SOTTOCATEGORIA>SAGGI</SOTTOCATEGORIA>
</ROW>
</ROWSET>
desc MIA_TABELLA_XML
desc MIA_TABELLA_XML
Name Null? Type
----------------------------------------- -------- -------------------
KEY1 NUMBER
XML_COLUMN SYS.XMLTYPE
METHOD
------
STATIC FUNCTION CREATEXML RETURNS XMLTYPE
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
XMLDATA CLOB IN
METHOD
------
MEMBER FUNCTION EXTRACT RETURNS XMLTYPE
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
XPATH VARCHAR2 IN
METHOD
------
MEMBER FUNCTION EXISTSNODE RETURNS NUMBER
Argument Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
XPATH VARCHAR2 IN
METHOD
------
MEMBER FUNCTION ISFRAGMENT RETURNS NUMBER
METHOD
------
MEMBER FUNCTION GETCLOBVAL RETURNS CLOB
METHOD
------
MEMBER FUNCTION GETSTRINGVAL RETURNS VARCHAR2
METHOD
------
MEMBER FUNCTION GETNUMBERVAL RETURNS NUMBER
</libro>'));
Con una chiamata al metodo GETCLOBVAL si può eseguire la query sui dati. Per esempio,
la query:
XML_DATA
-----------------------------------------------------
<libro>
<titolo>MY LEDGER</titolo>
<capitolo num="1">
<titolo>Beginning</titolo>
<testo>Questo è il registro di G.B. Talbot</testo>
</capitolo>
|</libro>
NOTA È possibile generare indici funzionali su colonne create con il tipo di dati
XMLType per migliorare le prestazioni delle query.
NOTA Per ulteriori dettagli sugli indici di testo, fare riferimento al Capitolo 25.
Oracle mette a disposizione i package seguenti per interagire con i dati XML:
DBMS_XMLGEN Converte i risultati delle query SQL in un formato XML canonico, restituendoli come CLOB: DBMS_XMLGEN
è implementato in C e compilato nel kernel del database. DBMS_XMLGEN assomiglia, a livello di funzio-
nalità, al package DBMS_XMLQuery.
SYS_XMLGEN Genera codice XML nelle query SQL. DBMS_XMLGEN e altri package operano a livello di query, dando
risultati aggregati per l’intera query. SYS_XMLGEN opera su singolo argomento in una query SQL e
converte il risultato in XML. SYS_XMLGEN accetta un valore scalare, un tipo di oggetto oppure un’istan-
za XMLType da convertire in un documento XML. Accetta anche un oggetto XMLGenFormatType facolta-
tivo, per specificare le opzioni di formattazione per il risultato. SYS_XMLGEN restituisce un tipo XML.
SYS_XMLAGG Aggrega più set di XMLTypes. SYS_XMLAGG aggrega tutti i documenti/frammenti XML di input e produ-
ce un singolo documento XML concatenando frammenti XML e aggiungendo una tag di livello superiore,
che ha come impostazione predefinita ROWSET.
GUIDA A XML IN ORACLE 885
Oracle mette a disposizione delle utility per supportare utilizzi aggiuntivi, come oraxml
(un’interfaccia a linea di comando usata per analizzare un documento XML) e oraxsl
(un’interfaccia a linea di comando usata per applicare un foglio di stile su più documenti XML).
Un’analisi completa di ogni utility e metodo di accesso ai dati andrebbe ben oltre lo scopo di
questo libro; per altre opzioni e programmi di esempio, si prega di consultare la documentazione
fornita con Oracle Database 10g. Per la descrizione delle funzioni che operano sulle istanze
XMLType, tra cui EXTRACT, EXTRACTVALUE, SYS_XMLAGG, SYS_XMLGEN, UPDATEXML,
XMLAGG, XMLCONCAT e XMLELEMENT, si rimanda al Capitolo 48.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Capitolo 48
Guida di riferimento
alfabetica
Q
uesto capitolo contiene la documentazione per l’utente di
Oracle Corporation riprodotta qui con l’autorizzazione di Oracle Corporation e offre un breve
riepilogo dei comandi SQL più comuni utilizzati dai DBA. I comandi sono disposti in ordine
alfabetico. Questo materiale è estratto dai documenti Oracle Database SQL Reference Release
10g, SQL*Plus User’s Guide and Reference, e Oracle Database Utilities 10g Release 1.
In questo capitolo vengono presentati i riferimenti relativi alla maggior parte dei comandi di
Oracle, le parole chiave, le funzionalità e le funzioni, con riferimenti incrociati tra gli argomenti.
Questa guida di riferimento è stata studiata per essere consultata sia dagli utenti sia dagli
sviluppatori di Oracle, ma richiede una certa familiarità con i prodotti. La lettura delle prime
pagine può essere d’aiuto per comprendere meglio la struttura della guida.
zato e raro che si è ritenuto non necessario includerle in questa guida. In questi casi, il testo fa
riferimento al manuale di Oracle, nel quale sarà possibile trovare le informazioni occorrenti.
RPAD
VEDERE ANCHE CARATTERI, FUNZIONI; LPAD, LTRIM, RTRIM, Capitolo 7.
SINTASSI
RPAD(stringa,lunghezza [ ,"set"])
DESCRIZIONE Abbreviazione di Right PAD (riempimento a destra). RPAD riempie una stringa
fino a una certa lunghezza, aggiungendo alla sua destra una determinata sequenza di caratteri. Se
non viene specificato il riempimento, viene aggiunto il carattere di riempimento predefinito: lo
spazio.
ESEMPIO
produce:
HELLO WORLDWORLDWORLDWOR
VARIABILE SIGNIFICATO
Colonna Nome di una colonna.
■ Tre puntini (o segno d’omissione) indicano che l’espressione precedente può essere ripetuta
per un numero di volte qualsiasi, come in colonna [,colonna]. . .; in questo caso colonna rappre-
senta un numero qualsiasi di colonne aggiuntive, separate tra loro da virgole.
■ In qualche raro caso la notazione normale è insufficiente, o inappropriata, per ciò che ci si
accinge a mostrare. In questi casi il testo del paragrafo “Descrizione” specifica in modo più
completo quanto evidenziato in “Sintassi”.
Simboli
I simboli vengono elencati in ordine di apparizione con una breve definizione o un nome. Quelli
che hanno definizioni in grassetto possiedono un’intera voce a essi dedicata, oppure rappresen-
tano prefissi a parole spiegate nelle pagine che seguono.
! punto esclamativo
# cancelletto
$ dollaro
? punto interrogativo
% segno di percentuale
(segue)
GUIDA DI RIFERIMENTO ALFABETICA 891
(continua)
() parentesi tonde
** esponenziale in PL/SQL
+ più
- sottrazione o trattino
.. vai a
: due punti
:= “uguale a” in PL/SQL
; punto e virgola
< minore di
<> diverso da
!= diverso da
= uguale a
> maggiore di
@ chiocciola
@@ doppia chiocciola
[] parentesi quadre
^ accento circonflesso
^= diverso da
{} parentesi graffe
|| concatenazione
892 CAPITOLO 48
_ (trattino di sottolineatura)
Il trattino di sottolineatura rappresenta una singola posizione assieme all’operatore LIKE. Vedere
LIKE.
_EDITOR
Vedere EDIT.
! (punto esclamativo)
VEDERE ANCHE =, CONTAINS, SOUNDEX, Capitolo 25.
SINTASSI
In SQL il punto esclamativo ! viene utilizzato come parte dell’espressione “diverso da” !=. Per
esempio, di seguito vengono selezionate tutte le città che non appartengono al continente Asia:
select Citta
from LOCALITA
where Continente != "ASIA";
Per gli indici di testo CONTEXT, ! comunica al motore di ricerca dei testi di eseguire una
ricerca SOUNDEX. I termini da ricercare vengono espansi in modo da includere termini che
assomigliano al testo cercato, utilizzando il valore SOUNDEX del testo per stabilire le possibili
corrispondenze; questo meccanismo vale quando si lavora con un testo in lingua inglese.
select Titolo
from CONTEXT_RECENSIONI_LIBRI
where CONTAINS(Testo_Recensione, "!grate")>0;
“ (doppi apici)
VEDERE ANCHE ALIAS, TO_CHAR, Capitolo 7 e Capitolo 10.
DESCRIZIONE " racchiude un alias di tabella o colonna che contiene caratteri speciali o uno
spazio, oppure racchiude testi letterali in una clausola in formato data di TO_CHAR.
ESEMPIO
In questo esempio viene utilizzato come alias:
# (cancelletto)
VEDERE ANCHE DOCUMENT, REMARK, /* */, Capitolo 6.
DESCRIZIONE # completa un blocco di documentazione in un file d’avvio di SQLPLUS, dove
il blocco inizia con la parola DOCUMENT. SQL*PLUS ignora tutte le linee a partire da quella
con la parola DOCUMENT fino alla linea dopo il segno #.
$ (dollaro)
VEDERE ANCHE @, @@, HOST, START, CONTAINS, Capitolo 25.
SINTASSI
Per SQL*PLUS:
$ comando_host
select colonna
from tabella
where CONTAINS(testo_colonna, '$termine_ricerca") >0;
DESCRIZIONE $ trasferisce qualsiasi comando dell’host al sistema operativo per essere esegui-
to senza uscire da SQL*PLUS. $ è una forma abbreviata di HOST. Questa funzione purtroppo
non garantisce il funzionamento su tutte le possibili piattaforme e sistemi operativi. Nel caso di
un indice di testo CONTEXT, $ istruisce il motore di ricerca in modo che esegua un’espansione
etimologica (stem) del termine di ricerca. Un’espansione etimologica include quelle parole che
hanno la stessa radice. Per esempio, un’espansione etimologica della parola ‘work’ include
‘works’, ‘working’ e così via.
? (punto interrogativo)
VEDERE ANCHE CONTAINS, Capitolo 25.
SINTASSI
select colonna
from tabella
where CONTAINS(testo_colonna, '?termine") >0;
DESCRIZIONE Per gli indici di testo CONTEXT, ? segnala al motore di ricerca dei testi di
eseguire una ricerca a corrispondenza non esatta. I termini da ricercare vengono espansi per
includere parole che sono scritte in modo simile al termine cercato, utilizzando l’indice per i
testi come fonte delle possibili corrispondenze.
% (segno percentuale)
% è un carattere jolly utilizzato per rappresentare qualsiasi numero di posizioni e caratteri con
l’operatore LIKE. Vedere LIKE.
894 CAPITOLO 48
%FOUND
VEDERE ANCHE %ISOPEN, %NOTFOUND, %ROWCOUNT, CURSOR, SQL CURSOR,
Capitolo 29.
SINTASSI
cursore%FOUND
oppure:
SQL%FOUND
DESCRIZIONE %FOUND rappresenta un flag di successo per select, insert, update e delete.
cursore è il nome di un cursore esplicito dichiarato in un blocco PL/SQL, oppure il cursore
implicito di nome SQL. %FOUND può essere associato al nome di un cursore come suffisso. I
due assieme rappresentano un flag di successo relativo all’esecuzione delle istruzioni select,
insert, update e delete all’interno di blocchi PL/SQL.
PL/SQL impegna temporaneamente una parte di memoria come blocco degli appunti per
l’esecuzione di istruzioni SQL e per memorizzare certi tipi di informazione (o attributi) relativi
allo stato di questa esecuzione. Se l’istruzione SQL è select, quest’area contiene una riga di dati.
%FOUND rappresenta uno di questi attributi. %FOUND normalmente viene testato (con il
ricorso alla logica IF/THEN) dopo che è stata eseguita un’istruzione fetch esplicita dal cursore.
Sarà TRUE se l’istruzione fetch ottiene una riga, altrimenti sarà FALSE. Viene sempre valutato
TRUE, FALSE o NULL. %NOTFOUND è il suo opposto logico. Risulta FALSE quando %FOUND
è pari a TRUE, TRUE quando %FOUND è FALSE e NULL quando %FOUND è NULL.
L’esecuzione del controllo su %FOUND per conoscere la condizione di un cursore esplicito
prima che venga aperto provoca un errore di tipo EXCEPTION (codice d’errore ORA-01001,
INVALID CURSOR).
%ISOPEN
VEDERE ANCHE CURSORE SQL, Capitolo 29.
SINTASSI
cursore%ISOPEN
%NOTFOUND
Vedere %FOUND.
GUIDA DI RIFERIMENTO ALFABETICA 895
%ROWCOUNT
VEDERE ANCHE CLOSE, DECLARE, DELETE, FETCH, INSERT, OPEN, SELECT, UPDATE,
Capitolo 29.
SINTASSI
cursore%ROWCOUNT
%ROWTYPE
VEDERE ANCHE FETCH, Capitolo 29.
SINTASSI
{[utente.]tabella | cursore}%ROWTYPE
DESCRIZIONE %ROWTYPE dichiara una variabile di un record in modo che abbia la stessa
struttura di un’intera riga di una tabella (o vista), oppure di una riga recuperata tramite il cursore
specificato. %ROWTYPE viene utilizzato come parte della dichiarazione di una variabile e fa in
modo che la variabile contenga i campi appropriati e i tipi di dati per gestire tutte le colonne
riportate. Se viene specificato [utente.]tabella, la tabella (o vista) specificata deve esistere nel
database.
Per creare una variabile che contenga i campi corrispondenti, occorre utilizzare declare, il
nome di una variabile e %ROWTYPE con il nome della tabella, per poi selezionare una riga nel
record. Dato che la variabile ha la stessa struttura della tabella, è possibile fare riferimento ai
campi come variabile.campo, utilizzando una notazione simile a quella tabella.colonna propria
delle istruzioni SQL. select...into e fetch...into rappresentano i soli metodi per caricare un intero
record in una variabile. I singoli campi all’interno del record possono essere caricati utilizzando
la notazione :=, come mostrato di seguito:
BIBLIOTECA_RECORD.Editore := "PANDORA";
Se come prefisso per %ROWTYPE si utilizza un cursore, esso può contenere un’istruzione
select con tante colonne quante sono necessarie. Tuttavia, se una colonna prelevata da un cursore
specifico è un’espressione, anziché un semplice nome di colonna, a questa espressione dev’esse-
re dato un alias nell’istruzione select prima che sia possibile farvi riferimento tramite questo
metodo.
896 CAPITOLO 48
%TYPE
VEDERE ANCHE %ROWTYPE, Capitolo 29.
SINTASSI
{[utente.]tabella.colonna | variabile}%TYPE
DESCRIZIONE %TYPE viene utilizzato per dichiarare una variabile dello stesso tipo di quella
dichiarata precedentemente, oppure come colonna particolare di una tabella già esistente nel
database cui si è collegati.
ESEMPIO
In questo esempio viene dichiarata una nuova variabile, Scrittore, in modo che sia dello stesso
tipo della colonna NomeAutore della tabella AUTORE. Dal momento che Scrittore ora esiste,
può essere utilizzata per dichiarare un’altra nuova variabile, Coautore.
Scrittore AUTORE.NomeAutore%TYPE;
Coautore Scrittore%TYPE;
&intero
&variabile
&&variabile
select Titolo
from CONTEXT_RECENSIONI_LIBRI
where CONTAINS(Testo_Recensione, "proprietà e raccolti")>0;
DESCRIZIONE & e && possono essere utilizzati in diversi modi (&& si applica solamente alla
seconda definizione descritta di seguito).
■ Prefisso dei parametri di un file di avvio di SQL*PLUS. &1, &2 e così via vengono sostituiti
da valori. Vedere START.
■ Prefisso di una variabile di sostituzione di un comando SQL in SQL*PLUS. SQL*PLUS
richiede l’inserimento di un valore se trova una variabile & o && non definita. && definisce la
variabile e quindi ne preserva il valore; & non definisce o preserva il valore, ma semplicemente
esegue una sostituzione di ciò che viene inserito. Vedere ACCEPT e DEFINE.
■ Quando si impiegano indici CONTEXT, & può inoltre essere utilizzato per segnalare una
condizione AND per ricerche di testi che coinvolgono più termini. Se anche solo uno dei termini
ricercati non viene trovato, il testo non viene restituito dall’operazione di ricerca.
SINTASSI
"stringa"
DESCRIZIONE Gli apici singoli racchiudono dei letterali (come stringhe di caratteri o date). Per
specificare un apice o un apostrofo all’interno di una costante di tipo stringa, è necessario inse-
rire due simboli ' (non un doppio apice). È opportuno evitare l’utilizzo di apostrofo nelle date (e
altrove) ogni volta che sia possibile.
ESEMPIO
produce:
Guglielmo
produce:
Guglielmo l"attore
( ) (parentesi)
VEDERE ANCHE PRECEDENZA, SUBQUERY, UPDATE, Capitoli 13 e 15.
DESCRIZIONE Delimita subquery, elenchi di colonne o precedenze di controlli all’interno del-
le espressioni.
* (moltiplicazione)
VEDERE ANCHE +, -, /, Capitoli 8 e 24.
SINTASSI
valore1 * valore2
DESCRIZIONE valore1 * valore2 significa valore1 moltiplicato per valore2. Per gli indici
CONTEXT, * viene utilizzato per ponderare in modo diverso i singoli termini ricercati.
** (esponenziale)
VEDERE ANCHE POWER.
SINTASSI
x ** y
DESCRIZIONE Il valore x viene elevato alla potenza y. x e y possono essere costanti, variabili,
colonne o espressioni. Entrambe devono essere di tipo numerico.
898 CAPITOLO 48
ESEMPIO
4**4 = 256
+ (addizione)
VEDERE ANCHE -, *, /, Capitolo 8.
SINTASSI
valore1 + valore2
valore1 - valore2
DESCRIZIONE valore1 – valore2 significa valore1 meno valore2. Per gli indici CONTEXT, un
segno meno ‘–’ indica la ricerca, all’interno del testo, di due termini per sottrarre il punteggio
ottenuto dalla ricerca del secondo termine da quello della ricerca del primo, prima di confrontare
il risultato con il punteggio di soglia. Per gli indici CTXCAT, un segno meno ‘–’ segnala al
motore di ricerca di escludere la riga dal set di risultati se il termine che segue il segno ‘–’ viene
trovato.
-- (commento)
VEDERE ANCHE /* */, REMARK, Capitolo 6.
GUIDA DI RIFERIMENTO ALFABETICA 899
SINTASSI
-- qualsiasi testo
SINTASSI
&variabile.suffisso
define Viale = 21
select '&Viale.a Strada n 100' from DUAL;
produce:
[utente.][tabella.]colonna
select Pratica.BIBLIOTECA.Titolo
from Pratica.BIBLIOTECA, Pratica.BIBLIOTECA_AUTORE
900 CAPITOLO 48
Se la tabella contiene colonne basate su un tipo di dato astratto, l’accesso agli attributi di
quest’ultimo può avvenire con il ricorso alla notazione . (punto).
select C.Persona.Indirizzo.Citta
from Societa C
where C.Persona.Indirizzo.Provincia = "MI";
.. (a)
Vedere CICLI.
valore1 / valore2
/* */ (commento)
VEDERE ANCHE REMARK, Capitolo 6.
SINTASSI
/* testo qualsiasi */
:nome
DESCRIZIONE nome è il nome di una variabile host. Quando si incorpora PL/SQL in un lin-
guaggio host attraverso un precompilatore di Oracle, è possibile fare riferimento alle variabili
host dai blocchi PL/SQL, facendo precedere i loro nomi nel linguaggio host con un segno di due
punti. A tutti gli effetti si fa riferimento alla variabile host. Se PL/SQL cambia il suo valore
attraverso un assegnamento (:=), il valore della variabile host viene modificato. Esse possono
essere utilizzate ovunque possa essere specificata una variabile PL/SQL. L’unica eccezione con-
siste nell’assegnamento del valore NULL a una variabile host, che non viene supportato diretta-
mente, ma richiede l’utilizzo di una variabile indicatore.
ESEMPIO
int ConteggioLibri;
...
select CONTEGGIO(*) into :ConteggioLibri from BIBLIOTECA;
:= (uguale a)
VEDERE ANCHE DECLARE, FETCH, SELECT INTO, Capitolo 29.
SINTASSI
variabile := espressione
DESCRIZIONE La variabile PL/SQL viene impostata uguale a espressione, che può essere una
costante, NULL oppure un’operazione di calcolo con altre variabili, lettere e funzioni di PL/SQL.
ESEMPIO
; (punto e virgola)
VEDERE ANCHE / (barra), BUFFER, EDIT, GET, RUN, SQLTERMINATOR, CONTAINS,
NEAR, Capitolo 25.
DESCRIZIONE ; esegue l’istruzione SQL o il comando che lo precede. Per gli indici CONTEXT
indica di effettuare una ricerca di vicinanza per le stringhe di testo specificate. Se i termini da
cercare fossero ‘estate’ e ‘vacanza’, una ricerca di prossimità potrebbe essere strutturata nella
maniera seguente:
select Testo
from SONNET
where CONTAINS(Testo,"estate;vacanza") >0;
Quando si valutano i risultati della ricerca testuale, le righe contenenti ‘estate’ e ‘vacanza’ in
stretta prossimità ottengono punteggi maggiori di quelle in cui le due parole distano di più.
902 CAPITOLO 48
@file
@@ (doppia chiocciola)
VEDERE ANCHE @ (Forma 1), START.
SINTASSI
@@file
{} (parentesi graffe)
VEDERE ANCHE CONTAINS, Capitolo 25, Capitolo 37.
SINTASSI
Per le ricerche di testo, {} indica che il testo racchiuso dev’essere considerato parte di una
stringa di ricerca anche se si tratta di una parola riservata. Per esempio, se il termine ricercato è
‘in and out’ e si desidera ritrovare l’intera frase, è necessario racchiudere la parola ‘and’ tra
parentesi graffe:
GUIDA DI RIFERIMENTO ALFABETICA 903
In Java le parentesi graffe {} indicano l’inizio e la fine di un blocco. Vedere il Capitolo 34 per
degli esempi di blocchi Java.
| (barra verticale )
VEDERE ANCHE BTITLE, HEADSEP, TTITLE, Capitolo 6, Capitolo 25.
SINTASSI
testo|testo
produce:
Ecco invece come viene utilizzato come clausola OR in una query di ricerca dei testi:
|| (concatenazione)
VEDERE ANCHE . (punto [forma 1]), CONCAT, SUBSTR, Capitolo 7.
SINTASSI
espressione1 || espressione2
ESEMPIO
Si utilizza || per visualizzare una colonna di città, seguite da una virgola, uno spazio e dal paese
a cui appartengono:
ABS(valore)
valore dev’essere un numero, sia un numero di tipo letterale, sia il nome di una colonna numeri-
ca, oppure una stringa di caratteri contenente un numero valido o ancora una colonna di caratteri
contenente solo numeri validi.
DESCRIZIONE Il valore assoluto è la misura della grandezza di un elemento ed è sempre un
numero positivo.
ESEMPI
ABS(146) = 146
ABS(-30) = 30
ABS("-27.88") = 27.88
ACCEPT
VEDERE ANCHE &, &&, DEFINE.
SINTASSI
DESCRIZIONE ACCEPT preleva l’input dalla tastiera dell’utente e lo registra nella variabile
specificata. Se la variabile non è stata prima definita tramite DEFINED, viene creata. NUMBER,
CHAR o DATE determinano il tipo di dato della variabile nel momento in cui viene inserita.
CHAR accetta qualsiasi numero o carattere. DATE accetta stringhe di caratteri con formati di data
validi (in caso contrario, viene restituito un messaggio d’errore). NUMBER accetta solo numeri,
con un punto decimale e un segno meno opzionali, altrimenti ACCEPT produce un messaggio
d’errore. FORMAT specifica il formato di input per la risposta (come A20). DEFAULT imposta il
valore predefinito, nel caso non venga data una risposta. PROMPT visualizza il testo all’utente
prima di accettare l’input. NOPROMPT salta una riga e aspetta l’input senza visualizzare alcun
prompt. Se non si specifica né PROMPT né NOPROMPT, ACCEPT inventa un prompt per richie-
dere di introdurre il nome per la variabile. HIDE occulta il valore inserito dall’utente ed è utile
per password e simili.
ESEMPIO
L’esempio che segue chiede all’utente “Che temperatura c’è?” e registra il dato inserito dal-
l’utente in una variabile di nome Temperatura:
ACCESSO CONCORRENTE
Accesso concorrente è un termine generale che indica l’accesso allo stesso dato da parte di più
utenti. Nel software per database, l’accesso concorrente richiede una programmazione software
complessa per assicurare che tutti gli utenti abbiano accesso ai dati corretti e che ogni modifica
venga effettuata nell’ordine appropriato.
ACCUMULATE
Vedere CONTAINS.
ACOS
VEDERE ANCHE ASIN, ATAN, ATAN2, COS, COSH, EXP, LN, LOG, SIN, SINH, TAN,
TANH.
SINTASSI
ACOS(valore)
ADD_MONTHS
VEDERE ANCHE DATE, FUNZIONI; Capitolo 10.
SINTASSI
ADD_MONTHS(data,intero)
select ADD_MONTHS(TO_DATE("22-APR-01"),1),
ADD_MONTHS(TO_DATE("22-APR-01"),.3) from DUAL;
ADD_MONTH ADD_MONTH
--------- ---------
22-MAY-01 22-APR-01
ALIAS
L’alias rappresenta un nome temporaneo assegnato a una tabella o ad una colonna all’interno di
un’istruzione SQL e viene utilizzato per fare riferimento a questi elementi in un altro punto nella
stessa istruzione (se si tratta di una tabella) o in un comando SQL*PLUS (se si tratta di una
906 CAPITOLO 48
colonna). Per separare la definizione della colonna dal proprio alias, è possibile utilizzare la
parola chiave AS. Vedere " (apici doppi), AS e SELECT. Quando si ricorre a un alias per una
tabella, esso viene chiamato nome di correlazione.
ALIAS DI TABELLA
L’alias di tabella è un sostituto temporaneo per un nome di tabella. Viene definito nella clausola
from dell’istruzione select. Vedere AS e il Capitolo 11.
ALL
VEDERE ANCHE ANY, BETWEEN, EXISTS, IN, OPERATORI LOGICI, Capitolo 13.
SINTASSI
DESCRIZIONE != ALL è l’equivalente di NOT IN. operatore può essere =, >, >=, <, <=, !=,
mentre elenco rappresenta una serie di stringhe letterali (quali ‘Mario’, ‘Giorgio’, ‘Ilaria’) oppu-
re una serie di numeri letterali (come 2, 43, 76, 32.06, 444) o una colonna da una query seconda-
ria, dove ciascuna riga della subquery diventa un membro dell’elenco, come per:
Può inoltre rappresentare una serie di colonne nella clausola where della query principale,
come mostrato di seguito:
LIMITAZIONI
elenco non può rappresentare una serie di colonne all’interno di una subquery, come:
Molti trovano che questo operatore e l’operatore ANY siano alquanto difficili da memorizza-
re, perché la logica utilizzata da entrambi in alcuni casi non è immediatamente intuitiva. Di
conseguenza vengono solitamente sostituiti con alcune forme di EXISTS. La combinazione di
un operatore con ALL e un elenco può risultare più chiara dalla seguente tabella.
Pag = ALL (4,2,7) Pag è uguale a ciascun elemento dell’elenco. Nessun numero soddisfa la condizione. Se una subquery
restituisse un elenco in cui tutti gli elementi siano identici, il valore di Pag potrebbe essere uguale a
ciascuno di essi, ma si tratta di un caso raro.
Pag > ALL (4,2,7) Pag è maggiore dell’elemento più grande nell’elenco (4,2,7). Qualsiasi elemento maggiore di 7 soddisfa
la condizione.
Pag >= ALL (4,2,7) Pag è maggiore o uguale all’elemento più grande nell’elenco (4,2,7). Qualsiasi elemento maggiore o
uguale a 7 soddisfa la condizione.
Pag < ALL (4,2,7) Pag è minore del più piccolo elemento nell’elenco (4,2,7). Qualsiasi elemento minore di 2 soddisfa la
condizione.
(segue)
GUIDA DI RIFERIMENTO ALFABETICA 907
(continua)
Pag <= ALL (4,2,7) Pag è minore o uguale all’elemento più piccolo nell’elenco (4,2,7). Qualsiasi elemento minore o uguale
a 2 soddisfa la condizione.
Pag != ALL (4,2,7) Pag è diverso da qualsiasi elemento dell’elenco. Qualsiasi numero soddisfa la condizione, fatta eccezio-
ne per 4, 2 e 7.
DESCRIZIONE La clausola ALLOCATE alloca una variabile cursore cui sia possibile fare riferi-
mento in un blocco PL/SQL. Consultare la documentazione del precompilatore per maggiori
dettagli su ALLOCATE e le clausole correlate, come il puntatore host.
ALTER CLUSTER
VEDERE ANCHE CREATE CLUSTER, CREATE TABLE, STORAGE, Capitolo 17.
SINTASSI
alter_cluster::=
schema .
ALTER CLUSTER cluster
physical_attributes_clause
SIZE size_clause
parallel_clause
allocate_extent_clause
;
deallocate_unused_clause
CACHE
NOCACHE
physical_attributes_clause::=
PCTFREE integer
PCTUSED integer
INITRANS integer
storage_clause
908 CAPITOLO 48
allocate_extent_clause::=
SIZE size_clause
( DATAFILE ’ filename ’ )
INSTANCE integer
ALLOCATE EXTENT
deallocate_unused_clause::=
KEEP size_clause
DEALLOCATE UNUSED
size_clause::=
T
integer
parallel_clause::=
NOPARALLEL
integer
PARALLEL
DESCRIZIONE Le descrizioni dei parametri si trovano alla voce CREATE TABLE. I parametri
di ALTER CLUSTER hanno lo stesso scopo ed effetto di quelli CREATE TABLE, tranne per il
fatto che vengono utilizzati per modificare un cluster. SIZE viene descritto alla voce CREATE
CLUSTER. Per modificare un cluster, è necessario esserne il proprietario o disporre del privile-
gio di sistema ALTER ANY CLUSTER.
Tutte le tabelle di un cluster utilizzano i valori per i parametri PCTFREE, PCTUSED,
INITRANS, MAXTRANS, TABLESPACE e STORAGE impostati da CREATE CLUSTER. ALTER
CLUSTER modifica questi valori per i blocchi di cluster successivi, ma non ha effetto su quelli
già esistenti. ALTER CLUSTER non consente di modificare il parametro MINEXTENTS in
STORAGE. La clausola DEALLOCATE UNUSED consente al cluster di compattare la propria
dimensione, liberando dello spazio inutilizzato.
ESEMPIO
ALTER DATABASE
VEDERE ANCHE ALTER ROLLBACK SEGMENT, AVVIO, CREATE DATABASE, RECOVER,
SHUTDOWN, Capitolo 46.
SINTASSI
alter_database::=
startup_clauses
recovery_clauses
database_file_clauses
logfile_clauses
database
ALTER DATABASE controlfile_clauses ;
standby_database_clauses
default_settings_clauses
redo_thread_clauses
security_clause
startup_clauses::=
STANDBY
DATABASE
CLONE
MOUNT
RESETLOGS UPGRADE
OPEN
READ ONLY
recovery_clauses::=
general_recovery
managed_standby_recovery
BEGIN
BACKUP
END
910 CAPITOLO 48
general_recovery::=
TEST
LOGFILE ’ filename ’
DEFAULT
CONTINUE
CANCEL
full_database_recovery::=
CANCEL
CHANGE integer
partial_database_recovery::=
TABLESPACE tablespace
’ filename ’
DATAFILE
filenumber
TABLESPACE tablespace
CONSISTENT WITH
,
STANDBY UNTIL CONTROLFILE
’ filename ’
DATAFILE
filenumber
GUIDA DI RIFERIMENTO ALFABETICA 911
parallel_clause::=
NOPARALLEL
integer
PARALLEL
managed_standby_recovery::=
recover_clause
cancel_clause
finish_clause
RECOVER MANAGED STANDBY DATABASE
recover_clause::=
FROM SESSION
DISCONNECT
TIMEOUT integer
NOTIMEOUT
NODELAY
DEFAULT DELAY
DELAY integer
NEXT integer
EXPIRE integer
NO EXPIRE
parallel_clause
THREAD integer
SEQUENCE integer
ALL ARCHIVELOG
THROUGH
ALL
LAST SWITCHOVER
NEXT
912 CAPITOLO 48
cancel_clause::=
WAIT
IMMEDIATE NOWAIT
CANCEL
finish_clause::=
FROM SESSION
DISCONNECT parallel_clause
WAIT
STANDBY LOGFILE
SKIP NOWAIT
FINISH
database_file_clauses::=
create_datafile_clause
alter_datafile_clause
alter_tempfile_clause
create_datafile_clause::=
, file_specification
AS
’ filename ’ NEW
CREATE DATAFILE
filenumber
alter_datafile_clause::=
ONLINE
, FOR DROP
’ filename ’ OFFLINE
DATAFILE
filenumber RESIZE size_clause
autoextend_clause
END BACKUP
GUIDA DI RIFERIMENTO ALFABETICA 913
size_clause::=
T
integer
alter_tempfile_clause::=
RESIZE size_clause
, autoextend_clause
’ filename ’ INCLUDING DATAFILES
TEMPFILE
filenumber DROP
ONLINE
OFFLINE
autoextend_clause::=
OFF
AUTOEXTEND NEXT size_clause maxsize_clause
ON
maxsize_clause::=
UNLIMITED
MAXSIZE
size_clause
logfile_clauses::=
MANUAL
ARCHIVELOG
NOARCHIVELOG
NO
FORCE LOGGING
(segue)
914 CAPITOLO 48
(continua)
,
UNARCHIVED UNRECOVERABLE DATAFILE
CLEAR LOGFILE logfile_descriptor
add_logfile_clauses
drop_logfile_clauses
supplemental_db_logging
add_logfile_clauses::=
STANDBY
ADD LOGFILE
INSTANCE ’ instance_name ’ ,
,
,
REUSE
MEMBER ’ filename ’ TO logfile_descriptor
drop_logfile_clauses::=
STANDBY
DROP LOGFILE
logfile_descriptor
MEMBER ’ filename ’
supplemental_db_logging::=
ADD DATA
SUPPLEMENTAL LOG
DROP supplemental_id_key_clause
GUIDA DI RIFERIMENTO ALFABETICA 915
supplemental_id_key_clause::=
ALL
PRIMARY KEY
DATA ( ) COLUMNS
UNIQUE
FOREIGN KEY
logfile_descriptor::=
GROUP integer
( ’ filename ’ )
’ filename ’
controlfile_clauses::=
LOGICAL
PHYSICAL REUSE
CREATE STANDBY CONTROLFILE AS ’ filename ’
REUSE
’ filename ’
BACKUP CONTROLFILE TO
trace_file_clause
trace_file_clause::=
RESETLOGS
REUSE
AS ’ filename ’ NORESETLOGS
TRACE
standby_database_clauses::=
activate_standby_db_clause
maximize_standby_db_clause
register_logfile_clause parallel_clause
commit_switchover_clause
start_standby_clause
stop_standby_clause
916 CAPITOLO 48
activate_standy_db_clause::=
PHYSICAL
STANDBY LOGFILE
LOGICAL SKIP
ACTIVATE STANDBY DATABASE
maximize_standby_db_clause::=
PROTECTION
PERFORMANCE
register_logfile_clause::=
PHYSICAL ,
FOR logminer_session_name
commit_switchover_clause::=
PREPARE
TO SWITCHOVER
COMMIT
PHYSICAL
PRIMARY
LOGICAL
WITH WAIT
TO SESSION SHUTDOWN
PHYSICAL WITHOUT NOWAIT
STANDBY
LOGICAL STANDBY
CANCEL
GUIDA DI RIFERIMENTO ALFABETICA 917
start_standby_clause::=
IMMEDIATE NODELAY
START LOGICAL STANDBY APPLY
scn_value
INITIAL
FINISH
stop_standby_clause::=
STOP
LOGICAL STANDBY APPLY
ABORT
default_settings_clauses::=
BIGFILE
SET DEFAULT TABLESPACE
SMALLFILE
tablespace
DEFAULT TEMPORARY TABLESPACE
tablespace_group_name
REUSE
USING FILE ’ filename ’
ENABLE BLOCK CHANGE TRACKING
flashback_mode_clause
set_time_zone_clause
set_time_zone_clause::=
+
hh : mi
–
SET TIME_ZONE = ’ ’
time_zone_region
918 CAPITOLO 48
flashback_mode_clause::=
ON
FLASHBACK
OFF
redo_thread_clauses::=
INSTANCE ’ instance_name ’
ENABLE
PUBLIC
DISABLE
THREAD integer
security_clause::=
ALL
GUARD STANDBY
NONE
ALTER DIMENSION
VEDERE ANCHE CREATE DIMENSION, DROP DIMENSION, Capitolo 24.
SINTASSI
alter_dimension::=
schema .
ALTER DIMENSION dimension
level_clause
hierarchy_clause
ADD
attribute_clause
extended_attribute_clause
RESTRICT
CASCADE
LEVEL level
;
HIERARCHY hierarchy
DROP ,
COLUMN column
LEVEL level
ATTRIBUTE attribute
COMPILE
level_clause::=
level_table . level_column
LEVEL level IS ,
( level_table . level_column )
GUIDA DI RIFERIMENTO ALFABETICA 921
hierarchy_clause::=
dimension_join_clause
HIERARCHY hierarchy ( child_level CHILD OF parent_level )
dimension_join_clause::=
child_key_column
( child_key_column )
attribute_clause::=
dependent_column
( dependent_column )
extended_attribute_clause::=
dependent_column
( dependent_column )
ALTER DISKGROUP
VEDERE ANCHE CREATE DISKGROUP, DROP DISKGROUP, Capitolo 46.
SINTASSI
alter_diskgroup::=
disk_clauses
ALTER DISKGROUP ;
diskgroup_clauses
922 CAPITOLO 48
disk_clauses::=
add_disk_clause
diskgroup_name drop_disk_clauses
resize_disk_clauses
diskgroup_name
undrop_disk_clause
ALL
diskgroup_clauses::=
rebalance_diskgroup_clause
check_diskgroup_clauses
diskgroup_template_clauses
diskgroup_name
diskgroup_directory_clauses
diskgroup_alias_clauses
drop_diskgroup_file_clause
diskgroup_name
diskgroup_availability
ALL
add_disk_clause::=
,
FAILGROUP failgroup_name
ADD DISK qualified_disk_clause
qualified_disk_clause::=
FORCE
size_clause::=
T
integer
drop_disk_clauses::=
FORCE
NOFORCE
DISK disk_name
,
DROP FORCE
NOFORCE
DISKS IN FAILGROUP failgroup_name
resize_disk_clauses::=
SIZE size_clause
ALL
SIZE size_clause
RESIZE DISK disk_name
SIZE size_clause
DISKS IN FAILGROUP failgroup_name
undrop_disk_clause::=
UNDROP DISKS
924 CAPITOLO 48
rebalance_diskgroup_clause::=
POWER integer
REBALANCE
check_diskgroup_clauses::=
ALL
,
REPAIR
DISK disk_name
NOREPAIR
CHECK ,
FILE filename
diskgroup_template_clauses::=
,
ADD
TEMPLATE qualified_template_clause
ALTER
qualified_template_clause::=
MIRROR FINE
UNPROTECTED COARSE
template_name ATTRIBUTES ( )
GUIDA DI RIFERIMENTO ALFABETICA 925
diskgroup_directory_clauses::=
FORCE
NOFORCE
DROP DIRECTORY ’ filename ’
diskgroup_alias_clauses::=
drop_diskgroup_file_clause::=
diskgroup_availability::=
MOUNT
FORCE
NOFORCE
DISMOUNT
926 CAPITOLO 48
ALTER FUNCTION
VEDERE ANCHE CREATE FUNCTION, DROP FUNCTION, Capitolo 31.
SINTASSI
alter_function::=
schema .
ALTER FUNCTION function
compiler_parameters_clause::=
parameter_name = parameter_value
DESCRIZIONE Utilizzare il comando ALTER FUNCTION per ricompilare una funzione memo-
rizzata autonoma non valida. La ricompilazione esplicita elimina la necessità di ricorrere alla
ricompilazione implicita in fase di esecuzione. Per generare e memorizzare il codice da utilizza-
re con il debugger PL/SQL, è necessario usare l’opzioneDEBUG.
ESEMPIO
ALTER INDEX
VEDERE ANCHE CREATE INDEX, DROP INDEX, STORAGE, Capitoli 17 e 43.
SINTASSI
GUIDA DI RIFERIMENTO ALFABETICA 927
alter_index::=
schema .
ALTER INDEX index
deallocate_unused_clause
allocate_extent_clause
shrink_clause
parallel_clause
physical_attributes_clause
logging_clause
rebuild_clause
PARAMETERS ( ’ ODCI_parameters ’ )
ENABLE
DISABLE
;
UNUSABLE
RENAME TO new_name
COALESCE
MONITORING
USAGE
NOMONITORING
alter_index_partitioning
deallocate_unused_clause::=
KEEP size_clause
DEALLOCATE UNUSED
allocate_extent_clause::=
SIZE size_clause
( DATAFILE ’ filename ’ )
INSTANCE integer
ALLOCATE EXTENT
928 CAPITOLO 48
size_clause::=
T
integer
shrink_clause::=
COMPACT CASCADE
SHRINK SPACE
parallel_clause::=
NOPARALLEL
integer
PARALLEL
physical_attributes_clause::=
PCTFREE integer
PCTUSED integer
INITRANS integer
storage_clause
logging_clause::=
LOGGING
NOLOGGING
GUIDA DI RIFERIMENTO ALFABETICA 929
rebuild_clause::=
PARTITION partition
SUBPARTITION subpartition
REVERSE
NOREVERSE
REBUILD
parallel_clause
TABLESPACE tablespace
PARAMETERS ( ’ ODCI_parameters ’ )
ONLINE
COMPUTE STATISTICS
physical_attributes_clause
key_compression
logging_clause
key_compression::=
integer
COMPRESS
NOCOMPRESS
alter_index_partitioning::=
modify_index_default_attrs
add_hash_index_partition
modify_index_partition
rename_index_partition
drop_index_partition
split_index_partition
coalesce_index_partition
modify_index_subpartition
930 CAPITOLO 48
modify_index_default_attrs::=
physical_attributes_clause
tablespace
TABLESPACE
DEFAULT
logging_clause
add_hash_index_partition::=
coalesce_index_partition::=
parallel_clause
COALESCE PARTITION
modify_index_partition::=
deallocate_unused_clause
allocate_extent_clause
physical_attributes_clause
logging_clause
key_compression
COALESCE
UNUSABLE
GUIDA DI RIFERIMENTO ALFABETICA 931
rename_index_partition::=
PARTITION partition
RENAME TO new_name
SUBPARTITION subpartition
drop_index_partition::=
split_index_partition::=
index_partition_description::=
segment_attributes_clause
key_compression
partition
PARTITION
segment_attributes_clause::=
physical_attributes_clause
TABLESPACE tablespace
logging_clause
modify_index_subpartition::=
UNUSABLE
deallocate_unused_clause
932 CAPITOLO 48
DESCRIZIONE utente rappresenta l’utente in possesso dell’indice da modificare (gli altri uten-
ti, per eseguire questo comando, devono possedere i privilegi DBA); indice è il nome di un
indice esistente. Vedere CREATE TABLE per una descrizione di INITRANS. Il valore predefinito
per INITRANS per quanto riguarda gli indici è 2. STORAGE contiene clausole secondarie che
sono descritte sotto STORAGE. Per poter creare un indice, è necessario disporre del privilegio
INDEX sulla tabella e occorre inoltre essere il proprietario dell’indice oppure avere il privilegio
di sistema ALTER ANY INDEX.
La clausola REBUILD del comando ALTER INDEX modifica le caratteristiche di registrazio-
ne di un indice esistente. REBUILD utilizza l’indice esistente come base per il nuovo indice.
Vengono gestiti tutti i comandi di registrazione dell’indice, quali STORAGE (per l’allocazione
di extent), TABLESPACE (per spostare l’indice in una nuova tablespace) e INITRANS (per modi-
ficare il numero iniziale di voci).
È possibile modificare, rinominare, eliminare, suddividere o ricostruire partizioni dell’indice.
COMPRESS consente la compressione delle chiavi, eliminando l’occorrenza ripetuta di
valori di colonna chiave per gli indici non unici. intero specifica la lunghezza del prefisso (nu-
mero di colonne prefisso da comprimere). Per default gli indici non sono compressi. Non è
possibile comprimere un indice bitmap.
COMPUTE STATISTICS genera statistiche per l’ottimizzatore basato sui costi al momento
della ricostruzione dell’indice.
ALTER INDEXTYPE
VEDERE ANCHE CREATE INDEXTYPE, DROP INDEXYPE.
SINTASSI
alter_indextype::=
schema .
ALTER INDEXTYPE indextype
using_type_clause::=
schema . array_DML_clause
USING implementation_type
GUIDA DI RIFERIMENTO ALFABETICA 933
array_DML_clause::=
WITH
WITHOUT
ARRAY DML
schema .
schema . , varray_type
( type )
ALTER JAVA
VEDERE ANCHE CREATE JAVA, DROP JAVA, Capitolo 34.
SINTASSI
alter_java::=
SOURCE schema .
ALTER JAVA object_name
CLASS
, schema_name
RESOLVER ( ( match_string ) ) COMPILE
–
RESOLVE
;
invoker_rights_clause
invoker_rights_clause::=
CURRENT_USER
AUTHID
DEFINER
DESCRIZIONE ALTER JAVA ricompila un oggetto dello schema in sorgente Java. È anche pos-
sibile utilizzare questo comando per modificare l’autorizzazione imposta (proprietario o utente
corrente). Per modificare gli oggetti dello schema dell’origine Java, è necessario essere proprie-
tario dell’origine o della classe oppure essere in possesso del privilegio di sistema ALTER ANY
PROCEDURE.
934 CAPITOLO 48
schema .
ALTER MATERIALIZED VIEW materialized_view
physical_attributes_clause
table_compression
LOB_storage_clause
modify_LOB_storage_clause
alter_table_partitioning
parallel_clause
logging_clause
allocate_extent_clause
shrink_clause
CACHE
NOCACHE alter_iot_clauses
MODIFY scoped_table_ref_constraint
ENABLE
QUERY REWRITE
DISABLE
COMPILE
CONSIDER FRESH
;
GUIDA DI RIFERIMENTO ALFABETICA 935
physical_attributes_clause::=
PCTFREE integer
PCTUSED integer
INITRANS integer
storage_clause
table_compression::=
COMPRESS
NOCOMPRESS
LOB_storage_clause::=
( LOB_parameters )
LOB_parameters::=
TABLESPACE tablespace
ENABLE
STORAGE IN ROW
DISABLE
storage_clause
CHUNK integer
PCTVERSION integer
RETENTION
FREEPOOLS integer
CACHE
NOCACHE logging_clause
CACHE READS
936 CAPITOLO 48
modify_LOB_storage_clause::=
modify_LOB_parameters::=
storage_clause
PCTVERSION integer
RETENTION
FREEPOOLS integer
REBUILD FREEPOOLS
CACHE
NOCACHE logging_clause
CACHE READS
allocate_extent_clause
deallocate_unused_clause
parallel_clause::=
NOPARALLEL
integer
PARALLEL
logging_clause::=
LOGGING
NOLOGGING
allocate_extent_clause::=
SIZE size_clause
( DATAFILE ’ filename ’ )
INSTANCE integer
ALLOCATE EXTENT
deallocate_unused_clause::=
KEEP size_clause
DEALLOCATE UNUSED
GUIDA DI RIFERIMENTO ALFABETICA 937
size_clause::=
T
integer
shrink_clause::=
COMPACT CASCADE
SHRINK SPACE
alter_iot_clauses::=
index_org_table_clause
alter_overflow_clause
alter_mapping_table_clauses
COALESCE
index_org_table_clause::=
mapping_table_clause
PCTTHRESHOLD integer
key_compression index_org_overflow_clause
index_org_overflow_clause::=
alter_overflow_clause::=
allocate_extent_clause
OVERFLOW
deallocate_unused_clause
add_overflow_clause
938 CAPITOLO 48
add_overflow_clause::=
segment_attributes_clause
ADD OVERFLOW
segment_attributes_clause
( PARTITION )
scoped_table_ref_constraint::=
alter_mv_refresh::=
FAST
COMPLETE
FORCE
DEMAND
ON
COMMIT
START WITH
date
REFRESH
NEXT
ENFORCED
USING CONSTRAINTS
TRUSTED
FORCE schema .
ALTER MATERIALIZED VIEW LOG ON table
physical_attributes_clause
alter_table_partitioning
parallel_clause
logging_clause
allocate_extent_clause
shrink_clause
CACHE
NOCACHE
OBJECT ID ,
ROWID
new_values_clause
SEQUENCE
ADD
,
( column )
;
new_values_clause::=
INCLUDING
NEW VALUES
EXCLUDING
940 CAPITOLO 48
physical_attributes_clause::=
PCTFREE integer
PCTUSED integer
INITRANS integer
storage_clause
allocate_extent_clause::=
SIZE size_clause
( DATAFILE ’ filename ’ )
INSTANCE integer
ALLOCATE EXTENT
size_clause::=
T
integer
shrink_clause::=
COMPACT CASCADE
SHRINK SPACE
parallel_clause::=
NOPARALLEL
integer
PARALLEL
privilegio ALTER sulla tabella di log oppure disporre del privilegio di sistema ALTER ANY TABLE.
Vedere CREATE MATERIALIZED VIEW LOG e il Capitolo 23.
ALTER OPERATOR
VEDERE ANCHE CREATE OPERATOR, DROP OPERATOR.
SINTASSI
alter_operator::=
add binding_clause
schema .
ALTER OPERATOR operator drop_binding_clause ;
COMPILE
add_binding_clause::=
implementation_clause
using_function_clause
implementation_clause::=
context_clause
context_clause::=
using_function_clause::=
package .
schema . type .
USING function_name
942 CAPITOLO 48
drop_binding_clause::=
,
FORCE
DROP BINDING ( parameter_type )
ALTER OUTLINE
VEDERE ANCHE CREATE OUTLINE, DROP OUTLINE, Capitolo 43.
SINTASSI
alter_outline::=
PUBLIC REBUILD
ENABLE
DISABLE
DESCRIZIONE È possibile utilizzare ALTER OUTLINE per rinominare una struttura memoriz-
zata o per assegnarla a una categoria diversa. Le strutture memorizzate mantengono dei set di
suggerimenti per le query eseguite in precedenza. Consultare il Capitolo 43.
ALTER PACKAGE
VEDERE ANCHE CREATE PACKAGE, DROP PACKAGE, Capitolo 31.
SINTASSI
alter_package::=
schema .
ALTER PACKAGE package
PACKAGE
SPECIFICATION
DEBUG BODY
COMPILE
compiler_parameters_clause::=
parameter_name = parameter_value
ALTER PROCEDURE
VEDERE ANCHE CREATE PROCEDURE, DROP PROCEDURE, Capitolo 31.
SINTASSI
alter_procedure::=
schema .
ALTER PROCEDURE procedure
compiler_parameters_clause::=
parameter_name = parameter_value
DESCRIZIONE ALTER PROCEDURE ricompila una procedura PL/SQL. Per evitare sovracca-
richi in fase di esecuzione e messaggi d’errore è consigliabile compilare una procedura in antici-
po, in modo esplicito. Per modificare una procedura, è necessario esserne il proprietario oppure
possedere il privilegio di sistema ALTER ANY PROCEDURE.
ALTER PROFILE
VEDERE ANCHE CREATE PROFILE, DROP PROFILE, Capitolo 18.
SINTASSI
alter_profile::=
resource_parameters
ALTER PROFILE profile LIMIT ;
password_parameters
944 CAPITOLO 48
resource_parameters::=
SESSIONS_PER_USER
CPU_PER_SESSION
CPU_PER_CALL
integer
CONNECT_TIME
UNLIMITED
IDLE_TIME
DEFAULT
LOGICAL_READS_PER_SESSION
LOGICAL_READS_PER_CALL
COMPOSITE_LIMIT
M
integer
PRIVATE_SGA UNLIMITED
DEFAULT
password_parameters::=
FAILED_LOGIN_ATTEMPTS
PASSWORD_LIFE_TIME
expr
PASSWORD_REUSE_TIME
UNLIMITED
PASSWORD_REUSE_MAX
DEFAULT
PASSWORD_LOCK_TIME
PASSWORD_GRACE_TIME
function
PASSWORD_VERIFY_FUNCTION NULL
DEFAULT
CPU_PER_SESSION
CONNECT_TIME
ALTER RESOURCE COST integer ;
LOGICAL_READS_PER_SESSION
PRIVATE_SGA
DESCRIZIONE La formula per il costo della risorsa calcola il costo totale delle risorse utilizzate
in una sessione di Oracle. ALTER RESOURCE COST consente di assegnare un peso a diverse
risorse. CPU_PER_SESSION rappresenta la quantità di CPU utilizzata in una sessione in cente-
simi di secondo. CONNECT_TIME è il tempo trascorso all’interno di una sessione, in minuti.
LOGICAL_READS_ PER_SESSION rappresenta il numero di blocchi di dati letti sia dalla me-
moria sia dal disco durante una sessione. PRIVATE_SGA è il numero di byte contenuti nella
SGA (System Global Area) privata, importante solo se si sta utilizzando l’architettura a server
condiviso. Assegnando dei pesi, è possibile modificare la formula utilizzata per calcolare il costo
della risorsa totale.
ALTER ROLE
VEDERE ANCHE CREATE ROLE, DROP ROLE, Capitolo 18.
SINTASSI
alter_role::=
NOT IDENTIFIED
BY password
ALTER ROLE role ;
schema .
IDENTIFIED USING package
EXTERNALLY
GLOBALLY
SINTASSI
alter_rollback_segment::=
ONLINE
OFFLINE
storage_clause
ALTER ROLLBACK SEGMENT rollback_segment ;
K
M
TO integer
SHRINK
ALTER SEQUENCE
VEDERE ANCHE AUDIT, CREATE SEQUENCE, DROP SEQUENCE, GRANT, NEXTVAL,
REVOKE e CURRVAL alla voce PSEUDOCOLONNE, Capitolo 17.
SINTASSI
alter_sequence::=
INCREMENT BY integer
MAXVALUE integer
NOMAXVALUE
MINVALUE integer
schema . NOMINVALUE
ALTER SEQUENCE sequence ;
CYCLE
NOCYCLE
CACHE integer
NOCACHE
ORDER
NOORDER
DESCRIZIONE Tutte queste opzioni influenzano l’utilizzo futuro di una sequenza esistente di
nome sequenza (si osservi che start with non è disponibile; per modificare il valore con cui viene
avviata una sequenza, è necessario eliminarla con DROP e ricrearla tramite CREATE).
GUIDA DI RIFERIMENTO ALFABETICA 947
Non può essere specificato un nuovo MAXVALUE inferiore all’attuale valore di CURRVAL
per le sequenze in ordine crescente (ossia una sequenza che ha un numero positivo come valore
INCREMENT BY). Analogamente, la stessa regola vale per MINVALUE per quanto riguarda le
sequenze in ordine decrescente (caratterizzate da un valore INCREMENT BY negativo).
Per effettuare questa operazione è necessario possedere il privilegio ALTER per la sequenza
o il privilegio di sistema DROP ANY SEQUENCE.
Tutte le altre funzionalità di ALTER SEQUENCE funzionano allo stesso modo che nel co-
mando CREATE SEQUENCE, fatta eccezione per il fatto che vengono applicate a una sequenza
esistente. Vedere CREATE SEQUENCE per ulteriori dettagli.
ALTER SESSION
VEDERE ANCHE Oracle9i Performance Guide and Reference, Oracle9i Database
Administrator's Guide.
SINTASSI
alter_session::=
COMMIT
ADVISE ROLLBACK
NOTHING
ENABLE
COMMIT IN PROCEDURE
DISABLE
ENABLE
GUARD
DISABLE
ALTER SESSION ;
ENABLE DML
PARALLEL integer
DISABLE PARALLEL DDL
FORCE QUERY
DISABLE RESUMABLE
alter_session_set_clause
alter_session_set_clause::=
Per disabilitare questa funzionalità è sufficiente impostare questo parametro al valore FALSE. Il
parametro di inizializzazione SQL_TRACE imposta il valore iniziale per questo report.
ADVISE consente di inviare una comunicazione di gestione della transazione ai database
remoti coinvolti nelle transazioni distribuite. Per eliminare il collegamento di una sessione a un
database remoto, è possibile chiudere (CLOSE) il collegamento al database (DATABASE LINK).
È possibile specificare se è possibile effettuare il COMMIT delle procedure, il grado in cui le
operazioni DML vengono messe in parallelo, e se la ripresa delle operazioni è consentita. Se si
abilitano le operazioni DML o DDL parallele per la propria sessione, occorre sempre specificare
il suggerimento PARALLEL per le operazioni che devono essere eseguite in parallelo.
Per abilitare o disabilitare l’allocazione dello spazio recuperabile, occorre disporre del pri-
vilegio di sistema RESUMABLE.
ALTER SYSTEM
VEDERE ANCHE ALTER SESSION, ARCHIVE_LOG, CREATE PROFILE.
SINTASSI
alter_system::=
archive_log_clause
checkpoint_clause
check_datafiles_clause
MINUTES integer
DUMP ACTIVE SESSION HISTORY
distributed_recov_clauses
restricted_session_clauses
SHARED_POOL
FLUSH
BUFFER_CACHE
SWITCH LOGFILE
SUSPEND
RESUME
quiesce_clauses
shutdown_dispatcher_clause
REGISTER
SET alter_system_set_clause
RESET alter_system_reset_clause
GUIDA DI RIFERIMENTO ALFABETICA 949
archive_log_clause::=
INSTANCE ’ instance_name ’
THREAD integer
ARCHIVE LOG
SEQUENCE integer
CHANGE integer
NOSWITCH
CURRENT
NEXT
ALL
START
STOP
checkpoint_clause::=
GLOBAL
LOCAL
CHECKPOINT
check_datafiles_clause::=
GLOBAL
LOCAL
CHECK DATAFILES
distributed_recov_clauses::=
ENABLE
DISTRIBUTED RECOVERY
DISABLE
950 CAPITOLO 48
restricted_session_clauses::=
ENABLE
RESTRICTED SESSION
DISABLE
end_session_clauses::=
POST_TRANSACTION
DISCONNECT SESSION ’ integer1 , integer2 ’ IMMEDIATE
quiesce_clauses::=
QUIESCE RESTRICTED
UNQUIESCE
shutdown_dispatcher_clause::=
IMMEDIATE
SHUTDOWN dispatcher_name
alter_system_set_clause::=
,
COMMENT ’ text ’ DEFERRED
parameter_name = parameter_value
MEMORY
alter_system_reset_clause::=
MEMORY
SCOPE = SPFILE
BOTH
parameter_name SID = ’ sid ’
GUIDA DI RIFERIMENTO ALFABETICA 951
ALTER TABLE
VEDERE ANCHE CREATE TABLE, DISABLE, DROP, ENABLE, Capitoli 17 e 46.
SINTASSI
alter_table::=
schema .
ALTER TABLE table
alter_table_properties
column_clauses
constraint_clauses
alter_table_partitioning enable_disable_clause
alter_table_properties::=
physical_attributes_clause
logging_clause
table_compression
supplemental_table_logging
allocate_extent_clause
deallocate_unused_clause
shrink_clause
CACHE
NOCACHE
upgrade_table_clause alter_iot_clauses
records_per_block_clause
parallel_clause
row_movement_clause
RENAME TO new_table_name
physical_attributes_clause::=
PCTFREE integer
PCTUSED integer
INITRANS integer
storage_clause
logging_clause::=
LOGGING
NOLOGGING
table_compression::=
COMPRESS
NOCOMPRESS
GUIDA DI RIFERIMENTO ALFABETICA 953
supplemental_table_logging::=
supplemental_log_grp_clause
ADD SUPPLEMENTAL LOG
supplemental_id_key_clause
supplemental_id_key_clause
DROP SUPPLEMENTAL LOG
GROUP log_group
supplemental_log_grp_clause::=
NO LOG ALWAYS
GROUP log_group ( column )
supplemental_id_key_clause::=
ALL
PRIMARY KEY
DATA ( ) COLUMNS
UNIQUE
FOREIGN KEY
allocate_extent_clause::=
SIZE size_clause
( DATAFILE ’ filename ’ )
INSTANCE integer
ALLOCATE EXTENT
deallocate_unused_clause::=
KEEP size_clause
DEALLOCATE UNUSED
954 CAPITOLO 48
size_clause::=
T
integer
shrink_clause::=
COMPACT CASCADE
SHRINK SPACE
upgrade_table_clause::=
NOT
INCLUDING DATA column_properties
UPGRADE
records_per_block_clause::=
MINIMIZE
RECORDS_PER_BLOCK
NOMINIMIZE
parallel_clause::=
NOPARALLEL
integer
PARALLEL
row_movement_clause::=
ENABLE
ROW MOVEMENT
DISABLE
alter_iot_clauses::=
index_org_table_clause
alter_overflow_clause
alter_mapping_table_clauses
COALESCE
GUIDA DI RIFERIMENTO ALFABETICA 955
index_org_table_clause::=
mapping_table_clause
PCTTHRESHOLD integer
key_compression index_org_overflow_clause
mapping_table_clauses::=
MAPPING TABLE
NOMAPPING
key_compression::=
integer
COMPRESS
NOCOMPRESS
index_org_overflow_clause::=
segment_attributes_clause::=
physical_attributes_clause
TABLESPACE tablespace
logging_clause
alter_overflow_clause::=
allocate_extent_clause
OVERFLOW
deallocate_unused_clause
add_overflow_clause
956 CAPITOLO 48
add_overflow_clause::=
segment_attributes_clause
ADD OVERFLOW
segment_attributes_clause
( PARTITION )
alter_mapping_table_clauses::=
allocate_extent_clause
MAPPING TABLE
deallocate_unused_clause
column_clauses::=
add_column_clauses
modify_column_clauses
drop_column_clause
rename_column_clause
modify_collection_retrieval
modify_LOB_storage_clause
alter_varray_col_properties
add_column_clause::=
inline_constraint
column_properties
GUIDA DI RIFERIMENTO ALFABETICA 957
modify_column_clauses::=
modify_col_properties
MODIFY
modify_col_substitutable
modify_col_properties::=
modify_col_substitutable::=
NOT FORCE
COLUMN column SUBSTITUTABLE AT ALL LEVELS
drop_column_clause::=
CASCADE CONSTRAINTS
COLUMN column
INVALIDATE
SET UNUSED ,
( column )
CASCADE CONSTRAINTS
COLUMN column
INVALIDATE CHECKPOINT integer
DROP ,
( column )
rename_column_clause::=
modify_collection_retrieval::=
LOCATOR
MODIFY NESTED TABLE collection_item RETURN AS
VALUE
958 CAPITOLO 48
constraint_clauses::=
out_of_line_constraint
ADD
out_of_line_ref_constraint
CONSTRAINT constraint
PRIMARY KEY
MODIFY constraint_state
,
UNIQUE ( column )
drop_constraint_clause
drop_contraint_clause::=
KEEP
PRIMARY KEY INDEX
CASCADE DROP
,
UNIQUE ( column )
DROP
CASCADE
CONSTRAINT constraint
column_properties::=
object_type_col_properties
nested_table_col_properties
varray_col_properties ( LOB_partition_storage )
LOB_storage_clause
XMLType_column_properties
object_type_col_properties::=
substitutable_column_clause::=
ELEMENT TYPE
IS OF ( ONLY type )
NOT
SUBSTITUTABLE AT ALL LEVELS
nested_table_col_properties::=
nested_item substitutable_column_clause
NESTED TABLE STORE AS storage_table
COLUMN_VALUE
( object_properties )
( physical_properties ) LOCATOR
RETURN AS
column_properties VALUE
object_properties::=
inline_constraint
attribute
out_of_line_constraint
out_of_line_ref_constraint
supplemental_logging_props
supplemental_logging_props::=
supplemental_log_grp_clause
supplemental_id_key_clause
960 CAPITOLO 48
physical_properties::=
table_compression
segment_attributes_clause
segment_attributes_clause table_compression
HEAP
segment_attributes_clause
ORGANIZATION
INDEX index_org_table_clause
EXTERNAL external_table_clause
varray_col_properties::=
VARRAY varray_item
LOB_segname
substitutable_column_clause ( LOB_parameters )
STORE AS LOB
LOB_segname
substitutable_column_clause
LOB_storage_clause::=
( LOB_parameters )
GUIDA DI RIFERIMENTO ALFABETICA 961
LOB_parameters::=
TABLESPACE tablespace
ENABLE
STORAGE IN ROW
DISABLE
storage_clause
CHUNK integer
PCTVERSION integer
RETENTION
FREEPOOLS integer
CACHE
NOCACHE logging_clause
CACHE READS
modify_LOB_storage_clause::=
modify_LOB_parameters::=
storage_clause
PCTVERSION integer
RETENTION
FREEPOOLS integer
REBUILD FREEPOOLS
CACHE
NOCACHE logging_clause
CACHE READS
allocate_extent_clause
deallocate_unused_clause
alter_varray_col_properties::=
LOB_partition_storage::=
LOB_storage_clause
PARTITION partition
varray_col_properties
LOB_storage_clause
( SUBPARTITION subpartition )
varray_col_properties
XMLType_column_properties::=
XMLType_storage::=
OBJECT RELATIONAL
( LOB_parameters )
STORE AS LOB_segname
LOB_parameters
CLOB
XMLSchema_spec::=
alter_external_table_clauses::=
add_column_clause
modify_column_clauses
drop_column_clause
parallel_clause
external_data_properties
integer
REJECT LIMIT
UNLIMITED
ALL
PROJECT COLUMN
REFERENCED
GUIDA DI RIFERIMENTO ALFABETICA 963
external_data_properties::=
( opaque_format_spec )
ACCESS PARAMETERS
USING CLOB subquery
DEFAULT DIRECTORY directory
directory :
LOCATION ( ’ location_specifier ’ )
alter_table_partitioning::=
modify_table_default_attrs
set_subpartition_template
modify_table_partition
modify_table_subpartition
move_table_partition
move_table_subpartition
add_table_partition
coalesce_table_partition
drop_table_partition
drop_table_subpartition
rename_partition_subpart
truncate_partition_subpart
split_table_partition
split_table_subpartition
merge_table_partitions
merge_table_subpartitions
exchange_partition_subpart
964 CAPITOLO 48
modify_table_default_attrs::=
segment_attributes_clause table_compression
LOB ( LOB_item )
( LOB_parameters )
VARRAY varray
set_subpartition_template::=
list_values_clause partitioning_storage_clause
( SUBPARTITION subpartition )
hash_subpartition_quantity
modify_table_partition::=
modify_range_partition
modify_hash_partition
modify_list_partition
GUIDA DI RIFERIMENTO ALFABETICA 965
modify_range_partition::=
partition_attributes
add_hash_subpartition
add_list_subpartition
update_index_clauses parallel_clause
COALESCE SUBPARTITION
alter_mapping_table_clause
REBUILD
UNUSABLE LOCAL INDEXES
modify_hash_partition::=
partition_attributes
alter_mapping_table_clause
REBUILD
UNUSABLE LOCAL INDEXES
modify_list_partition::=
partition_attributes
,
ADD
MODIFY PARTITION partition VALUES ( partition_value )
DROP
REBUILD
UNUSABLE LOCAL INDEXES
966 CAPITOLO 48
modify_table_subpartition::=
modify_hash_subpartition
MODIFY SUBPARTITION subpartition
modify_list_subpartition
move_table_partition::=
update_index_clauses parallel_clause
move_table_subpartition::=
update_index_clauses parallel_clause
MOVE subpartition_spec
add_table_partition::=
add_range_partition_clause
add_hash_partition_clause
add_list_partition_clause
add_range_partition_clause::=
add_hash_partition_clause::=
partition
ADD PARTITION
update_index_clauses parallel_clause
partitioning_storage_clause
add_list_partition_clause::=
coalesce_table_partition::=
update_index_clauses parallel_clause
COALESCE PARTITION
drop_table_partition::=
parallel_clause
update_index_clauses
DROP PARTITION partition
drop_table_subpartition::=
parallel_clause
update_index_clauses
DROP SUBPARTITION subpartition
rename_partition_subpart::=
PARTITION
RENAME current_name TO new_name
SUBPARTITION
truncate_partition_subpart::=
PARTITION partition
TRUNCATE
SUBPARTITION subpartition
DROP
STORAGE parallel_clause
REUSE update_index_clauses
split_table_partition::=
,
AT
SPLIT PARTITION current_partition ( value )
VALUES
update_index_clauses parallel_clause
968 CAPITOLO 48
split_table_subpartition::=
value
SPLIT SUBPARTITION subpartition VALUES ( )
NULL
update_index_clauses parallel_clause
merge_table_partitions::=
merge_table_subpartitions::=
INTO subpartition_spec
MERGE SUBPARTITIONS subpart_1 , subpart_2
update_index_clauses parallel_clause
exchange_partition_subpart::=
PARTITION partition
EXCHANGE WITH TABLE table
SUBPARTITION subpartition
INCLUDING WITH
INDEXES VALIDATION
EXCLUDING WITHOUT
parallel_clause
exceptions_clause update_index_clauses
exceptions_clause::=
schema .
EXCEPTIONS INTO table
GUIDA DI RIFERIMENTO ALFABETICA 969
list_values_clause::=
value
NULL
VALUES ( )
DEFAULT
range_values_clause::=
value
VALUES LESS THAN ( )
MAXVALUE
partitioning_storage_clause::=
TABLESPACE tablespace
TABLESPACE tablespace
OVERFLOW
( TABLESPACE tablespace )
LOB_segname
LOB ( LOB_item ) STORE AS
( TABLESPACE tablespace )
partition_attributes::=
physical_attributes_clause
logging_clause physical_attributes_clause
allocate_extent_clause logging_clause
OVERFLOW
deallocate_unused_clause allocate_extent_clause
shrink_clause deallocate_unused_clause
LOB LOB_item
modify_LOB_parameters
table_compression VARRAY varray
970 CAPITOLO 48
add_hash_subpartition::=
update_index_clauses parallel_clause
ADD subpartition_spec
add_list_subpartition::=
update_index_clauses
ADD subpartition_spec
modify_hash_subpartition::=
allocate_extent_clause
deallocate_unused_clause
shrink_clause
LOB LOB_item
modify_LOB_parameters
VARRAY varray
REBUILD
UNUSABLE LOCAL INDEXES
modify_list_subpartition::=
allocate_extent_clause
deallocate_unused_clause
shrink_clause
LOB LOB_item
modify_LOB_parameters
VARRAY varray
REBUILD
UNUSABLE LOCAL INDEXES
,
ADD
VALUES ( value )
DROP
GUIDA DI RIFERIMENTO ALFABETICA 971
table_partition_description::=
table_compression
segment_attributes_clause key_compression
segment_attributes_clause
OVERFLOW
LOB_storage_clause
varray_col_properties partition_level_subpartition
partition_level_subpartition::=
STORE IN ( tablespace )
SUBPARTITIONS hash_subpartition_quantity
( subpartition_spec )
partition_spec::=
partition table_partition_description
PARTITION
subpartition_spec::=
update_index_clauses::=
update_global_index_clause
update_all_indexes_clause
update_global_index_clause::=
UPDATE
GLOBAL INDEXES
INVALIDATE
972 CAPITOLO 48
update_all_indexes_clause::=
update_index_partition
( index ( ) )
update_index_subpartition
UPDATE INDEXES
update_index_partition::=
index_subpartition_clause
partition index_partition_description
PARTITION
update_index_subpartition::=
index_partition_description::=
segment_attributes_clause
key_compression
partition
PARTITION
index_subpartition_clause::=
STORE IN ( tablespace )
TABLESPACE tablespace
subpartition
( SUBPARTITION )
parallel_clause::=
NOPARALLEL
integer
PARALLEL
GUIDA DI RIFERIMENTO ALFABETICA 973
move_table_clause::=
LOB_storage_clause
enable_disable_clause::=
,
VALIDATE
UNIQUE ( column )
ENABLE NOVALIDATE
PRIMARY KEY
DISABLE
CONSTRAINT constraint
KEEP
INDEX
using_index_clause exceptions_clause CASCADE DROP
using_index_clause::=
schema .
index
index_properties
index_properties::=
global_partitioned_index
local_partitioned_index
index_attributes
domain_index_clause
974 CAPITOLO 48
index_attributes::=
physical_attributes_clause
logging_clause
ONLINE
COMPUTE STATISTICS
tablespace
TABLESPACE
DEFAULT
key_compression
SORT
NOSORT
REVERSE
parallel_clause
DESCRIZIONE ALTER TABLE modifica la definizione di una tabella esistente. ADD consente di
aggiungere una nuova colonna alla fine di una tabella esistente oppure aggiungere una limitazio-
ne alla definizione della tabella. Viene utilizzato lo stesso formato di CREATE TABLE.
MODIFY modifica una colonna esistente, con alcune restrizioni.
■ È possibile modificare il tipo di colonna o ridurne la dimensione solo se ciascuna riga della
colonna è NULL.
■ Una colonna NOT NULL può essere aggiunta solo a una tabella che non possiede alcuna riga.
■ Una colonna esistente può essere modificata in NOT NULL solo se possiede un valore non
nullo per ciascuna riga o se viene specificato un valore predefinito durante la modifica.
■ Incrementando la lunghezza di una colonna NOT NULL senza specificare NULL, questa vie-
ne lasciata invariata a NOT NULL.
È possibile utilizzare la clausola SET UNUSED per contrassegnare le colonne come inutiliz-
zate. Quando si utilizza la clausola DROP UNUSED COLUMNS, la tabella sarà riorganizzata e
tutte le colonne inutilizzate saranno rimosse.
ALLOCATE EXTENT consente di allocare in modo esplicito un nuovo extent. ENABLE e
DISABLE abilitano e disabilitano i vincoli. Tutte le altre funzionalità di ALTER TABLE funziona-
no allo stesso modo che nel comando CREATE TABLE, tranne per il fatto che vengono applicate
a una tabella esistente. Vedere CREATE TABLE per ulteriori dettagli.
Per modificare una tabella, è necessario essere in possesso del privilegio ALTER per quella
tabella o del privilegio di sistema ALTER ANY TABLE.
CACHE specifica che i blocchi per questa tabella, quando letti, devono essere contrassegnati
come “blocchi utilizzati più di recente” e mantenuti nella buffer cache dei blocchi di dati il più a
lungo possibile. Questa opzione è utile se le tabelle sono di piccole dimensioni e abbastanza
statiche. NOCACHE (l’opzione predefinita) inverte la tabella ritornando al funzionamento nor-
male per l’elenco LRU.
PARALLEL, assieme a DEGREE e INSTANCES, specifica le caratteristiche del funziona-
mento in parallelo della tabella (per i database che utilizzano l’opzione Real Application Clusters).
GUIDA DI RIFERIMENTO ALFABETICA 975
DEGREE specifica il numero di server da utilizzare per le query; INSTANCES specifica il modo
in cui la tabella dev’essere suddivisa tra le istanze di Real Application Clusters per l’elaborazio-
ne in parallelo delle query. Un intero n indica che la tabella dev’essere suddivisa tra il numero
specificato di istanze disponibili.
È possibile utilizzare ALTER TABLE per eseguire sulle partizioni i comandi ADD, DROP,
EXCHANGE, MODIFY, MOVE, SPLIT o TRUNCATE. Vedere il Capitolo 17 e CREATE TABLE.
Le clausole di memorizzazione LOB specificano l’area di memorizzazione da utilizzare per
i dati LOB che non saranno memorizzati nella tabella stessa (fuori linea).
L’opzione MOVE ONLINE consente di accedere a una tabella per effettuare operazioni DML
durante una riorganizzazione di tabella in linea. Le opzioni MOVE e MOVE ONLINE sono dispo-
nibili solo per le tabelle organizzate con indici e non partizionate. Durante un’operazione MOVE
ONLINE, le operazioni DML parallele sulla tabella non sono supportate.
A partire da Oracle Database 10g è possibile utilizzare la parola chiave COMPRESS, per
chiedere a Oracle di comprimere i segmenti dei dati per ridurre l’uso del disco e della memoria
per le tabelle che vengono caricate con inserimenti a percorso diretto.
ALTER TABLESPACE
VEDERE ANCHE CREATE TABLESPACE, DROP TABLESPACE, STORAGE, Capitoli 20 e 46.
SINTASSI
alter_tablespace::=
table_compression
DEFAULT storage_clause
M
MINIMUM EXTENT integer
RESIZE size_clause
COALESCE
RENAME TO new_tablespace_name
BEGIN
ALTER TABLESPACE tablespace BACKUP ;
END
datafile_tempfile_clauses
tablespace_logging_clauses
tablespace_group_clause
tablespace_state_clauses
autoextend_clause
flashback_mode_clause
tablespace_retention_clause
976 CAPITOLO 48
size_clause::=
T
integer
datafile_tempfile_clauses::=
DATAFILE file_specification
ADD
TEMPFILE
, ,
DATAFILE ONLINE
TEMPFILE OFFLINE
tablespace_logging_clauses::=
logging_clause
NO
FORCE LOGGING
tablespace_group_clause::=
tablespace_group_name
TABLESPACE GROUP
’ ’
GUIDA DI RIFERIMENTO ALFABETICA 977
tablespace_state_clauses::=
ONLINE
NORMAL
TEMPORARY
IMMEDIATE
OFFLINE
ONLY
READ
WRITE
PERMANENT
TEMPORARY
autoextend_clause::=
OFF
AUTOEXTEND NEXT size_clause maxsize_clause
ON
maxsize_clause::=
UNLIMITED
MAXSIZE
size_clause
flashback_mode_clause::=
ON
FLASHBACK
OFF
tablespace_retention_clause::=
GUARANTEE
RETENTION
NOGUARANTEE
978 CAPITOLO 48
DESCRIZIONE tablespace è il nome dello spazio occupato da una tabella. ADD DATAFILE
aggiunge alla tablespace un file o una serie di file descritti in base a una definizione_file, che
specifica i nomi e le dimensioni dei file del database: il formato del nome del file è specifico del
sistema operativo. SIZE rappresenta il numero di byte riservati per questo file. Specificando il
suffisso K, il valore viene moltiplicato per 1024; specificando M viene moltiplicato per 1048576.
REUSE (senza SIZE) significa distruggere il contenuto di qualunque file con quel nome e asse-
gnare il nome in modo che sia usato da questa tablespace. SIZE e REUSE creano il file, se non
esiste, e ne controllano la dimensione, nel caso esista già. SIZE da solo crea il file se non esiste,
ma in caso contrario restituisce un errore.
È possibile utilizzare la clausola AUTOEXTEND per ridimensionare dinamicamente i propri
file di dati, se necessario, incrementandoli di una dimensione pari a NEXT, fino a un massimo di
MAXSIZE (oppure UNLIMITED).
NOLOGGING specifica l’azione predefinita per la scrittura di voci di redo log per determi-
nati tipi di transazioni nella tablespace. È possibile ridefinire questa impostazione a livello di
oggetto. RENAME DATAFILE cambia il nome del file contenente una tablespace esistente. La
tablespace dev’essere sconnessa al momento in cui avviene il cambio del nome. Si osservi che
RENAME in realtà non rinomina i file; associa solamente i loro nuovi nomi con la tablespace in
questione. La modifica vera e propria dei nomi dei file all’interno del sistema operativo dev’es-
sere effettuata all’interno del sistema operativo stesso. Per cambiare in modo appropriato i nomi
ai file, per prima cosa occorre eseguire il comando ALTER TABLESPACE OFFLINE, rinominare
i file all’interno del sistema operativo, eseguendo un RENAME dei file con ALTER TABLESPACE
e, successivamente, eseguire il comando ALTER TABLESPACE ONLINE.
DEFAULT STORAGE definisce lo spazio di memorizzazione predefinito per tutti i futuri
oggetti creati nella tablespace in questione, fatta eccezione per quei valori predefiniti che vengo-
no reimpostati, per esempio tramite un’operazione CREATE TABLE. ONLINE riporta in linea la
tablespace. OFFLINE la disconnette, senza aspettare che i suoi utenti si scolleghino (opzione
IMMEDIATE) oppure dopo che tutti gli utenti hanno terminato la sessione (opzione NORMAL).
MINIMUM EXTENT imposta la dimensione minima per qualunque extent creato nella
tablespace. COALESCE combina gli extent liberi vicini tra loro nella tablespace in un numero
minore di extent liberi più grandi.
Le tablespace READ ONLY non vengono mai aggiornate da Oracle e possono essere colloca-
te su supporti di sola lettura. Le tablespace di sola lettura non hanno bisogno di backup ripetuti.
Tutti le tablespace vengono create con la possibilità di lettura e scrittura. Per riportare una
tablespace di sola lettura nello stato lettura-scrittura, si utilizza la clausola READ WRITE.
BEGIN BACKUP può essere eseguito in qualsiasi momento. Esso colloca la tablespace in
uno stato tale che un backup in linea può avvenire mentre vi sono utenti che accedono alla
tablespace. END BACKUP indica che il backup del sistema è finito. Se la tablespace è in linea,
qualunque salvataggio del sistema deve salvare anche i redo log dell’archivio. Se invece non è in
linea, questa operazione non è necessaria.
Le tablespace TEMPORARY non possono contenere alcun oggetto permanente (quali tabelle
o indici); possono solamente contenere i segmenti temporanei utilizzati da Oracle durante le
operazioni di ordinamento e di creazione di indici. Una tablespace PERMANENT può contenere
qualsiasi tipo di segmento di Oracle.
A partire da Oracle Database 10g, è possibile rinominare una tablespace con la clausola
RENAME. Si può anche garantire che i dati di undo saranno preservati, anche a spese delle
transazioni in corso che richiedono spazio di undo (tramite RETENTION GUARANTEE).
GUIDA DI RIFERIMENTO ALFABETICA 979
ALTER TRIGGER
VEDERE ANCHE CREATE TRIGGER, DROP TRIGGER, ENABLE, TRIGGER, Capitolo 30.
SINTASSI
alter_trigger::=
schema .
ALTER TRIGGER trigger
ENABLE
DISABLE
RENAME TO new_name ;
compiler_parameters_clause::=
parameter_name = parameter_value
ALTER TYPE
VEDERE ANCHE CREATE TYPE, CREATE TYPE BODY, Capitolo 33.
SINTASSI
alter_type::=
schema .
ALTER TYPE type
compile_type_clause
replace_type_clause
alter_method_spec ;
alter_attribute_definition dependent_handling_clause
alter_collection_clauses
NOT INSTANTIABLE
FINAL
980 CAPITOLO 48
compile_type_clause::=
SPECIFICATION
DEBUG BODY
COMPILE
compiler_parameters_clause::=
parameter_name = parameter_value
replace_type_clause::=
invoker_rights_clause
REPLACE AS OBJECT
,
,
, element_spec
( atttribute datatype )
invoker_rights_clause::=
CURRENT_USER
AUTHID
DEFINER
element_spec::=
subprogram_spec
inheritance_clauses , pragma_clause
constructor_spec
map_order_function_spec
inheritance_clauses::=
OVERRIDING
NOT
FINAL
INSTANTIABLE
GUIDA DI RIFERIMENTO ALFABETICA 981
subprogram_spec::=
MEMBER procedure_spec
STATIC function_spec
procedure_spec::=
IS
, call_spec
AS
PROCEDURE name ( parameter datatype )
function_spec::=
constructor_spec::=
FINAL INSTANTIABLE
CONSTRUCTOR FUNCTION datatype
,
SELF IN OUT datatype ,
( parameter datatype )
IS
call_spec
AS
RETURN SELF AS RESULT
map_order_function_spec::=
MAP
MEMBER function_spec
ORDER
pragma_clause::=
RNDS
WNDS
method_name
PRAGMA RESTRICT_REFERENCES ( , RNPS )
DEFAULT
WNPS
TRUST
982 CAPITOLO 48
alter_method_spec::=
ADD map_order_function_spec
DROP subprogram_spec
alter_attribute_definition::=
datatype
attribute
ADD
ATTRIBUTE ,
MODIFY
( attribute datatype )
attribute
DROP ATTRIBUTE ,
( attribute )
alter_collection_clauses::=
LIMIT integer
MODIFY
ELEMENT TYPE datatype
dependent_handling_clause::=
INVALIDATE
NOT
INCLUDING TABLE DATA
FORCE
CONVERT TO SUBSTITUTABLE exceptions_clause
CASCADE
exceptions_clause::=
schema .
EXCEPTIONS INTO table
DESCRIZIONE ALTER TYPE consente di modificare i tipi di dati astratti esistenti. Quando
viene creato un metodo che agisce sul tipo di dato astratto, si utilizza il comando CREATE TYPE
BODY (vedere la voce corrispondente in questo capitolo). Ciascun metodo definito nel corpo del
tipo deve prima essere elencato all’interno del tipo.
GUIDA DI RIFERIMENTO ALFABETICA 983
A partire da Oracle Database 10g, è possibile modificare array variabili e tabelle nidificate
di tipi scalari.
ALTER USER
VEDERE ANCHE CREATE TABLESPACE, GRANT, CREATE PROFILE, CREATE USER,
Capitolo 18.
SINTASSI
alter_user::=
REPLACE old_password
BY password
IDENTIFIED EXTERNALLY
GLOBALLY AS ’ external_name ’
tablespace
TEMPORARY TABLESPACE
tablespace_group_name
M
integer
QUOTA ON tablespace
UNLIMITED
user
PROFILE profile
role
,
DEFAULT ROLE EXCEPT role
ALL
ALTER USER ;
NONE
PASSWORD EXPIRE
LOCK
ACCOUNT
UNLOCK
user proxy_clause
984 CAPITOLO 48
proxy_clause::=
GRANT
CONNECT THROUGH proxy
REVOKE
role_name
ROLE ,
NO ROLES proxy_authentication
proxy_authentication::=
AUTHENTICATION REQUIRED
PASSWORD
DISTINGUISHED NAME
AUTHENTICATED USING
TYPE ’ type ’ VERSION ’ version ’
CERTIFICATE
ALTER VIEW
VEDERE ANCHE CREATE VIEW, DROP VIEW, Capitolo 17.
SINTASSI
GUIDA DI RIFERIMENTO ALFABETICA 985
alter_view::=
ADD out_of_line_constraint
RELY
MODIFY CONSTRAINT constraint
NORELY
UNIQUE ( column )
COMPILE
DESCRIZIONE ALTER VIEW ricompila una vista o ne modifica i vincoli. Per modificare una
vista è necessario esserne il proprietario oppure disporre del privilegio di sistema ALTER ANY
TABLE.
ALTRE FUNZIONI
Di seguito è riportato un elenco alfabetico di tutte le funzioni SQL di Oracle che non possono
essere classificate all’interno delle altre categorie. Ciascuna viene riportata altrove in questa
guida, assieme alla sintassi e ad esempi d’uso.
BFILENAME, COALESCE, CV, DECODE, DEPTH, DUMP, EMPTY_BLOB, EMPTY_CLOB,
EXISTSNODE, EXTRACT, EXTRACTVALUE, GREATEST, LEAST, LNNVL, NLS_CHARSET_
DECL_LEN, NLS_CHARSET_ID, NLS_CHARSET_NAME, NULLIF, NVL, NVL2, ORA_HASH,
PATH, PRESENTNNV, PRESENTV, PREVIOUS, SYS_CONNECT_BY_PATH, SYS_CONTEXT,
SYS_DBURIGEN, SYS_EXTRACT_UTC, SYS_GUID, SYS_TYPEID, SYS_XMLAGG,
SYS_XMLGEN, UID, UPDATEXML, USER, USERENV, VSIZE, XMLAGG, XMLCOLATTVAL,
XMLCONCAT, XMLFOREST, XMLSEQUENCE, XMLTRANSFORM
ANALISI
L’analisi è la corrispondenza di un’istruzione SQL a un cursore. A questo stadio, vengono effet-
tuati diversi controlli di convalida quali la verifica di esistenza di tutti gli oggetti indicati, il
controllo della correttezza delle concessioni e il controllo sintattico e semantico e così via. Inol-
tre, vengono prese decisioni riguardanti l’esecuzione e l’ottimizzazione del codice come la scel-
ta degli indici e così via.
ANALYZE
VEDERE ANCHE Capitolo 43.
986 CAPITOLO 48
SINTASSI
analyze::=
PARTITION ( partition )
PARTITION ( partition )
schema .
CLUSTER cluster
validation_clauses
into_clause
LIST CHAINED ROWS
SYSTEM ;
DELETE STATISTICS
compute_statistics_clause
estimate_statistics_clause
validation_clauses::=
for_clause::=
TABLE
LOCAL
ALL INDEXES
GUIDA DI RIFERIMENTO ALFABETICA 987
into_clause::=
schema .
INTO table
compute_statistics_clause::=
SYSTEM for_clause
COMPUTE STATISTICS
estimate_statistics_clause::=
SYSTEM for_clause
ESTIMATE STATISTICS
ROWS
SAMPLE integer
PERCENT
AND
Vedere OPERATORI LOGICI, PRECEDENZE, CONTAINS.
ANSI
L’American National Standards Institute stabilisce una serie di standard per il linguaggio SQL e
per molti dei suoi elementi.
ANY
VEDERE ANCHE ALL, BETWEEN, EXISTS, IN, OPERATORI LOGICI, Capitolo 13.
SINTASSI
DESCRIZIONE = ANY è l’equivalente di IN. operatore rappresenta uno dei seguenti operatori =,
>, >=, <, <=, != ed elenco può essere una serie di stringhe letterali (quali ‘Mario’, ‘Giovanni’ o
‘Ilaria’) o di numeri letterali (quali 2, 43, 76, 32.06 o 444) oppure una colonna ricavata da una
subquery, in cui ciascuna riga della subquery diventa membro di un elenco, come mostrato di
seguito:
Può inoltre rappresentare una serie di colonne nella clausola where della query principale,
come mostrato di seguito:
LIMITAZIONI
elenco non può essere una serie di colonne di una subquery del tipo:
Molti trovano difficoltà nel ricordare questo operatore, come per l’operatore ALL, perché la
logica di alcuni casi non è immediatamente intuitiva. Di conseguenza vengono solitamente so-
stituiti con alcune forme di EXISTS.
La combinazione di un operatore con ANY e con un elenco può risultare più chiara grazie
alla tabella seguente:
Pag > ANY (4,2,7) Pag è maggiore di qualsiasi singolo elemento nell’elenco (4,2,7); anche 3 soddisfa la condizione, per-
ché è maggiore di 2.
Pag >= ANY (4,2,7) Pag è maggiore o uguale a qualsiasi elemento nell’elenco (4,2,7); anche 2 soddisfa la condizione,
perché è uguale a 2.
Pag < ANY (4,2,7) Pag è minore di qualsiasi elemento dell’elenco (4,2,7); anche 6 soddisfa la condizione perché è minore di 7.
Pag <= ANY (4,2,7) Pag è minore o uguale a qualsiasi elemento dell’elenco (4,2,7); anche 7 soddisfa la condizione.
Pag != ANY (4,2,7) Pag è diverso da qualsiasi elemento singolo dell’elenco; qualsiasi numero soddisfa la condizione poiché
l’elenco contiene più di un valore. Con un solo valore, !=ANY equivale a !=.
APPEND
VEDERE ANCHE CHANGE, DEL, EDIT, LIST, Capitolo 6.
SINTASSI
A[PPEND] testo
essi viene considerato come simbolo di fine comando e scartato). APPEND non è disponibile in
iSQL*Plus
ESEMPIO
APPEND ;;
ARCH, PROCESSO
Uno dei processi in background utilizzati da Oracle; ARCH esegue archiviazioni automatiche di
file redo log quando il database viene utilizzato in modalità ARCHIVELOG . Vedere
BACKGROUND, PROCESSO.
ARCHIVE LOG
VEDERE ANCHE ALTER DATABASE, RECOVER, Capitolo 46.
SINTASSI
DESCRIZIONE ARCHIVE LOG avvia o interrompe l’archiviazione automatica dei file di redo
log in linea, archivia manualmente file di redo log specifici, oppure visualizza informazioni sui
file di redo log. START abilita l’archiviazione automatica, mentre STOP la disabilita. LIST mo-
stra lo stato di archiviazione dei redo log in linea. NEXT archivia manualmente il gruppo di file
di redo log successivo che è stato riempito ma non ancora archiviato. ALL archivia manualmente
tutti i gruppi di file di redo log riempiti ma non ancora archiviati. È possibile specificare il
numero del gruppo di file di redo log in linea e l’area di destinazione per i file archiviati.
ESEMPIO
ARCHIVIARE
In generale, archiviare significa salvare i dati per un possibile utilizzo futuro. In senso specifico,
significa salvare i dati trovati nei redo log in linea, nel caso che i log risultino necessari per
ripristinare il database in seguito a un errore verificatosi in uno dei supporti.
AREA DI CONTESTO
Un’area di contesto è un’area di lavoro all’interno della memoria in cui Oracle memorizza l’istru-
zione SQL corrente e, se si tratta di una query, una riga di risultato. L’area di contesto contiene lo
stato di un cursore.
ARRAY VARIABILE
Un array variabile è un collettore. Per ciascuna riga di una tabella è in grado di contenere più
voci. Il numero massimo di dati di un array variabile per riga viene impostato alla sua creazione
(con CREATE TYPE). Vedere il Capitolo 34.
990 CAPITOLO 48
ARRAYSIZE (SQL*PLUS)
Vedere SET.
AS
VEDERE ANCHE ALIAS, TO_CHAR, Capitolo 7 e Capitolo 10.
DESCRIZIONE AS viene utilizzato per separare le formule delle colonne dagli alias delle colonne.
ESEMPIO
In questo esempio AS separa l’alias GiornoPaga della colonna dalla formula della colonna stessa:
ASCII
VEDERE ANCHE CARATTERI, FUNZIONI; ASCIISTR; CHR.
SINTASSI
ASCII(stringa)
ASCIISTR
VEDERE ANCHE CARATTERI, FUNZIONI; ASCII; CHR.
SINTASSI
ASCIISTR(stringa)
GUIDA DI RIFERIMENTO ALFABETICA 991
DESCRIZIONE La funzione ASCII prende una stringa e restituisce il valore ASCII equivalente
nel set di caratteri del database.
ESEMPIO
A ASCII
- -----
E EMILY
ASIN
VEDERE ANCHE ACOS, ATAN, ATAN2, COS, COSH, EXP, LN, LOG, SIN, SINH, TAN,
TANH.
SINTASSI
ASIN(valore)
ASSOCIATE STATISTICS
VEDERE ANCHE ANALYZE.
SINTASSI
associate_statistics::=
column_association
ASSOCIATE STATISTICS WITH ;
function_association
column_association::=
schema .
COLUMNS table . column using_statistics_type
992 CAPITOLO 48
function_association::=
schema .
FUNCTIONS function
schema .
PACKAGES package
,
using_statistics_type
schema .
TYPES type , default_selectivity_clause
default_cost_clause
,
, default_cost_clause
schema . default_selectivity_clause
INDEXES index
schema .
INDEXTYPES indextype
using_statistics_type::=
schema .
statistics_type
USING
NULL
default_cost_clause::=
default_selectivity_clause::=
DESCRIZIONE ASSOCIATE STATISTICS associa un set di funzioni statistiche con una o più
colonne, funzioni standalone, package, tipi o indici. È necessario disporre dei privilegi richiesti
per poter applicare il comando ALTER all’oggetto modificato.
È possibile vedere le associazioni in USER_USTATS dopo aver analizzato l’oggetto con il
quale si stanno associando le proprie funzioni statistiche.
ATAN
VEDERE ANCHE ACOS, ASIN, ATAN2, COS, COSH, EXP, LN, LOG, SIN, SINH, TAN,
TANH.
SINTASSI
ATAN(valore)
DESCRIZIONE ASIN restituisce l’arcotangente di un valore. I valori di input sono infiniti; gli
output sono espressi in radianti.
ATAN2
VEDERE ANCHE ACOS, ASIN, ATAN, COS, COSH, EXP, LN, LOG, SIN, SINH, TAN, TANH.
SINTASSI
ATAN2(valore1, valore2)
DESCRIZIONE ATAN2 restituisce l’arcotangente di due valori. I valori di input sono infiniti; gli
output sono espressi in radianti.
ATTRIBUTE (SQL*Plus)
VEDERE ANCHE COLONNA, Capitolo 33.
SINTASSI
ALI[AS] alias
CLE[AR]
FOR[MAT] sintassi
LIKE {nome_tipo.nome_attributo|alias}
ON|OFF
DESCRIZIONE ATTRIBUTE imposta gli attributi di visualizzazione per gli attributi di una co-
lonna di tipo definito dall’utente in SQL*Plus.
ESEMPIO
AUDIT
VEDERE ANCHE CREATE DATABASE LINK, DIZIONARIO DI DATI, NOAUDIT, PRIVI-
LEGI.
SINTASSI
994 CAPITOLO 48
audit::=
sql_statement_clause
AUDIT
schema_object_clause
SESSION
BY NOT
ACCESS WHENEVER SUCCESSFUL
;
sql_statement_clause::=
statement_option
ALL
auditing_by_clause
,
system_privilege
ALL PRIVILEGES
auditing_by_clause::=
proxy
BY ,
user
schema_object_clause::=
object_option
auditing_on_clause
ALL
auditing_on_clause::=
schema .
object
ON DIRECTORY directory_name
DEFAULT
GUIDA DI RIFERIMENTO ALFABETICA 995
DESCRIZIONE È possibile applicare il comando AUDIT alle istruzioni eseguite dagli utenti e a
quelle che accedono a oggetti specifici.
Le opzioni dell’istruzione sono le seguenti.
NOT EXISTS Istruzioni SQL che falliscono perché l’oggetto non esiste.
PROCEDURE Crea o elimina una procedura, una funzione, una libreria o un package; crea il corpo del package.
TRIGGER Crea, modifica o elimina un trigger; modifica una tabella con ENABLE|DISABLE ALL TRIGGERS.
Quello che segue è un elenco delle opzioni a livello di istruzione aggiuntive disponibili.
996 CAPITOLO 48
COMMENT TABLE COMMENT ON TABLE tabella, vista, vista materializzata COMMENT ON COLUMN tabella.colonna,
vista.column, vista materializzata.colonna
AUTOCOMMIT (SQL*Plus)
AUTOCOMMIT è un’impostazione di SQL*PLUS utilizzata per effettuare il commit automatico
delle modifiche apportate al database a seguito di un comando SQL del tipo insert, update o
delete, rispettivamente, per l’inserimento, l’aggiornamento o l’eliminazione di dati nel database.
Vedere SET.
AUTORECOVERY (SQL*Plus)
Vedere SET.
AVG
VEDERE ANCHE COMPUTE, GROUP FUNCTIONS, Capitolo 9.
SINTASSI
DESCRIZIONE AVG è la media dei valori contenuti in un gruppo di righe. DISTINCT costringe
al calcolo della media solo di valori unici. Le righe NULL vengono ignorate da questa funzione,
in quanto potrebbero influire sul risultato.
BACKGROUND, PROCESSO
Un processo in background è uno dei processi utilizzati da un’istanza di Oracle allo scopo di
eseguire e coordinare operazioni per conto degli utenti simultaneamente collegati a un database.
BACKUP IN LINEA
Il backup in linea è la funzione di Oracle che archivia i dati durante l’esecuzione del database. Il
DBA non deve chiudere il database per archiviare i dati. Anche i dati in corso di accesso possono
essere archiviati.
BEGIN
VEDERE ANCHE BLOCCO, STRUTTURA; DECLARE; END; EXCEPTION; TERMINA-
TORE; Capitolo 29.
SINTASSI
[<<etichetta blocco>>]
[DECLARE]
BEGIN
... logica del blocco ...
END [etichetta blocco];
998 CAPITOLO 48
BETWEEN
Vedere OPERATORI LOGICI.
BFILE
BFILE è un tipo di dato (vedere DATI, TIPI) utilizzato per dati LOB binari memorizzati all’ester-
no del database. Oracle non gestisce la coerenza nella lettura o l’integrità dei dati memorizzati
esternamente. All’interno del database viene memorizzato il valore di un localizzatore LOB che
punta al file esterno. Prima di creare una voce BFILE, è necessario creare una directory. Vedere
CREATE DIRECTORY.
BFILENAME
VEDERE ANCHE BFILE, CREATE DIRECTORY, Capitolo 35.
SINTASSI
BINARY_DOUBLE
Vedere DATI, TIPI.
BINARY_FLOAT
Vedere DATI, TIPI.
BIN_TO_NUM
VEDERE ANCHE NUMERI, FUNZIONI; Capitolo 8.
GUIDA DI RIFERIMENTO ALFABETICA 999
SINTASSI
BIN_TO_NUM(1,0,0,1)
-------------------
9
BIND VARIABLE
Una bind variable è una variabile contenuta in un’istruzione SQL che dev’essere sostituita con
un valore valido o l’indirizzo di un valore in modo che l’istruzione possa essere eseguita corret-
tamente.
BITAND
VEDERE ANCHE DECODE, Capitolo 16.
SINTASSI
DESCRIZIONE BITAND effettua un’operazione di calcolo AND sui bit di argomento1 e argo-
mento2, che devono entrambi risolversi in numeri non negativi, e restituisce un intero. Questa
funzione viene normalmente utilizzata con la funzione DECODE.
BITMAP, INDICE
Un indice bitmap è un tipo di indice maggiormente adatto per colonne con pochi valori distinti (e
quindi, scarsa selettività). Se vi sono pochi valori distinti per una colonna e quest’ultima viene
utilizzata spesso come condizione di limitazione nelle query, è opportuno considerare l’impiego
di un indice bitmap per quella colonna. Vedere il Capitolo 20 per ulteriori dettagli sugli indici
bitmap. Per informazioni complete riguardo alla sintassi, vedere CREATE INDEX.
BLOB
Un BLOB è un oggetto binario di grandi dimensioni (Binary Large OBject), memorizzato all’in-
terno del database. Vedere il Capitolo 35.
per le operazioni del dizionario, i blocchi per le definizioni del dizionario e i blocchi per le
definizioni delle tabelle.
BLOCCO
Un blocco è l’unità di base di memorizzazione (fisica e logica) per tutti i dati di Oracle. La
dimensione del blocco di Oracle varia in relazione al sistema operativo e può essere diversa dalla
dimensione del blocco del sistema operativo dell’host. Le dimensioni di blocco più comuni sono
4K, 8K e 16K. Per conoscere la dimensione di un blocco sul proprio sistema operativo, fare
riferimento alla Installation and User’s Guide. Le dimensioni dei blocchi del database possono
differire a livello di tablespace.
BLOCCO (LOCK)
Un blocco è una restrizione temporanea dell’accesso ai dati per gli altri utenti. La restrizione
imposta a questi dati prende il nome di “lock”. Le modalità di lock sono SHARE, SHARE
UPDATE, EXCLUSIVE, SHARE EXCLUSIVE, ROW SHARE e ROW EXCLUSIVE. Non è
possibile acquisire tutti i blocchi in tutte le modalità.
BLOCCO ESCLUSIVO
Un blocco esclusivo è un sistema di limitazione degli accessi che consente ad altri utenti di
eseguire delle query sui dati pur vietando loro qualsiasi modifica. Si differenzia dal blocco SHARE
in quanto non permette che altri utenti applichino qualsiasi altro tipo di limitazione sugli stessi
dati; più utenti possono porre contemporaneamente blocchi SHARE sugli stessi dati.
BLOCCO, STRUTTURA
La struttura di un blocco è la struttura delle sezioni di un blocco in PL/SQL.
VEDERE ANCHE BEGIN, DECLARE, END, EXCEPTION, GOTO, Capitolo 29.
DESCRIZIONE I blocchi PL/SQL possono essere racchiusi in SQL*Plus, o in un qualunque
altro linguaggio di programmazione, con il ricorso ai precompilatori di Oracle. I blocchi PL/SQL
risultano strutturati nel modo seguente:
[<<etichetta blocco>>]
[DECLARE
.. dichiarazioni (CURSOR, VARIABLE ed EXCEPTION)...]
GUIDA DI RIFERIMENTO ALFABETICA 1001
BEGIN
[EXCEPTION
<<calc_areas>>
DECLARE
pi constant NUMBER(9,7) := 3.14159;
area NUMBER(14,2);
cursor rad_cursor is
select * from RADIUS_VALS;
rad_val rad_cursor%ROWTYPE;
BEGIN
open rad_cursor;
loop
fetch rad_cursor into rad_val;
exit when rad_cursor%NOTFOUND;
area := pi*power(rad_val.radius,2);
insert into AREAS values (rad_val.radius, area);
end loop;
close rad_cursor;
END calc_areas;
BREAK (SQL*Plus)
VEDERE ANCHE CLEAR, COMPUTE, Capitolo 6.
SINTASSI
Dove elemento_report è:
{colonna|espr|ROW|REPORT}
e azione è:
[SKI[P]n|[SKI[P]] PAGE][NODUP[LICATES]|DUP[LICATES]]
1002 CAPITOLO 48
BTITLE (SQL*Plus)
VEDERE ANCHE ACCEPT, DEFINE, PARAMETRI, REPFOOTER, REPHEADER, SET
HEADSEP, TTITLE.
SINTASSI
DESCRIZIONE BTITLE inserisce un testo (anche composto da più righe) alla fine di ciascuna
pagina di un report. OFF e ON rispettivamente sopprimono e ripristinano la visualizzazione del
testo senza modificarne i contenuti. BTITLE da solo visualizza le opzioni btitle e il testo o la
variabile. testo è un titolo di fondo pagina che si desidera aggiungere al report, mentre variabile
rappresenta una variabile definita dall’utente o una variabile gestita dal sistema, incluse SQL.LNO,
il numero della linea corrente, SQL.PNO, il numero di pagina corrente, SQL.RELEASE, il nu-
mero della versione di Oracle, SQL.SQLCODE, l’attuale codice d’errore, e SQL.USER, il nome
dell’utente.
Quella che segue è una descrizione delle opzioni specstampa.
■ COL n salta direttamente alla posizione n (dal margine sinistro) della linea corrente.
■ S[KIP] n visualizza n linee vuote. Se non viene specificato alcun numero, viene stampata una
sola linea vuota. Se n vale 0, non viene visualizzata alcuna linea vuota e la posizione di stampa
corrente diventa la prima della linea corrente (all’estremità sinistra della pagina).
GUIDA DI RIFERIMENTO ALFABETICA 1003
B*-TREE
B*-TREE rappresenta una struttura di indicizzazione utilizzata da Oracle per creare e memoriz-
zare gli indici.
BUFFER
In termini generali, un buffer è una specie di blocco degli appunti, solitamente contenuto nella
memoria del computer, in cui i comandi vengono posizionati temporaneamente per la modifica
e l’esecuzione.
In SQL*PLUS, un buffer rappresenta un’area di memoria per la modifica di comandi SQL.
Vedere EDIT e SET.
BUFFER (DATABASE)
I buffer del database sono spazi temporanei di memorizzazione di blocchi del database utilizzati
in quel momento dagli utenti.
CACHE
Le cache sono spazi temporanei di memorizzazione sia per i dati del database utilizzati (tramite
operazioni di accesso o modifica) in quel momento dagli utenti, sia per i dati richiesti da Oracle
per il supporto agli utenti.
1004 CAPITOLO 48
CALL
VEDERE ANCHE EXECUTE, Capitolo 39.
SINTASSI
call::=
routine_clause
CALL
object_access_expression
INDICATOR
: indicator_variable
INTO : host_variable
;
routine_clause::=
type .
function
schema . package .
procedure
method
@ dblink_name argument
( )
object_access_expression::=
argument
.
. method ( )
attribute
table_alias . column .
,
object_table_alias .
argument
( expr ) .
method ( )
DESCRIZIONE È possibile utilizzare CALL per eseguire una stored procedure o una funzione da
SQL. Occorre però disporre del privilegio EXECUTE sulla procedura o funzione, o sul package
nel quale la procedura o funzione esiste.
GUIDA DI RIFERIMENTO ALFABETICA 1005
CAMPO
In una tabella, un campo equivale all’informazione contenuta all’intersezione di una riga e di
una colonna. Generalmente, campo è sinonimo di colonna, sebbene possa riferirsi spesso ai
valori in essa contenuti.
CARATTERI, FUNZIONI
VEDERE ANCHE CONVERSIONE, FUNZIONI; NUMERI, FUNZIONI; ALTRE FUNZIO-
NI; Capitolo 7.
DESCRIZIONE Riportiamo un elenco alfabetico di tutte le funzioni per caratteri di SQL di
Oracle. Ciascuna viene riportata altrove in questa guida, assieme alla sintassi e ad esempi d’uso.
stringa || stringa
|| concatena due stringhe. Il simbolo | viene chiamato barra verticale spezzata, anche se in
alcuni computer può comparire come una barra intera.
ASCII(stringa)
CHR(intero)
CHR fornisce il carattere il cui valore ASCII equivale a un dato intero positivo.
CONCAT(stringa1,stringa2)
INITCAP(stringa)
Sta per INITial CAPital (iniziale maiuscola). Rende maiuscola la prima lettera di una parola.
LENGTH(stringa)
LOWER(stringa)
LPAD(stringa,lunghezza [,'car'])
LPAD sta per Left PAD (riempimento a sinistra). Rende una stringa di una lunghezza deter-
minata, aggiungendo a sinistra la sequenza di caratteri specificata da car.
1006 CAPITOLO 48
LTRIM(stringa [,'car'])
LTRIM sta per Left TRIM. Taglia dalla parte di sinistra di una stringa tutte le occorrenze
della sequenza di caratteri specificata da car.
NLS_INITCAP(stringa[,'NLS_SORT=ordine'])
NLS_INITCAP sta per National Language Support INItial CAPital. Questa versione di
INITCAP utilizza l’ordine della sequenza di confronto per effettuare la conversione tra maiusco-
le e minuscole.
NLS_LOWER(stringa,'NLS_SORT=ordine'])
NLS_LOWER sta per National Language Support LOWER case. Questa versione di LOWER
utilizza l’ordine della sequenza di confronto per effettuare la conversione tra maiuscole e minu-
scole.
NLS_UPPER(stringa[,'NLS_SORT=ordine'])
NLS_UPPER sta per National Language Support UPPER case. Questa versione di UPPER
utilizza l’ordine della sequenza di confronto per effettuare la conversione tra maiuscole e minu-
scole.
NLSSORT(stringa[,'NLS_SORT=ordine'])
Oracle utilizza il National Language Support SORT. Questa funzione fornisce il valore della
sequenza di confronto della stringa data nella sequenza di confronto ordine o, se quest’ultima
viene omessa, l’opzione National Language Support scelta per il sito.
REGEXP_INSTR(stringa_di_origine, modello
[,posizione,occorrenza,opzione_restituzione,parametro_di_corrispondenza])
REGEXP_REPLACE(stringa_di_origine, modello
[,stringa_di_sostituzione,posizione,occorrenza,parametro_di_corrispondenza])
REGEXP_SUBSTR(stringa_di_origine, modello
[,posizione,occorrenza,parametro_di_corrispondenza ])
REPLACE(stringa, if [,then])
GUIDA DI RIFERIMENTO ALFABETICA 1007
REPLACE restituisce la stringa dopo che ciascuna occorrenza di if è stata sostituita con then
(zero o più caratteri). Se non viene specificata alcuna stringa then, vengono rimosse tutte le
occorrenze di if. Vedere TRANSLATE.
RPAD(stringa,lunghezza [ ,'car'])
RPAD sta per Right PAD. Rende una stringa di una lunghezza specifica aggiungendo a de-
stra un determinato insieme di caratteri.
RTRIM(stringa [,'car'])
RTRIM sta per Right TRIM. Taglia tutte le occorrenze della sequenza di caratteri specificata
da car dalla parte destra di una stringa.
SOUNDEX(stringa)
SOUNDEX converte una stringa in un valore di codice. I nomi con fonema simile tendono ad
avere lo stesso valore di codice. È possibile utilizzare SOUNDEX per confrontare i nomi che
possono avere piccole differenze di pronuncia, ma sono di fatto lo stesso nome (vale per la
lingua inglese).
SUBSTR ritaglia una parte di una stringa a partire dalla posizione inizio e contando un
numero conta di caratteri a partire da inizio.
TREAT(espr AS [REF][utente.]tipo)
TRANSLATE(stringa,if,then)
Questa funzione traduce una stringa, carattere per carattere, in base a una corrispondenza di
posizione di caratteri nella stringa if con caratteri nella stringa then. Vedere REPLACE.
TRIM
( [{ { LEADING | TRAILING | BOTH } [caratteri_da_tagliare])
| caratteri_da_tagliare
} FROM ] sorgente_da_tagliare )
TRIM taglia tutte le occorrenze della sequenza di caratteri specificata da car dalla parte
destra, da quella sinistra o da entrambe le parti di una stringa.
UPPER(stringa)
USERENV(opzione)
VSIZE(stringa)
CARDINALITY
VEDERE ANCHE FUNZIONI DI RACCOLTA.
SINTASSI
CARDINALITY ( tabella_nidificata )
CASE
VEDERE ANCHE ALTRE FUNZIONI, DECODE, TRANSLATE, Capitolo 16.
SINTASSI
case_expression::=
simple_case_expression else_clause
CASE END
searched_case_expression
simple_case_expression::=
searched_case_expression::=
else_clause::=
ELSE else_expr
DESCRIZIONE CASE supporta la logica if-then-else nelle istruzioni SQL. È possibile utilizzare
le clausole WHEN/THEN per indicare al database cosa fare per ciascuna condizione. È possibile
impiegare una clausola ELSE per gestire le eccezioni alle proprie clausole WHEN.
GUIDA DI RIFERIMENTO ALFABETICA 1009
ESEMPIO
select distinct
CASE NomeCategoria
when 'NARRADULTI' then 'Narrativa adulti'
when 'SAGGIADULTI' then 'Saggi adulti'
when 'CONSADULTI' then 'Consultazione adulti'
when 'NARRRAGAZZI' then 'Narrativa ragazzi'
when 'SAGGIRAGAZZI' then 'Saggi ragazzi'
when 'ILLUSRAGAZZI' then 'Illustrati ragazzi'
else NomeCategoria
end
from BIBLIOTECA;
CAST
VEDERE ANCHE Vedere TABELLA ANNIDATA, Capitolo 34.
SINTASSI
DESCRIZIONE CAST può essere utilizzato per convertire un tipo di dato in un altro. CAST
viene utilizzato più comunemente quando si lavora con dei collettori come le tabelle annidate.
CATSEARCH
CATSEARCH viene impiegato per le ricerche di testo in indici testuali CTXCAT creati in Oracle
Text. Consultare il Capitolo 25 per esempi di creazione di indici e di ricerche di testo. Tra gli
operatori di ricerca del testo utilizzabili si segnalano i seguenti.
OPERATORE DESCRIZIONE
| Restituisce un record se almeno uno dei termini di ricerca ha un punteggio superiore alla soglia.
AND Restituisce un record se entrambi i termini di ricerca hanno un punteggio superiore alla soglia. Questa è
l’azione predefinita.
- Restituisce le righe che contengono il termine che precede l’operatore "-" e che non contengono il
termine che lo segue.
NOT Identico a -.
CEIL
VEDERE ANCHE FLOOR; NUMERI, FUNZIONI.
SINTASSI
CEIL(valore)
1010 CAPITOLO 48
CEIL(1.3) = 2
CEIL(-2.3) = -2
CONCATENATA, RIGA
Una riga concatenata è una riga che viene memorizzata in più di un blocco di database e che
pertanto è composta da più parti. Le righe lunghe (o LOB in linea), la cui lunghezza è maggiore
della dimensione di un blocco possiedono sempre vari pezzi di riga. Il comando ANALYZE può
identificare le righe in catena e fornire informazioni statistiche sul loro numero. Vedere ANALYZE.
CHANGE (SQL*Plus)
VEDERE ANCHE APPEND, DEL, EDIT, LIST, Capitolo 6.
SINTASSI
where NomeCategoria='NARRADULTI'
questa riga:
C /NARRADULTI/SAGGIADULTI
where NomeCategoria='SAGGIADULTI'
CHARTOROWID
VEDERE ANCHE CONVERSIONE, FUNZIONI; ROWIDTOCHAR.
SINTASSI
CHARTOROWID(stringa)
DESCRIZIONE CHARTOROWID sta per CHARacter TO ROW IDentifier (da carattere a identifi-
catore di riga). Essa modifica una stringa di caratteri in modo che funzioni come un identificatore
di riga interno di Oracle o ROWID.
CHIAMATA RICORSIVA
Una chiamata ricorsiva è una chiamata annidata dell’RDBMS; per esempio, le informazioni di
audit sono registrate nelle tabelle di sistema tramite chiamate ricorsive. Durante una normale
operazione di database, magari un aggiornamento, viene eseguita un’altra operazione per scrive-
re informazioni di log, di audit e altre informazioni vitali relative alle normali operazioni di
database in corso.
CHIAVE
Una chiave è una colonna (o più colonne) utilizzata per identificare delle righe; non equivale a
un indice, anche se spesso vengono utilizzati insieme. Vedere CHIAVE ESTERNA, CHIAVE
PRIMARIA e CHIAVE UNICA.
CHIAVE COMPOSTA
Si tratta di una chiave primaria o esterna composta da due o più colonne.
CHIAVE ESTERNA
Una chiave esterna è una colonna, o un insieme di colonne, i cui valori si basano su quelli delle
chiavi primarie o candidate di un’altra tabella.
CHIAVE PRIMARIA
La chiave primaria è quella colonna (ma possono essere anche più d’una) che identifica in modo
univoco ogni riga di una tabella.
CHIAVE UNICA
Una chiave unica è una colonna (o più colonne) che deve contenere valori unici per ciascuna riga
della tabella. Vedere CHIAVE, CHIAVE PRIMARIA e VINCOLI DI INTEGRITÀ.
CHR
VEDERE ANCHE ASCII; CARATTERI, FUNZIONI.
SINTASSI
CHR(intero)
1012 CAPITOLO 48
DESCRIZIONE CHR restituisce il carattere a cui corrisponde il valore ASCII di intero (intero
rappresenta un numero intero tra 0 e 255, poiché il valore ASCII di un carattere è un intero tra 0
e 255). I valori tra lo 0 e il 127 possiedono standard ben definiti. I valori superiori al 127 (chia-
mati set esteso di caratteri ASCII) tendono a differire da nazione a nazione, in relazione all’ap-
plicazione e al costruttore di computer. La lettera A, per esempio, è uguale al numero ASCII 65,
B è 66, C è 67 e così via. La virgola decimale è 46. Il segno meno è 45. Il numero 0 è 48, 1 è 49,
2 è 50 e così via.
ESEMPIO
C C C
- - -
M . 8
CICLI
È possibile utilizzare dei cicli per elaborare più record all’interno di un unico blocco PL/SQL.
Questo linguaggio supporta tre tipi di cicli:
I cicli possono elaborare record multipli a partire da un cursore. Il ciclo a cursore più comu-
ne è il ciclo FOR. Per dettagli riguardanti l’uso di cicli sia per la logica di elaborazione semplice
sia per quella basata sui cursori, si consulti CICLI FOR A CURSORE e il Capitolo 29.
declare
pi constant NUMBER(9,7) := 3.1415927;
area NUMBER(14,2);
cursore rag_cursore is
select * from VALORI_RAGGIO;
val_rag_ rag_cursore%ROWTYPE;
begin
for val_rag in rag_cursore
loop
area := pi*power(val_rag.raggio,2);
insert into AREE values (va_rag.raggio, area);
GUIDA DI RIFERIMENTO ALFABETICA 1013
end loop;
end;
CLAUSOLA
Una clausola è una delle parti principali di un’istruzione SQL che inizia con una parola del tipo
select, insert, update, delete, from, where, order by, group by o having.
CLEAR (SQL*Plus)
VEDERE ANCHE BREAK, COLUMN, COMPUTE.
SINTASSI
CL[EAR] opzione
clear computes
clear columns
CLOB
CLOB è un tipo di dato che supporta oggetti carattere di grandi dimensioni (character large
object). Vedere il Capitolo 35.
1014 CAPITOLO 48
CLOSE
VEDERE ANCHE DECLARE, FETCH, FOR, OPEN, Capitolo 29.
SINTASSI
CLOSE cursore;
DESCRIZIONE CLOSE chiude il cursore specificato e ne rilascia le risorse in modo che Oracle
le possa riutilizzare altrove; cursore dev’essere il nome di un cursore attualmente aperto.
Anche se un cursore è stato chiuso, la sua definizione non è perduta ed è possibile eseguire
nuovamente OPEN cursore, a patto che precedentemente sia stato dichiarato in modo esplicito.
Un ciclo FOR apre in modo implicito un cursore dichiarato. Vedere CICLI FOR A CURSORE.
CLUSTER
Un cluster rappresenta un mezzo per memorizzare assieme i dati provenienti da più tabelle,
quando i dati delle tabelle contengono informazioni in comune ed è probabile che si acceda ad
esse simultaneamente. È anche possibile avere un cluster con una singola tabella. Vedere CREA-
TE CLUSTER e il Capitolo 20.
CLUSTER, CHIAVE
La chiave di cluster è la colonna o le colonne che le tabelle associate a cluster hanno in comune
e che viene scelta come chiave di memorizzazione/accesso. Per esempio, le due tabelle BIBLIO-
TECA e AUTORE_BIBLIOTECA possono essere associate a cluster sulla colonna Titolo. La chia-
ve di un cluster è uguale alla colonna di un cluster.
CLUSTER HASH
Un cluster hash è un cluster memorizzato da una chiave di hash invece che da una chiave di
indice. Una chiave di hash è un valore calcolato a partire dai valori delle chiavi che rappresenta-
no la locazione su disco. Una chiave di indice richiede che Oracle cerchi la locazione nell’indice,
mentre una chiave di hash consente a Oracle di calcolare la locazione.
CLUSTER, INDICE
L’indice di un cluster viene creato manualmente dopo la creazione del cluster e prima che qual-
siasi istruzione DML (select, insert, update o delete) possa operare sul cluster. Questo indice
viene creato sulle colonne chiave del cluster tramite l’istruzione SQL CREATE INDEX. In Oracle
è possibile definire un cluster hash per indicizzare la chiave primaria. Vedere CLUSTER HASH.
CMDSEP (SQL*PLUS)
Vedere SET.
COALESCE
VEDERE ANCHE DECODE, Capitolo 16.
GUIDA DI RIFERIMENTO ALFABETICA 1015
SINTASSI
DESCRIZIONE COALESCE restituirà il primo valore non NULL incontrato nell’elenco dei
valori forniti.
COERENZA DI LETTURA
La coerenza di lettura è uno stato che garantisce che tutti i dati di un’istruzione o di una transa-
zione rimangano coerenti per tutta la durata dell’istruzione/transazione. Vedere SET
TRANSACTION.
COLONNA
Una colonna rappresenta una suddivisione di una tabella identificata da un nome e da un tipo di
dato. Per esempio, in una tabella contenente i dati dei dipendenti di una ditta, tutte le età dei
dipendenti costituiscono una colonna. Vedere RIGA.
COLONNA DI JOIN
Una colonna di join è una colonna utilizzata nell’unione di una tabella con un’altra. Una colonna
di join può essere identificata usandola in una clausola where, in una clausola using oppure in
una clausola on che specifichi la relazione tra le due tabelle.
COLONNA, VINCOLO
Un vincolo su una colonna è un vincolo integrità assegnato a una specifica colonna di una tabel-
la. Vedere VINCOLO DI INTEGRITÀ.
COLSEP (SQL*PLUS)
Vedere SET.
COLUMN (SQL*Plus)
VEDERE ANCHE ALIAS, Capitolo 6.
SINTASSI
FORMATO RISULTATO
, Visualizza una virgola.
. Visualizza un punto.
(segue)
GUIDA DI RIFERIMENTO ALFABETICA 1017
(continua)
FORMATO RISULTATO
$99999 Un segno di dollaro inserito all’inizio di ciascun numero.
9999990 Il conteggio dei nove e zeri determina le cifre massime che possono essere visualizzate.
99999MI Se il numero è negativo, un segno meno segue il numero. Per default il segno negativo è sulla sinistra.
S9999 o 9999S Restituisce “+” per i valori positivi, "–" per quelli negativi.
U999 Visualizza il simbolo di valuta dell'Euro o un altro simbolo di valuta duale nella posizione specificata.
999V99 Moltiplica il numero per 10n, dove n rappresenta il numero di cifre a destra di V. 999V99 traduce 1234 in
123400.
X Visualizza il valore esadecimale per il valore arrotondato del numero specificato di cifre.
NEW_VALUE definisce una variabile che contenga il valore della colonna da utilizzare nel
comando ttitle. Vedere il Capitolo 6 per informazioni relative all’utilizzo di questo comando.
NOPRINT e PRINT abilita o disabilita la visualizzazione della colonna.
NULL imposta il testo da visualizzare se la colonna possiede un valore NULL. L’impostazione
predefinita per questa opzione è una stringa di spazi di larghezza pari a quella della colonna.
OFF o ON abilita o disabilita tutte queste opzioni per una colonna, senza influenzarne i
contenuti.
OLD_VALUE definisce una variabile che contenga il valore della colonna da utilizzare nel
comando btitle. Vedere il Capitolo 13 per informazioni relative all’utilizzo di questo comando.
WRAPPED, WORD_WRAPPED e TRUNCATED controllano il modo in cui SQL*PLUS
visualizza un’intestazione o il valore di una stringa troppo ampio per essere contenuto nella
colonna. WRAP prosegue la scrittura del valore alla riga successiva. WORD_WRAP esegue un’ope-
razione simile, ma fa cadere l’interruzione sulle parole. TRUNCATED tronca il valore all’am-
piezza della definizione della colonna.
COMMENT
VEDERE ANCHE VISTE DEL DIZIONARIO DI DATI, Capitolo 42.
SINTASSI
COMMENT ON
{ TABLE [schema .] { tabella | vista | vista materializzata }
| COLUMN [schema .] {tabella. | vista . | vista materializzata . } colonna
| OPERATOR [schema .] operatore
| INDEXTYPE [schema .] tipoindice
}
IS 'testo';
COMMIT
L’espressione “effettuare il commit” significa apportare modifiche ai dati (tramite insert, update
e delete) in modo permanente. Prima che le modifiche vengano memorizzate, esistono sia i
vecchi che i nuovi dati, perciò è possibile rendere effettive le modifiche oppure ripristinare i dati
originari (rollback dei dati). Quando un utente inserisce il comando COMMIT di Oracle SQL,
tutte le modifiche provenienti da quella transazione vengono rese permanenti.
DESCRIZIONE COMMIT rende effettive le modifiche apportate al database dal momento in cui
è stato eseguito l’ultimo COMMIT, sia implicito che esplicito. WORK è facoltativo e non ha
effetti sull’utilizzo.
COMMENT associa alla transazione un testo di commento che può essere visualizzato trami-
te la vista del dizionario di dati DBA_2PC_PENDING nel caso in cui una transazione distribuita
non possa essere completata. FORCE effettua il commit manuale di una transazione distribuita
sconosciuta.
COMPOSE
VEDERE ANCHE CONVERSIONE, FUNZIONI; Capitolo 10.
SINTASSI
COMPOSE(stringa)
DESCRIZIONE COMPOSE prende come argomento una stringa in qualunque tipo di dato e
restituisce una stringa UNICODE nella sua forma completamente normalizzata utilizzando il
medesimo set di caratteri della stringa di input.
ESEMPIO
Per visualizzare una “o” con la dieresi:
1020 CAPITOLO 48
C
-
ö
COMPUTE (SQL*Plus)
VEDERE ANCHE BREAK, FUNZIONI DI GRUPPO.
SINTASSI
COMP[UTE][AVG|COU[NT]|MAX[IMUM]|MIN[IMUM]|NUM[BER]|STD|SUM|VAR[IANCE]]...
[funzione LABEL nome_etichetta
OF {espressione | colonna | alias} ...
ON [espressione | colonna | alias | REPORT | ROW}...]
I calcoli successivi vengono semplicemente elencati in ordine senza virgole, come nel caso
seguente:
GUIDA DI RIFERIMENTO ALFABETICA 1021
Questa istruzione calcola la somma, la media e il valore massimo sia di Importo che Aliquota
per l’intero report.
ESEMPIO
Per eseguire il calcolo per ogni classificazione di Elemento e per l’intero report, si può scrivere:
CONCAT
Vedere SET, ||.
CONDIZIONE
Una condizione è un’espressione il cui valore viene valutato TRUE o FALSE, come in Eta > 65.
DESCRIZIONE Per utilizzare questo comando occorre trovarsi in SQL*PLUS, anche se non è
necessario essere collegati a Oracle (vedere DISCONNECT). CONNECT effettua il commit di
qualsiasi modifica pendente, esegue la disconnessione da Oracle e ricollega l’utente con il nome
specificato tramite utente. Se viene omessa la password, il sistema richiede di introdurla. La
password introdotta in risposta al prompt di richiesta non viene visualizzata.
@identificatore_connessione collega al database specificato, che può trovarsi sul proprio
host, oppure su un altro computer connesso tramite Oracle Net.
AT viene utilizzato per specificare un database diverso da quello predefinito attivo per l’utente
in questione. Si tratta di una clausola richiesta per raggiungere qualunque database diverso da
quello predefinito per l’utente. Questo nome può essere utilizzato successivamente in altre istru-
zioni SQL con AT. Questo database dev’essere prima identificato con DECLARE DATABASE.
USING specifica una stringa di Oracle Net opzionale (quale il nome di un servizio) utilizzata
durante l’operazione di connessione. Senza la stringa USING, la connessione avviene con il
database predefinito dell’utente, a prescindere dal database specificato alla riga AT.
CONNECT BY
VEDERE ANCHE Capitolo 14.
SINTASSI
CONTAINS
CONTAINS serve per valutare le ricerche di testo che usano gli indici CONTEXT all’interno di
Oracle Text. Si consulti il Capitolo 24. Nella tabella seguente sono elencati gli operatori supportati
delle ricerche di testo per CONTAINS.
GUIDA DI RIFERIMENTO ALFABETICA 1023
OPERATORE DESCRIZIONE
OR Restituisce un record se almeno uno dei termini di ricerca ha un punteggio superiore alla soglia.
| Identico a OR.
AND Restituisce un record se entrambi i termini di ricerca hanno un punteggio superiore alla soglia.
ACCUM Restituisce un record se la somma dei punteggi dei termini di ricerca supera la soglia.
, Identico a ACCUM.
MINUS Restituisce un record se la differenza di punteggio fra il primo e il secondo termine di ricerca supera la
soglia.
- Identico a MINUS.
NEAR Il punteggio si baserà sulla vicinanza reciproca dei termini di ricerca nel testo esaminato.
; Identico a NEAR.
? Effettua una corrispondenza non esatta (che trova anche gli errori di digitazione) del termine di ricerca
prima di effettuare la ricerca vera e propria.
CONTEXT, INDICE
Oracle Text supporta tre tipi di indici testuali; gli indici CONTEXT, gli indici CTXCAT e infine
gli indici CTXRULE. Gli indici CONTEXT usano l’operatore CONTAINS e supportano una
gamma più ampia di capacità per le ricerche di testo. Gli indici CTXCAT supportano una serie
più limitata di operatori di ricerca ma supportano la creazione di gruppi di indici. Gli indici
CTXRULE sono indici su colonne che contengono un gruppo di query di testo. Per ulteriori
informazioni si consulti il Capitolo 25.
CONVERSIONE, FUNZIONI
VEDERE ANCHE CARATTERI, FUNZIONI; NUMERI, FUNZIONI; Capitolo 10.
DESCRIZIONE Di seguito è riportato un elenco in ordine alfabetico di tutte le funzioni di
conversione e trasformazione attualmente disponibili in SQL di Oracle.
CAST Effettua una conversione CAST di un tipo incorporato o collection in un altro; utilizzato comunemente
con tabelle annidate e array variabili.
CHARTOROWID Abbreviazione di CHARacter TO ROW IDentifier. Modifica una stringa di caratteri in modo che funzioni
come un identificatore di riga interno di Oracle o RowID.
COMPOSE Traduce una stringa in qualunque tipo di dati in una stringa UNICODE nella sua forma completamente
normalizzata utilizzando il medesimo set di caratteri della stringa di input.
CONVERT Converte una stringa di caratteri dal set di caratteri di una lingua in un altro.
DECODE Decodifica una stringa di caratteri CHAR o VARCHAR2 o un numero (NUMBER) in una serie di vari
numeri, in base a un valore. Si tratta di una funzione di tipo if, then, else molto potente. A essa è dedicato
il Capitolo 17.
DECOMPOSE Traduce una stringa in qualunque tipo di dati in una stringa UNICODE dopo la sua scomposizione canonica
utilizzando il medesimo set di caratteri della stringa di input.
HEXTORAW Abbreviazione di HEXadecimal TO RAW. Modifica una stringa di caratteri di numeri esadecimali in binario.
RAWTOHEX Abbreviazione di RAW TO HEXadecimal. Modifica una stringa di numeri binari in una stringa di caratteri
di numeri esadecimali.
RAWTONHEX RAW TO NHEX. Converte un dato RAW in un valore NVARCHAR2 contenente l’equivalente esadecimale.
ROWIDTOCHAR ROW Identifier TO CHARacter. Modifica un identificatore di riga interno di Oracle, o RowID, in una stringa
di caratteri.
(segue)
GUIDA DI RIFERIMENTO ALFABETICA 1025
(continua)
TO_CLOB TO CLOB. Converte i valori NCLOB in una colonna LOB o in altre stringhe di caratteri in valori CLOB.
TO_DATE TO DATE. Converte un elemento di tipo NUMBER, CHAR o VARCHAR2 in un elemento di tipo DATE (un
tipo di dati di Oracle).
TO_DSINTERVAL Converte una stringa di tipo di dati CHAR, VARCHAR2, NCHAR o NVARCHAR2 in un tipo INTERVAL DAY
TO SECOND.
TO_LOB TO LOB. Converte un valore LONG in un LOB come parte di un’istruzione insert as select.
TO_MULTI_BYTE TO MULTI_BYTE. Converte i caratteri a singolo byte di una stringa di caratteri in caratteri di più byte.
TO_NCHAR TO NCHAR. Converte una stringa di caratteri, i numeri o le date dal set di caratteri del database in quello
della lingua nazionale.
TO_NCLOB TO NCLOB. Converte i valori CLOB in una colonna LOB o in altre stringhe di caratteri in valori NCLOB.
TO_SINGLE_BYTE TO SINGLE BYTE. Converte i caratteri a più byte di un CHAR o un VARCHAR2 in byte singoli.
TO_TIMESTAMP_TZ Converte una stringa di caratteri in un valore del tipo TIMESTAMP WITH TIME ZONE.
TO_YMINTERVAL Converte una stringa di tipo di dati CHAR, VARCHAR2, NCHAR o NVARCHAR2 in un tipo INTERVAL
YEAR TO MONTH .
UNISTR Converte una stringa Unicode nel set di caratteri Unicode del database.
CONVERT
VEDERE ANCHE CONVERSIONE, FUNZIONI.
SINTASSI
CONVERT(stringa,[set_destinazione,[set_sorgente]])
COPY (SQL*Plus)
NOTA Il comando COPY di SQL*Plus non è stato potenziato per gestire tipi di
dati o caratteristiche introdotte con o dopo Oracle8i. È probabile che nelle versioni future verrà
considerato obsoleto.
DESCRIZIONE COPY copia da una tabella in un’altra tabella che risiede su un computer diffe-
rente, tramite Oracle Net. FROM specifica il nome utente, la password e il database della tabella
di origine, mentre TO rappresenta la tabella di destinazione. Sia FROM che TO possono essere
omessi, nel qual caso al posto della clausola mancante viene utilizzato il database predefinito
dell’utente. Il database di origine e quello di destinazione non devono coincidere, perciò può
essere omessa solo una delle clausole from e to.
APPEND aggiunge dati alla tabella di destinazione; se la tabella non esiste, viene creata.
CREATE chiede di creare la tabella di destinazione; se questa esiste già, compare il messaggio
d’errore ‘table already exists’, per informare l’utente che la tabella esiste già. INSERT inserisce
dati nella tabella di destinazione; se la tabella non esiste compare il messaggio d’errore ‘table
does not exist’, per informare l’utente che la tabella non esiste. REPLACE cancella i dati all’in-
terno della tabella di destinazione e li sostituisce con i dati provenienti dalla tabella di origine; se
la tabella non esiste, viene creata.
tabella è il nome della tabella di destinazione. colonna rappresenta il nome o i nomi delle
colonne all’interno della tabella di destinazione. Se specificato, il numero delle colonne dev’es-
sere uguale a quello delle colonne nella query. Se non viene specificata alcuna colonna, alle
colonne copiate nella tabella di destinazione vengono assegnati gli stessi nomi delle colonne
contenute nella tabella di origine. query identifica la tabella di origine e stabilisce quali righe e
colonne copiare da quest’ultima.
SET LONG (vedere SET) determina la lunghezza di un campo LONG che può essere copia-
to. Le colonne lunghe con dati di lunghezza maggiore rispetto al valore di LONG vengono tron-
GUIDA DI RIFERIMENTO ALFABETICA 1027
cate. SET COPYCOMMIT determina quanti gruppi di righe copiare prima di effettuare un commit.
SET ARRAYSIZE stabilisce quante righe possono essere contenute in un gruppo.
ESEMPIO
Questo esempio copia BIBLIOTECA_PRESTITO dal database EDMESTON al database
cui l’utente SQL*PLUS locale è connesso. La tabella PRESTITO_LOCALE viene creata dalla
copia. Una volta giunte a destinazione le colonne possono essere rinominate. Si osservi l’uso del
trattino (-) alla fine di ogni linea. Questo trattino è richiesto. Il comando non termina con un
punto e virgola (poiché si tratta di un comando SQL*Plus, e non di un comando SQL). Per le
opzioni relative al comando COPY si consulti il comando SET.
COPYCOMMIT (SQL*Plus)
Vedere SET e COPY.
COPYTYPECHECK (SQL*Plus)
Vedere SET e COPY.
CORR
VEDERE ANCHE FUNZIONI DI AGGREGAZIONE.
SINTASSI
CORR
VEDERE ANCHE CORR_K e CORR_S.
SINTASSI
CORR
VEDERE ANCHE CORR.
SINTASSI
{CORR_K | CORR_S }
(espr1, espr2 [, { COEFFICIENT |ONE_SIDED_SIG|TWO_SIDED_SIG}])
COS
VEDERE ANCHE ACOS, ASIN, ATAN, ATAN2, COSH, EXP, LN, LOG, SIN, SINH, TAN,
TANH.
SINTASSI
COS(valore)
DESCRIZIONE COS restituisce il coseno di un valore, un angolo espresso in radianti. Per conver-
tire in radianti la misura di un angolo espressa in gradi occorre moltiplicarla per pi/180.
COSH
VEDERE ANCHE ACOS, ASIN, ATAN, ATAN2, COS, EXP, LN, LOG, SIN, SINH, TAN, TANH.
SINTASSI
COSH(valore)
COUNT
VEDERE ANCHE FUNZIONI DI GRUPPO, Capitolo 9, Capitolo 12.
GUIDA DI RIFERIMENTO ALFABETICA 1029
SINTASSI
DESCRIZIONE COUNT conta il numero di righe in cui espressione non è NULL, che vengono
poi restituite da una query. L’opzione DISTINCT fa in modo che vengano contate solo le righe
non NULL distinte. Con il simbolo *, vengono contate tutte le righe, sia NULL che non NULL.
COVAR_POP
VEDERE ANCHE FUNZIONI DI AGGREGAZIONE.
SINTASSI
COVAR_SAMP
VEDERE ANCHE FUNZIONI DI AGGREGAZIONE.
SINTASSI
CREATE CLUSTER
VEDERE ANCHE CREATE INDEX, CREATE TABLE, Capitolo 17.
SINTASSI
1030 CAPITOLO 48
create_cluster::=
schema . SORT
CREATE CLUSTER cluster ( column datatype )
physical_attributes_clause
SIZE size_clause
TABLESPACE tablespace
INDEX
N0ROWDEPENDENCIES CACHE
physical_attributes_clause::=
PCTFREE integer
PCTUSED integer
INITRANS integer
storage_clause
size_clause::=
T
integer
parallel_clause::=
NOPARALLEL
integer
PARALLEL
GUIDA DI RIFERIMENTO ALFABETICA 1031
DESCRIZIONE CREATE CLUSTER crea un cluster per una o più tabelle. Le tabelle vengono
aggiunte al cluster tramite CREATE TABLE con la clausola cluster. CREATE CLUSTER richiede
almeno una colonna cluster da ciascuna delle tabelle. Queste devono avere la stessa dimensione
ed essere dello stesso tipo di dati, ma non è richiesto che siano omonime. Per le tabelle di un
cluster, le righe con gli stessi valori della colonna cluster vengono riunite insieme nella stessa
area del disco, nello stesso blocco o negli stessi blocchi logici. In questo modo, le prestazioni
possono migliorare quando le colonne cluster sono le colonne attraverso cui le tabelle vengono
solitamente unite.
Ogni valore distinto in ogni colonna cluster viene memorizzato solo una volta, indipenden-
temente dal fatto che ricorra più volte nelle tabelle e nelle righe. Solitamente, in questo modo si
riduce la quantità di spazio su disco necessaria per memorizzare le tabelle, ma ciascuna tabella
continua ad apparire come se contenesse tutti i suoi dati. Le tabelle con colonne di tipo LONG
non possono essere raggruppate in cluster.
cluster è il nome assegnato al cluster. colonna e tipodato seguono il metodo di CREATE
TABLE, con l’unica eccezione dell’impossibilità di specificare NULL e NOT NULL. Tuttavia nel-
l’istruzione CREATE TABLE vera e propria almeno una colonna di un cluster dev’essere NOT
NULL. SIZE imposta la dimensione in byte di un blocco logico (diverso dal blocco fisico). SPACE
rappresenta l’allocazione iniziale su disco del cluster, come viene utilizzata in CREATE TABLE.
SIZE dovrebbe essere la quantità media di spazio necessaria per memorizzare tutte le righe
da tutte le tabelle contenute in cluster che risultano associate a un’unica chiave di clusterizzazione.
Un valore di SIZE piccolo può far lievitare il tempo necessario per accedere alle tabelle nel
cluster, ma può ridurre l’uso di spazio su disco. SIZE dovrebbe essere un divisore adeguato della
dimensione di un blocco fisico. In caso contrario, Oracle utilizza il divisore successivo di valore
maggiore. Se SIZE supera la dimensione di un blocco fisico, Oracle utilizza al suo posto la
dimensione di un blocco fisico.
Per default, il cluster è indicizzato ed è necessario creare un indice sulla chiave di
clusterizzazione prima di inserire i dati nel cluster. Se si specifica la forma di cluster hash,
tuttavia, non è necessario (e non è nemmeno possibile) creare un indice sulla chiave di clusteriz-
zazione. Al contrario, Oracle utilizza una funzione di hash per memorizzare le righe della tabella.
È possibile creare il proprio valore di hash come una colonna della tabella e utilizzarlo con
la clausola HASH IS per dire a Oracle di utilizzare questa colonna come valore di hash. In caso
contrario, Oracle utilizza una funzione di hash interna che si basa sulle colonne della chiave di
clusterizzazione. La clausola HASHKEYS in realtà crea il cluster hash e specifica il numero di
valori hash, arrotondati al numero primo più vicino. Il valore minimo è 2.
Per i dettagli sui parametri comuni della clausola di memorizzazione si consulti la voce
STORAGE.
CREATE CONTEXT
VEDERE ANCHE ALTER CONTEXT.
SINTASSI
CREATE CONTROLFILE
VEDERE ANCHE ALTER DATABASE, CREATE DATABASE.
SINTASSI
create_controlfile::=
REUSE SET
CREATE CONTROLFILE DATABASE database
NORESETL0GS
MAXLOGFILES integer
MAXLOGMEMBERS integer
MAXLOGHISTORY integer
MAXDATAFILES integer
MAXINSTANCES integer
ARCHIVELOG
NOARCHIVELOG
logfile_clause::=
GROUP integer
LOGFILE file_specification
character_set_clause::=
DESCRIZIONE Il comando CREATE CONTROLFILE ricrea un control file nel caso in cui l’utente
abbia perso il proprio control file corrente a causa di un inconveniente tecnico, oppure nel caso
si desideri modificare il nome del database o una delle opzioni per il file di log di un file di dati.
In generale, questo comando dovrebbe essere utilizzato solo da amministratori di database esperti.
GUIDA DI RIFERIMENTO ALFABETICA 1033
CREATE DATABASE
VEDERE ANCHE ALTER DATABASE, CREATE CONTROLFILE, CREATE ROLLBACK
SEGMENT, CREATE TABLESPACE, SHUTDOWN, STARTUP, Capitoli 2 e 46.
SINTASSI
create_database::=
CONTROLFILE REUSE
MAXDATAFILES integer
MAXINSTANCES integer
BIGFILE
SET DEFAULT TABLESPACE
SMALLFILE
database_logging_clauses
tablespace_clauses
set_time_zone_clause
1034 CAPITOLO 48
database_logging_clauses::=
GROUP integer
LOGFILE file_specification
MAXLOGFILES integer
MAXLOGMEMBERS integer
MAXLOGHISTORY integer
ARCHIVELOG
NOARCHIVELOG
FORCE LOGGING
tablespace_clauses::=
DATAFILE file_specification
default_tablespace
default_temp_tablespace
undo_tablespace
default_tablespace::=
DATAFILE datafile_tempfile_spec
DEFAULT TABLESPACE tablespace extent_management_clause
default_temp_tablespace::=
BIGFILE
SMALLFILE
DEFAULT TEMPORARY TABLESPACE tablespace
TEMPFILE file_specification
extent_management_clause
GUIDA DI RIFERIMENTO ALFABETICA 1035
extent_management_clause::=
DICTIONARY
AUTOALLOCATE
EXTENT MANAGEMENT
SIZE size_clause
UNIFORM
LOCAL
size_clause::=
T
integer
undo_tablespace::=
BIGFILE ,
set_time_zone_clause::=
+
hh : mi
–
SET TIME_ZONE = ’ ’
time_zone_region
DESCRIZIONE database è il nome del database, e deve avere una lunghezza pari o inferiore a
otto caratteri. DB_NAME in init.ora contiene il nome di database predefinito. In generale, que-
sto comando dovrebbe essere utilizzato solo da amministratori di database esperti.
definizione_file specifica i nomi e le dimensioni dei file di dati e dei file di log:
SIZE rappresenta il numero di byte riservati per questo file. Il suffisso K moltiplica il valore
specificato per 1024; M moltiplica il valore per 1048576. REUSE (senza SIZE) provoca la di-
1036 CAPITOLO 48
struzione dei contenuti di qualsiasi file con quel nome e associa il nome al database in questione.
SIZE con REUSE crea il file nel caso non esista ancora, altrimenti ne controlla la dimensione.
CONTROLFILE REUSE sovrascrive i control file già esistenti definiti dal parametro CONTROL_
FILES nel file dei parametri di inizializzaione.
LOGFILE assegna il nome dei file da utilizzare come redo log file. Se questo parametro non
viene utilizzato, per default Oracle ne crea due. MAXLOGFILES sostituisce il parametro di
inizializzazione LOG_FILES e definisce il numero massimo di redo log file che possono essere
creati per il database. Questo numero non potrà essere aumentato in futuro se non quando si
ricreerà il control file. Il valore minimo è 2. Un numero maggiore crea semplicemente un control
file più grande.
DATAFILE specifica i nomi dei file che il database stesso utilizzerà. MAXDATAFILES impo-
sta il limite superiore assoluto per i file che possono essere creati per questo database e sostitui-
sce il parametro di inizializzazione DB_FILES. Un numero maggiore crea semplicemente un
control file più grande.
A partire da Oracle Database 10g è possibile specificare file di ASM così come file del file
system.
Quando l’opzione AUTOEXTEND viene abilitata (ON) per un file di dati, il file di dati si
estenderà dinamicamente in base alle necessità con incrementi di dimensione pari a NEXT, fino
a un valore massimo pari a MAXSIZE (o UNLIMITED, illimitato).
MAXINSTANCES sostituisce il parametro INSTANCES in init.ora e imposta il numero mas-
simo di istanze simultanee che possono eseguire il MOUNT del database e aprire il database.
ARCHIVELOG e NOARCHIVELOG definiscono il modo in cui i redo log file vengono utiliz-
zati quando il database viene creato per la prima volta. NOARCHIVELOG è l’impostazione
predefinita e significa che i file di redo vengono riutilizzati senza salvarne il contenuto altrove.
In questo modo, viene garantito il recupero dell’istanza, ma non il recupero dei dati a fronte di
un malfunzionamento del sistema, quale un crash del disco. ARCHIVELOG impone l’archiviazione
dei file di redo (solitamente su un altro disco o nastro), in modo che sia possibile effettuare il
ripristino dei dati a fronte di un malfunzionamento del sistema. Questa modalità gestisce anche
il ripristino dell’istanza. Questo parametro può essere reimpostato tramite il comando ALTER
DATABASE.
L’opzione MAXLOGMEMBERS specifica il numero massimo di copie di un gruppo di redo
log file. L’opzione MAXLOGHISTORY specifica il numero massimo di redo log file archiviati,
utile solo per Real Application Cluster quando si archiviano i file di log. L’opzione CHARACTER
SET specifica l’insieme di caratteri utilizzato per memorizzare i dati, che dipende dal sistema
operativo.
Per una gestione maggiormente automatizzata dei segmenti (di rollback) di undo è possibile
specificare la clausola UNDO TABLESPACE per allocare una tablespace appositamente per con-
tenere i dati degli undo. Il database dev’essere avviato nella modalità Automatic Undo Manage-
ment (AUM).
La clausola DEFAULT TEMPORARY TABLESPACE può essere utilizzata per designare una
tablespace non SYSTEM come tablespace temporanea predefinita per tutti i nuovi utenti creati
nel database.
A partire da Oracle Database 10g è possibile utilizzare il comando CREATE DATABASE per
fare quanto segue:
■ Creare una tablespace permanente predefinita per il database.
■ Specificare dei file di dati per la tablespace SYSAUX.
■ Specificare una tablespace grande come predefinita per il database.
■ Ignorare l’opzione predefinita per la tablespace di undo e quella temporanea predefinita.
GUIDA DI RIFERIMENTO ALFABETICA 1037
A questo punto, si può eseguire una query sulle tabelle di Pratica, come mostrato di seguito:
Inoltre, si potrebbe creare un sinonimo per celare il fatto che le tabelle sono remote:
CREATE DIMENSION
VEDERE ANCHE ALTER DIMENSION, DROP DIMENSION, Capitolo 24.
SINTASSI
create_dimension::=
hierarchy_clause
schema .
CREATE DIMENSION dimension level_clause attribute_clause ;
extended_attribute_clause
level_clause::=
level_table . level_column
LEVEL level IS ,
( level_table . level_column )
hierarchy_clause::=
dimension_join_clause
HIERARCHY hierarchy ( child_level CHILD OF parent_level )
dimension_join_clause::=
child_key_column
( child_key_column )
attribute_clause::=
dependent_column
( dependent_column )
GUIDA DI RIFERIMENTO ALFABETICA 1039
extended_attribute_clause::=
dependent_column
( dependent_column )
DESCRIZIONE CREATE DIMENSION crea delle gerarchie tra le colonne correlate nelle tabelle
in modo che possano essere utilizzate dall’ottimizzatore. L’ottimizzatore usa i valori della di-
mensione quando stabilisce se una vista materializzata restituisce o meno gli stessi dati della sua
tabella base. Per creare una dimensione, è necessario disporre del privilegio CREATE DIMEN-
SION; per creare una dimensione nello schema di un altro utente si deve possedere il privilegio
CREATE ANY DIMENSION.
LEVEL definisce il livello all’interno della dimensione. HIERARCHY definisce le relazioni
tra i livelli. ATTRIBUTE assegna attributi specifici ai livelli all’interno della dimensione. JOIN_KEY
definisce le clausole di join tra i livelli.
ESEMPI
Si consideri una dimensione geografica. I continenti sono divisi in paesi, pertanto esiste una
gerarchia tra i dati dei paesi e quelli di un continente. Per una tabella di nome PAESE con
colonne Paese e Continente e per una seconda tabella denominata CONTINENTE con una co-
lonna Continente:
CREATE DIRECTORY
VEDERE ANCHE BFILE, Capitoli 22, 26 e 35.
SINTASSI
DESCRIZIONE In Oracle, una “directory” rappresenta un alias di una directory del sistema
operativo. Prima di accedere ai valori del tipo di dati BFILE, è necessario creare una directory.
Per dettagli sulla creazione e la gestione delle tabelle esterne, si rimanda al Capitolo 26.
1040 CAPITOLO 48
CREATE DISKGROUP
VEDERE ANCHE ALTER DISKGROUP, DROP DISKGROUP, Capitolo 46
SINTASSI
create_diskgroup::=
HIGH
NORMAL REDUNDANCY
EXTERNAL
CREATE DISKGROUP diskgroup_name
,
FAILGROUP failgroup_name
DISK qualified_disk_clause ;
qualified_disk_clause::=
FORCE
size_clause::=
T
integer
DESCRIZIONE CREATE DISKGROUP crea una collezione di dischi. Oracle gestisce un gruppo
di dischi come unità logica e divide ogni file tra i dischi per bilanciare l’attività di I/O. Oracle
distribuisce automaticamente i file del database tra i dischi disponibili nei gruppi di dischi e
ribilancia lo spazio di memorizzazione quando la configurazione di memorizzazione cambia.
CREATE DISKGROUP crea un gruppo di dischi, vi assegna dei dischi ed effettua il MOUNT
del gruppo di dischi per la prima volta.
GUIDA DI RIFERIMENTO ALFABETICA 1041
CREATE FUNCTION
VEDERE ANCHE ALTER FUNCTION; BLOCCO, STRUTTURA; CREATE LIBRARY; CRE-
ATE PACKAGE; CREATE PROCEDURE; DATI, TIPI; DROP FUNCTION; Capitolo 31.
SINTASSI
create_function::=
OR REPLACE schema .
CREATE FUNCTION function
IN
OUT
IN OUT NOCOPY
( argument datatype )
RETURN datatype
invoker_rights_clause
AS call_spec
invoker_rights_clause::=
CURRENT_USER
AUTHID
DEFINER
parallel_enable_clause::=
PARALLEL_ENABLE
ANY
streaming_clause
( PARTITION argument BY , )
HASH
( column )
RANGE
streaming_clause::=
,
ORDER
BY ( column )
CLUSTER
1042 CAPITOLO 48
call_spec::=
Java_declaration
LANGUAGE
C_declaration
Java_declaration::=
C_declaration::=
DESCRIZIONE funzione è il nome della funzione da definire. Una funzione può avere parame-
tri, argomenti di un certo tipo di dati cui è stato assegnato un nome, e ciascuna funzione restitu-
isce un valore di un certo tipo di dati come specificato dalla clausola RETURN. Il blocco PL/
SQL definisce il comportamento della funzione come una serie di dichiarazioni, istruzioni di
programma PL/SQL ed eccezioni.
Il qualificatore IN richiede di specificare un valore per il parametro nel momento in cui la
funzione viene chiamata, ma poiché questa specifica va sempre fatta per le funzioni, la sintassi è
facoltativa. In una procedura si possono avere altri tipi di parametri. La differenza tra una funzio-
ne e una procedura è che una funzione restituisce un valore all’ambiente chiamante.
Per creare una funzione, è necessario disporre del privilegio di sistema CREATE PROCE-
DURE. Per creare una funzione nell’account di un altro utente, occorre possedere il privilegio di
sistema CREATE ANY PROCEDURE.
La funzione può servirsi delle librerie C memorizzate al di fuori del database (si consulti
CREATE LIBRARY). Se all’interno della funzione si usa Java, è possibile fornire una dichiara-
zione Java all’interno della clausola LANGUAGE. La clausola diritti_chiamante consente di spe-
cificare se la funzione viene eseguita con i privilegi del proprietario della funzione stessa oppure
con i privilegi dell’utente corrente (l’utente chiamante).
CREATE INDEX
VEDERE ANCHE ANALYZE, ALTER INDEX, DROP INDEX, VINCOLO DI INTEGRITÀ,
STORAGE, Capitoli 17 e 43.
SINTASSI
GUIDA DI RIFERIMENTO ALFABETICA 1043
create_index::=
UNIQUE
cluster_index_clause
BITMAP schema .
CREATE INDEX index ON table_index_clause ;
bitmap_join_index_clause
cluster_index_clause::=
subpartition_by_list
PARTITION BY RANGE ( column_list )
subpartition_by_hash
partition
( PARTITION range_values_clause table_partition_description )
table_index_clause::=
schema . t_alias
table
ASC
DESC index_properties
( index_expr )
bitmap_join_index_clause::=
schema .
table . ASC
schema . t_alias
FROM table
local_partitioned_index
WHERE condition index_attributes
1044 CAPITOLO 48
index_expr::=
column
column_expression
index_properties::=
global_partitioned_index
local_partitioned_index
index_attributes
domain_index_clause
index_attributes::=
physical_attributes_clause
logging_clause
ONLINE
COMPUTE STATISTICS
tablespace
TABLESPACE
DEFAULT
key_compression
SORT
NOSORT
REVERSE
parallel_clause
physical_attributes_clause::=
PCTFREE integer
PCTUSED integer
INITRANS integer
storage_clause
GUIDA DI RIFERIMENTO ALFABETICA 1045
logging_clause::=
LOGGING
NOLOGGING
key_compression::=
integer
COMPRESS
NOCOMPRESS
domain_index_clause::=
INDEXTYPE IS indextype
global_partitioned_index::=
individual_hash_partitions::=
partition partitioning_storage_clause
( PARTITION )
partitioning_storage_clause::=
TABLESPACE tablespace
TABLESPACE tablespace
OVERFLOW
( TABLESPACE tablespace )
LOB_segname
LOB ( LOB_item ) STORE AS
( TABLESPACE tablespace )
hash_partitions_by_quantity::=
STORE IN ( tablespace )
PARTITIONS hash_partition_quantity
index_partitioning_clause::=
,
individual_hash_partitions
PARTITION BY HASH ( column )
hash_partitions_by_quantity
local_partitioned_index::=
on_range_partitioned_table
on_list_partitioned_table
on_hash_partitioned_table
on_comp_partitioned_table
LOCAL
on_range_partitioned_table::=
segment_attributes_clause
key_compression
partition
( PARTITION )
on_list_partitioned_table::=
segment_attributes_clause
key_compression
partition
( PARTITION )
GUIDA DI RIFERIMENTO ALFABETICA 1047
segment_attributes_clause::=
physical_attributes_clause
TABLESPACE tablespace
logging_clause
on_hash_partitioned_table::=
STORE IN ( tablespace )
TABLESPACE tablespace
partition
( PARTITION )
on_comp_partitioned_table::=
STORE IN ( tablespace )
segment_attribute_clause
key_compression index_subpartition_clause
partition
( PARTITION )
index_subpartition_clause::=
STORE IN ( tablespace )
TABLESPACE tablespace
subpartition
( SUBPARTITION )
1048 CAPITOLO 48
parallel_clause::=
NOPARALLEL
integer
PARALLEL
DESCRIZIONE indice è il nome assegnato a questo indice. Solitamente è buona norma fare in
modo che rispecchi i nomi delle colonne e della tabella da indicizzare. tabella e colonna(e)
rappresentano la tabella e le colonne su cui creare l’indice. Un indice UNIQUE garantisce che
ciascuna riga indicizzata sia unica per quanto riguarda i valori delle colonne dell’indice. Per
creare automaticamente indici unici, si può utilizzare il vincolo unico sulle colonne. Se si speci-
ficano più colonne viene creato un indice composto. ASC e DESC significano rispettivamente
crescente e decrescente; gli indici decrescenti sono supportati a partire da Oracle8i. CLUSTER è
il nome della chiave di clusterizzazione che risulta indicizzata per un cluster. Le chiavi dei cluster
devono essere indicizzate per consentire l’accesso alle tabelle loro associate (vedere CREATE
TABLE per una descrizione di INITRANS e MAXTRANS). Il valore predefinito di INITRANS
per gli indici è 2; MAXTRANS è 255. PCTFREE rappresenta la percentuale di spazio da lasciare
libera nell’indice per i nuovi inserimenti e aggiornamenti. Il valore minimo è zero.
TABLESPACE è il nome della tablespace cui viene assegnato questo indice. La sezione degli
attributi fisici contiene sottoclausole descritte in STORAGE. NOSORT è un’opzione il cui valore
primario consiste nel ridurre il tempo di creazione di un indice, solo ed esclusivamente nel caso
in cui i valori nella colonna da indicizzare siano già in ordine crescente. Non viene compromes-
so nulla se in seguito l’ordine crescente decade, tuttavia NOSORT funziona solo se questi valori
sono in ordine quando viene creato l’indice. Se le righe non sono in ordine, CREATE INDEX
restituisce un messaggio d’errore; non viene danneggiato nulla, ma viene consentito di eseguire
di nuovo il comando senza l’opzione NOSORT.
PARALLEL, insieme a DEGREE e INSTANCES, specifica le caratteristiche parallele del-
l’indice. DEGREE specifica il numero dei server di query da utilizzare per creare l’indice; INSTANCES
specifica in che modo l’indice dovrà essere suddiviso tra le istanze di Real Application Clusters
per l’elaborazione in parallelo delle query. Un intero n specifica che l’indice deve essere suddi-
viso tra il numero specificato di istanze disponibili.
Per creare un indice, è necessario essere il proprietario della tabella indicizzata, disporre del
privilegio INDEX sulla tabella oppure del privilegio di sistema CREATE ANY INDEX. Per creare
un indice basato sulle funzioni, occorre possedere il privilegio QUERY REWRITE.
BITMAP crea un indice bitmap, che può essere utile per colonne con pochi valori distinti. Le
clausole PARTITION creano indici sulle tabelle partizionate. Gli indici di join delle bitmap pos-
sono memorizzare valori chiave di bitmap per più tabelle in un singolo indice (in genere per le
applicazioni di data warehouse). Gli indici di join dell bitmap utilizzano le clausole FROM e
WHERE per specificare le tabelle coinvolte e le condizoni di join
REVERSE memorizza i byte del valore indicizzato in ordine inverso. Non è possibile inver-
tire un indice bitmap.
COMPRESS risparmia spazio di memorizzazione comprimendo indici non partizionati non
unici. Durante le operazioni di recupero dei dati, questi verranno visualizzati come se non fosse-
ro compressi. È possibile disattivare la compressione dell’indice; ricreare l’indice con la clauso-
la NOCOMPRESS.
COMPUTE STATISTICS analizza i dati di indice mentre quest’ultimo viene creato.
A partire da Oracle Database 10g è possibile creare indici con partizionamento hash globali.
GUIDA DI RIFERIMENTO ALFABETICA 1049
CREATE INDEXTYPE
SINTASSI
create_indextype::=
OR REPLACE schema .
CREATE INDEXTYPE indextype
,
schema .
FOR operator ( paramater_type ) using_type_clause
using_type_clause::=
schema . array_DML_clause
USING implementation_type
array_DML_clause::=
WITH
WITHOUT
ARRAY DML
schema .
schema . , varray_type
( type )
CREATE JAVA
VEDERE ANCHE ALTER JAVA, DROP JAVA, Capitoli 37, 38 e 39.
SINTASSI
1050 CAPITOLO 48
create_java::=
RESOLVE
AND
OR REPLACE COMPILE NOFORCE
CREATE
SOURCE schema .
NAMED primary_name
RESOURCE
JAVA
SCHEMA schema
CLASS
, schema_name
RESOLVER ( ( match_string ) )
invoker_rights_clause –
CLOB
BFILE
;
’ key_for_BLOB ’
AS source_text
invoker_rights_clause::=
CURRENT_USER
AUTHID
DEFINER
DESCRIZIONE CREATE JAVA crea una sorgente, una classe o una risorsa Java. Si deve posse-
dere il privilegio di sistema CREATE PROCEDURE oppure (per creare l’oggetto nello schema
di un altro utente) CREATE ANY PROCEDURE. Per sostituire un oggetto dello schema simile
nello schema di un altro utente, è necessario disporre del privilegio di sistema ALTER ANY
PROCEDURE.
Le clausole JAVA SOURCE, JAVA CLASS e JAVA RESOURCE caricano sorgenti, classi e
risorse.
AUTHID consente di specificare se la funzione viene eseguita con i privilegi del proprietario
della funzione o con quelli dell’utente corrente.
ESEMPIO
Il comando seguente crea un sorgente Java:
CREATE LIBRARY
VEDERE ANCHE CREATE FUNCTION, CREATE PACKAGE BODY, CREATE PROCEDU-
RE, Capitolo 31.
SINTASSI
schema .
CREATE MATERIALIZED VIEW materialized_view
schema .
OF object_type ( scoped_table_ref_constraint )
WITH
REDUCED PRECISION
WITHOUT
ON PREBUILT TABLE
physical_properties materialized_view_props
physical_attributes_clause
TABLESPACE tablespace
USING INDEX
DISABLE
QUERY REWRITE
FOR UPDATE ENABLE
AS subquery ;
1052 CAPITOLO 48
physical_properties::=
table_compression
segment_attributes_clause
segment_attributes_clause table_compression
HEAP
segment_attributes_clause
ORGANIZATION
INDEX index_org_table_clause
EXTERNAL external_table_clause
materialized_view_props::=
CACHE
build_clause
scoped_table_ref_constraint::=
index_org_table_clause::=
mapping_table_clause
PCTTHRESHOLD integer
key_compression index_org_overflow_clause
key_compression::=
integer
COMPRESS
NOCOMPRESS
GUIDA DI RIFERIMENTO ALFABETICA 1053
index_org_overflow-clause::=
create_mv_refresh:=
FAST
COMPLETE
FORCE
DEMAND
ON
COMMIT
START WITH
date
NEXT
PRIMARY KEY
WITH
REFRESH ROWID
MASTER
LOCAL
DEFAULT ROLLBACK SEGMENT
MASTER
USING
LOCAL
ROLLBACK SEGMENT rollback_segment
ENFORCED
USING CONSTRAINTS
TRUSTED
NEVER REFRESH
segment_attributes_clause::=
physical_attributes_clause
TABLESPACE tablespace
logging_clause
physical_attributes_clause::=
PCTFREE integer
PCTUSED integer
INITRANS integer
storage_clause
1054 CAPITOLO 48
logging_clause::=
LOGGING
NOLOGGING
table_compression::=
COMPRESS
NOCOMPRESS
column_properties::=
object_type_col_properties
nested_table_col_properties
varray_col_properties ( LOB_partition_storage )
LOB_storage_clause
XMLType_column_properties
object_type_col_properties::=
substitutable_column_clause::=
ELEMENT TYPE
IS OF ( ONLY type )
NOT
SUBSTITUTABLE AT ALL LEVELS
nested_table_col_properties::=
nested_item substitutable_column_clause
NESTED TABLE STORE AS storage_table
COLUMN_VALUE
( object_properties )
( physical_properties ) LOCATOR
RETURN AS
column_properties VALUE
GUIDA DI RIFERIMENTO ALFABETICA 1055
varray_col_properties::=
VARRAY varray_item
LOB_segname
substitutable_column_clause ( LOB_parameters )
STORE AS LOB
LOB_segname
substitutable_column_clause
LOB_storage_clause::=
( LOB_parameters )
LOB_parameters::=
TABLESPACE tablespace
ENABLE
STORAGE IN ROW
DISABLE
storage_clause
CHUNK integer
PCTVERSION integer
RETENTION
FREEPOOLS integer
CACHE
NOCACHE logging_clause
CACHE READS
LOB_partition_storage::=
LOB_storage_clause
PARTITION partition
varray_col_properties
LOB_storage_clause
( SUBPARTITION subpartition )
varray_col_properties
1056 CAPITOLO 48
parallel_clause::=
NOPARALLEL
integer
PARALLEL
build_clause::=
IMMEDIATE
BUILD
DEFERRED
schema .
CREATE MATERIALIZED VIEW LOG ON table
physical_attributes_clause
TABLESPACE tablespace
logging_clause
CACHE
OBJECT ID
PRIMARY KEY
ROWID new_values_clause
WITH
SEQUENCE
( column )
;
physical_attributes_clause::=
PCTFREE integer
PCTUSED integer
INITRANS integer
storage_clause
logging_clause::=
LOGGING
NOLOGGING
1058 CAPITOLO 48
parallel_clause::=
NOPARALLEL
integer
PARALLEL
new_values_clause::=
INCLUDING
NEW VALUES
EXCLUDING
CREATE OPERATOR
SINTASSI
create_operator::=
OR REPLACE schema .
CREATE OPERAT0R operator binding_clause ;
binding_clause::=
BINDING
,
implementation_clause
( parameter_type ) RETURN return_type using_function_clause
GUIDA DI RIFERIMENTO ALFABETICA 1059
implementation_clause::=
context_clause
context_clause::=
using_function_clause::=
package .
schema . type .
USING function_name
CREATE OUTLINE
VEDERE ANCHE Capitolo 43.
SINTASSI
DESCRIZIONE CREATE OUTLINE crea una struttura memorizzata, ovvero un gruppo di sugge-
rimenti utilizzati per creare un piano esecutivo della query associata. Le esecuzioni successive
della query applicheranno lo stesso gruppo di suggerimenti. Le strutture memorizzate possono
essere raggruppate in categorie.
1060 CAPITOLO 48
Per creare un operatore, si deve possedere il privilegio di sistema CREATE ANY OUTLINE.
ESEMPIO
CREATE PACKAGE
VEDERE ANCHE ALTER PACKAGE; CREATE FUNCTION; CREATE PACKAGE BODY;
CREATE PROCEDURE; CURSORE; DROP PACKAGE; ECCEZIONE; RECORD; TABEL-
LA; VARIABILI, DICHIARAZIONE, Capitolo 31.
SINTASSI
disporre del privilegio di sistema CREATE PROCEDURE; per creare il corpo di un package
nell’account di un altro utente, occorre possedere il privilegio di sistema CREATE ANY PROCE-
DURE.
CREATE PFILE
VEDERE ANCHE CREATE SPFILE, init.ora.
SINTASSI
DESCRIZIONE CREATE PFILE esporta un file binario dei parametri di server in un file di testo
dei parametri di inizializzazione (init.ora). La creazione di un file di testo dei parametri è una
soluzione conveniente per ottenere un elenco delle impostazioni dei parametri correnti utilizzate
dal database, e consente di modificare facilmente il file in un editore di testo e di convertirlo
nuovamente in un file dei parametri di server con l’istruzione CREATE SPFILE. Si possono
specificare entrambi i nomi: il nome del file binario di origine dei parametri di server e quello del
file di testo di destinazione dei parametri.
ESEMPIO
CREATE PROCEDURE
VEDERE ANCHE ALTER PROCEDURE; BLOCCO, STRUTTURA; CREATE LIBRARY;
CREATE FUNCTION; CREATE PACKAGE; DATI, TIPI; DROP PROCEDURE, Capitoli 31 e 39.
SINTASSI
create_procedure::=
OR REPLACE schema .
CREATE PROCEDURE procedure
IN
OUT
IN OUT NOCOPY
( argument datatype )
invoker_rights_clause IS pl/sql_subprogram_body
;
AS call_spec
1062 CAPITOLO 48
invoker_rights_clause::=
CURRENT_USER
AUTHID
DEFINER
call_spec::=
Java_declaration
LANGUAGE
C_declaration
Java_declaration::=
C_declaration::=
DESCRIZIONE CREATE PROCEDURE crea la specifica e il corpo di una procedura. Una pro-
cedura può avere parametri, ovvero argomenti di un certo tipo di dati cui è stato assegnato un
nome. Il blocco PL/SQL definisce il comportamento della procedura come una serie di dichiara-
zioni, istruzioni di programma PL/SQL ed eccezioni.
Il qualificatore IN significa che è necessario specificare un valore per l’argomento quando si
chiama la procedura. Il qualificatore OUT significa che la procedura restituisce un valore al
chiamante attraverso questo argomento. Il qualificatore IN OUT combina sia il significato di IN
che quello di OUT; si specifica un valore e la procedura lo sostituisce con un altro. Se non si
specifica alcun qualificatore, l’argomento predefinito è IN. La differenza tra una funzione e una
procedura è che la funzione restituisce un valore all’ambiente chiamante oltre a qualsiasi argo-
mento di tipo OUT.
Il blocco PL/SQL può fare riferimento ai programmi contenuti in una libreria C esterna
oppure a una specifica di chiamata Java. La clausola invoker_rights (AUTHID) consente di speci-
ficare se la procedura viene eseguita con i privilegi del proprietario della funzione o con quelli
dell’utente che chiama la funzione.
GUIDA DI RIFERIMENTO ALFABETICA 1063
CREATE PROFILE
VEDERE ANCHE ALTER PROFILE, ALTER RESOURCE COST, ALTER SYSTEM, ALTER
USER, CREATE USER, DROP PROFILE, Capitolo 18.
SINTASSI
create_profile::=
resource_parameters
CREATE PROFILE profile LIMIT ;
password_parameters
resource_parameters::=
SESSIONS_PER_USER
CPU_PER_SESSION
CPU_PER_CALL
integer
CONNECT_TIME
UNLIMITED
IDLE_TIME
DEFAULT
LOGICAL_READS_PER_SESSION
LOGICAL_READS_PER_CALL
COMPOSITE_LIMIT
M
integer
PRIVATE_SGA UNLIMITED
DEFAULT
password_parameters::=
FAILED_LOGIN_ATTEMPTS
PASSWORD_LIFE_TIME
expr
PASSWORD_REUSE_TIME
UNLIMITED
PASSWORD_REUSE_MAX
DEFAULT
PASSWORD_LOCK_TIME
PASSWORD_GRACE_TIME
function
PASSWORD_VERIFY_FUNCTION NULL
DEFAULT
1064 CAPITOLO 48
DESCRIZIONE CREATE PROFILE crea un insieme di limiti relativi all’uso delle risorse del
database. Quando si associa il profilo a un utente tramite CREATE o ALTER USER, è possibile
controllare quello che l’utente fa grazie a questi limiti,. Per utilizzare CREATE PROFILE, è
necessario abilitare i limiti delle risorse attraverso il parametro di inizializzazione RESOURCE_LIMIT
oppure con il comando ALTER SYSTEM.
SESSIONS_PER_USER limita il numero di sessioni SQL contemporanee intere per l’uten-
te. CPU_PER_SESSION limita il tempo di CPU in centesimi di secondo. CPU_PER_CALL
limita il tempo di CPU in centesimi di secondo per analisi, esecuzioni o chiamate fetch.
CONNECT_TIME limita il tempo rimanente di una sessione in minuti. IDLE_TIME scollega un
utente trascorsi i minuti specificati; ciò non si applica durante l’esecuzione di una query.
LOGICAL_READS_PER_SESSION limita il numero di blocchi letti per sessione; LOGICAL_
READS_PER_CALL fa la stessa cosa per l’analisi, l’esecuzione o le chiamate fetch. PRIVATE_SGA
limita la quantità di spazio che è possibile allocare come privato nella SG; le opzioni K e M si
applicano solo a questo limite. COMPOSITE_LIMIT limita il costo totale delle risorse per sessio-
ne, espresso in unità di servizio in base a una somma pesata dei costi della CPU, del tempo di
connessione, delle letture logiche e delle risorse SGA private.
UNLIMITED significa che non esiste un limite per una particolare risorsa. DEFAULT selezio-
na il limite dal profilo predefinito, che può essere modificato tramite il comando ALTER PROFILE.
Se un utente supera un limite, Oracle sospende l’esecuzione ed esegue il rollback della
transazione, quindi termina la sessione. Per creare un profilo, è necessario disporre del privilegio
di sistema CREATE PROFILE. Per associare un profilo a un utente, si utilizza il comando ALTER
USER.
CREATE ROLE
VEDERE ANCHE ALTER ROLE, ALTER USER, CREATE USER, DROP ROLE, GRANT,
REVOKE, ROLE, SET ROLE, Capitolo 18.
SINTASSI
DESCRIZIONE Con CREATE ROLE è possibile creare un ruolo con un certo nome o un insieme
di privilegi. Quando si concede un ruolo a un utente, in realtà gli si concedono tutti i privilegi di
quel ruolo. Per prima cosa, è necessario creare il ruolo con CREATE ROLE, poi concedere i
privilegi al ruolo con il comando GRANT. Quando un utente desidera accedere a qualche opera-
zione consentita dal ruolo che possiede, abilita il ruolo con SET ROLE. In alternativa, si può
impostare il ruolo come il ruolo DEFAULT dell’utente tramite il comando ALTER USER o CRE-
ATE USER.
Se si protegge il ruolo tramite una password, l’utente che intende disporre dei privilegi deve
fornire la password con il comando SET ROLE per abilitare il ruolo. La clausola USING package
consente di creare il ruolo di un’applicazione, ovvero un ruolo che può essere abilitato soltanto
da applicazioni che usano il package autorizzato. Se non si specifica schema, Oracle assume che
il package si trovi nello schema di proprietà dell’utente.
GUIDA DI RIFERIMENTO ALFABETICA 1065
CREATE SCHEMA
VEDERE ANCHE CREATE TABLE, CREATE VIEW, GRANT.
SINTASSI
DESCRIZIONE Il comando CREATE SCHEMA crea una collection di tabelle, viste e concessio-
ni di privilegi come un’unica transazione. Il nome dello schema è identico al proprio nome
utente di Oracle. I comandi CREATE TABLE, CREATE VIEW e GRANT sono i comandi standard
e l’ordine con cui appaiono non è importante, anche se esistono dipendenze interne.
CREATE SEQUENCE
VEDERE ANCHE ALTER SEQUENCE, AUDIT, DROP SEQUENCE, GRANT, REVOKE,
NEXTVAL e CURRVAL alla voce PSEUDOCOLONNE, Capitolo 17.
SINTASSI
DESCRIZIONE sequenza è il nome assegnato alla sequenza. Il valore predefinito per INCREMENT
BY è 1. Un numero positivo incrementa il numero della sequenza di un intervallo uguale all’in-
tero. Un numero negativo decrementa la sequenza (ossia ne riduce il valore) nello stesso modo.
START WITH è il numero con cui la sequenza ha inizio. Il valore predefinito per START WITH è
MAXVALUE per le sequenze in ordine decrescente e MINVALUE per quelle in ordine crescente;
per sostituire questo valore predefinito, si utilizzi START WITH.
MINVALUE è il numero più piccolo che la sequenza può generare. Il valore predefinito è 1
per le sequenze in ordine crescente. MAXVALUE è il numero più grande che la sequenza può
generare. Per le sequenze in ordine decrescente il valore predefinito è –1. Per consentire alle
sequenze di progredire senza limiti, è sufficiente specificare MINVALUE per le sequenze in ordi-
ne crescente e MAXVALUE per quelle in ordine decrescente. Per interrompere la creazione dei
numeri di sequenza e indurre un errore nel caso si cerchi di ottenere un nuovo numero, occorre
specificare un MAXVALUE su una sequenza in ordine crescente, o un MINVALUE su una sequen-
za in ordine decrescente, più NOCYCLE. Per riavviare entrambi i tipi di sequenze dal punto
corrispondente al relativo MAXVALUE o MINVALUE, occorre specificare CYCLE.
CACHE consente di tenere in memoria un gruppo preallocato di numeri di sequenza. Il
valore predefinito è 20. Il valore impostato dev’essere minore di MAXVALUE meno MINVALUE.
ORDER garantisce che i numeri di sequenza verranno assegnati alle istanze che li richiedo-
no nell’ordine in cui vengono ricevute le richieste. Ciò è necessario solamente nelle applicazioni
che utilizzano Real Application Clusters.
Per creare una sequenza nel proprio schema, è necessario disporre del privilegio di sistema
CREATE SEQUENCE; per creare una sequenza nello schema di un altro utente occorre possede-
re il privilegio di sistema CREATE ANY SEQUENCE.
CREATE SPFILE
VEDERE ANCHE CREATE PFILE, init.ora.
SINTASSI
DESCRIZIONE CREATE SPFILE crea un file dei parametri per server da un file dei parametri di
inizializzazione testuale sul lato client. I file dei parametri per server sono file binari che esisto-
no solo sul server e vengono chiamati dalle posizioni del client per avviare il database. I file dei
parametri di server consentono di modificare in modo permanente i singoli parametri; le modi-
fiche apportate ai parametri con i comandi ALTER SYSTEM vengono conservate durante le chiu-
sure e gli avvii del database anche se nessun file dei parametri esterno viene aggiornato manual-
mente.
CREATE SYNONYM
VEDERE ANCHE CREATE DATABASE LINK, CREATE TABLE, CREATE VIEW, Capitoli
17 e 23.
GUIDA DI RIFERIMENTO ALFABETICA 1067
SINTASSI
DESCRIZIONE CREATE SYNONYM crea un sinonimo per una tabella, vista, sequenza, stored
procedure, funzione, package, vista materializzata, oggetto di classe Java oppure sinonimo com-
presi quelli che risiedono su un server remoto. PUBLIC rende disponibile il sinonimo per tutti gli
utenti, ma può essere creato solo da un DBA. Senza PUBLIC, gli utenti devono anteporre al
sinonimo il proprio nome utente. sinonimo è il nome del sinonimo. utente.tabella rappresenta il
nome della tabella, della vista o del sinonimo cui fa riferimento il sinonimo stesso. È possibile
creare il sinonimo di un sinonimo. @link_database è un database link a un database remoto. Il
sinonimo si riferisce a una tabella nel database remoto come specificato dal database link.
ESEMPIO
CREATE TABLE
VEDERE ANCHE ALTER TABLE; CREATE CLUSTER; CREATE INDEX; CREATE
TABLESPACE; CREATE TYPE; DATI, TIPI; DROP TABLE, VINCOLO DI INTEGRITÀ,
NOMI DEGLI OGGETTI, STORAGE, Capitoli 3, 17, 26, 33, 34 e 36.
SINTASSI
create_table::=
relational_table
object_table
XMLType_table
relational_table::=
DELETE
ON COMMIT ROWS
( relational_properties ) PRESERVE
physical_properties table_properties
;
1068 CAPITOLO 48
object_table::=
schema . object_table_substitution
OF object_type
DELETE
ON COMMIT ROWS
( object_properties ) PRESERVE
XMLType_table::=
DELETE
ON COMMIT ROWS
PRESERVE OID_clause OID_index_clause
physical_properties table_properties
relational_properties::=
inline_constraint
out_of_line_constraint
out_of_line_ref_constraint
supplemental_logging_props
GUIDA DI RIFERIMENTO ALFABETICA 1069
object_table_substitution::=
NOT
SUBSTITUTABLE AT ALL LEVELS
object_properties::=
inline_constraint
attribute
out_of_line_constraint
out_of_line_ref_constraint
supplemental_logging_props
oid_clause::=
SYSTEM GENERATED
OBJECT IDENTIFIER IS
PRIMARY KEY
oid_index_clause::=
index physical_attributes_clause
OIDINDEX ( )
TABLESPACE tablespace
physical_properties::=
table_compression
segment_attributes_clause
segment_attributes_clause table_compression
HEAP
segment_attributes_clause
ORGANIZATION
INDEX index_org_table_clause
EXTERNAL external_table_clause
segment_attributes_clause::=
physical_attributes_clause
TABLESPACE tablespace
logging_clause
physical_attributes_clause::=
PCTFREE integer
PCTUSED integer
INITRANS integer
storage_clause
table_compression::=
COMPRESS
NOCOMPRESS
table_properties::=
CACHE
ROWDEPENDENCIES
parallel_clause NOROWDEPENDENCIES
column_properties::=
object_type_col_properties
nested_table_col_properties
varray_col_properties ( LOB_partition_storage )
LOB_storage_clause
XMLType_column_properties
GUIDA DI RIFERIMENTO ALFABETICA 1071
object_type_col_properties::=
substitutable_column_clause::=
ELEMENT TYPE
IS OF ( ONLY type )
NOT
SUBSTITUTABLE AT ALL LEVELS
nested_table_col_properties::=
nested_item substitutable_column_clause
NESTED TABLE STORE AS storage_table
COLUMN_VALUE
( object_properties )
( physical_properties ) LOCATOR
RETURN AS
column_properties VALUE
varray_col_properties::=
VARRAY varray_item
LOB_segname
substitutable_column_clause ( LOB_parameters )
STORE AS LOB
LOB_segname
substitutable_column_clause
LOB_storage_clause::=
( LOB_parameters )
1072 CAPITOLO 48
LOB_parameters::=
TABLESPACE tablespace
ENABLE
STORAGE IN ROW
DISABLE
storage_clause
CHUNK integer
PCTVERSION integer
RETENTION
FREEPOOLS integer
CACHE
NOCACHE logging_clause
CACHE READS
logging_clause::=
LOGGING
NOLOGGING
LOB_partition_storage::=
LOB_storage_clause
PARTITION partition
varray_col_properties
LOB_storage_clause
( SUBPARTITION subpartition )
varray_col_properties
XMLType_column_properties::=
XMLType_storage::=
OBJECT RELATIONAL
( LOB_parameters )
STORE AS LOB_segname
LOB_parameters
CLOB
XMLSchema_spec::=
row_movement_clause::=
ENABLE
ROW MOVEMENT
DISABLE
index_org_table_clause::=
mapping_table_clause
PCTTHRESHOLD integer
key_compression index_org_overflow_clause
mapping_table_clauses::=
MAPPING TABLE
NOMAPPING
key_compression::=
integer
COMPRESS
NOCOMPRESS
1074 CAPITOLO 48
index_org_overflow_clause::=
supplemental_logging_props::=
supplemental_log_grp_clause
supplemental_id_key_clause
supplemental_log_grp_clause::=
NO LOG ALWAYS
GROUP log_group ( column )
supplemental_id_key_clause::=
ALL
PRIMARY KEY
DATA ( ) COLUMNS
UNIQUE
FOREIGN KEY
external_table_clause::=
integer
REJECT LIMIT
TYPE access_driver_type UNLIMITED
( external_data_properties )
external_data_properties::=
( opaque_format_spec )
ACCESS PARAMETERS
USING CLOB subquery
DEFAULT DIRECTORY directory
directory :
LOCATION ( ’ location_specifier ’ )
GUIDA DI RIFERIMENTO ALFABETICA 1075
table_partitioning_clauses::=
range_partitioning
hash_partitioning
list_partitioning
composite_partitioning
range_partitioning::=
partition
( PARTITION range_values_clause table_partition_description )
hash_partitioning::=
,
individual_hash_partitions
PARTITION BY HASH ( column )
hash_partitions_by_quantity
list_partitioning::=
partition
( PARTITION list_values_clause table_partition_description )
composite_partitioning::=
subpartition_by_list
PARTITION BY RANGE ( column_list )
subpartition_by_hash
partition
( PARTITION range_values_clause table_partition_description )
1076 CAPITOLO 48
subpartition_by_hash::=
STORE IN ( tablespace )
SUBPARTITIONS quantity
subpartition_template
individual_hash_partitions::=
partition partitioning_storage_clause
( PARTITION )
hash_partitions_by_quantity::=
STORE IN ( tablespace )
PARTITIONS hash_partition_quantity
subpartition_by_list::=
subpartition_template
SUBPARTITION BY LIST ( column )
subpartition_template::=
SUBPARTITION TEMPLATE
list_values_clause partitioning_storage_clause
( SUBPARTITION subpartition )
hash_subpartition_quantity
GUIDA DI RIFERIMENTO ALFABETICA 1077
range_values_clause::=
value
VALUES LESS THAN ( )
MAXVALUE
list_values_clause::=
value
NULL
VALUES ( )
DEFAULT
table_partition_description::=
table_compression
segment_attributes_clause key_compression
segment_attributes_clause
OVERFLOW
LOB_storage_clause
varray_col_properties partition_level_subpartition
partition_level_subpartition::=
STORE IN ( tablespace )
SUBPARTITIONS hash_subpartition_quantity
( subpartition_spec )
subpartition_spec::=
partitioning_storage_clause::=
TABLESPACE tablespace
TABLESPACE tablespace
OVERFLOW
( TABLESPACE tablespace )
LOB_segname
LOB ( LOB_item ) STORE AS
( TABLESPACE tablespace )
parallel_clause::=
NOPARALLEL
integer
PARALLEL
enable_disable_clause::=
,
VALIDATE
UNIQUE ( column )
ENABLE NOVALIDATE
PRIMARY KEY
DISABLE
CONSTRAINT constraint
KEEP
INDEX
using_index_clause exceptions_clause CASCADE DROP
using_index_clause::=
schema .
index
index_properties
index_properties::=
global_partitioned_index
local_partitioned_index
index_attributes
domain_index_clause
GUIDA DI RIFERIMENTO ALFABETICA 1079
index_attributes::=
physical_attributes_clause
logging_clause
ONLINE
COMPUTE STATISTICS
tablespace
TABLESPACE
DEFAULT
key_compression
SORT
NOSORT
REVERSE
parallel_clause
Per i dettagli sull’uso delle tabelle oggetto, si rimanda alla Parte quinta del libro.
Vedere VINCOLO DI INTEGRITÀ per una descrizione completa dei vincoli di tabella e di
colonna.
CLUSTER include la tabella in questione nel cluster specificato. Le colonne della tabella
elencate devono corrispondere, nell’ordine e nel tipo di dati, alle colonne del cluster. Non occor-
re che i nomi siano gli stessi delle corrispondenti colonne del cluster, anche se la corrispondenza
dei nomi aiuterebbe l’utente a capire cosa succede.
INITRANS specifica il numero iniziale di transazioni che possono aggiornare contempora-
neamente un blocco di dati (le selezioni non sono contate). La sequenza di valori per INITRANS
va da 1 a 255. 1 è il valore predefinito. Ogni transazione occupa spazio nel blocco di dati (23 byte
nella maggior parte dei sistemi) fino a che non risulta completata. Quando per un blocco si crea
un numero di transazioni maggiore di INITRANS, lo spazio viene automaticamente allocato per
queste transazioni. Le code di transazioni in attesa di essere eseguite occupano sempre più spa-
zio all’interno del blocco, anche se, solitamente, c’è più spazio libero di quello necessario per
tutte le transazioni contemporanee.
1080 CAPITOLO 48
Ogni volta che Oracle inserisce una riga in una tabella, prima controlla per vedere quanto
spazio è disponibile nel blocco corrente (la dimensione di un blocco dipende dal sistema opera-
tivo, si consulti Oracle Installation and User’s Guide per il proprio sistema). Se la dimensione
della riga lascia meno spazio della percentuale PCTFREE nel blocco, la riga viene inserita in un
blocco appena allocato. Il valore predefinito è 10; 0 è il valore minimo.
PCTUSED ha un valore predefinito pari a 40, che rappresenta la percentuale minima di
spazio disponibile in un blocco perché questo rappresenti un candidato per l’inserimento di
nuove righe. Oracle tiene traccia di quanto spazio è stato liberato dalle cancellazioni in un bloc-
co. Se questo valore è inferiore a PCTUSED, Oracle rende disponibile il blocco per nuovi
inserimenti.
STORAGE contiene delle clausole secondarie descritte alla voce STORAGE. TABLESPACE
è il nome della tablespace cui è assegnata questa tabella.
Le clausole ENABLE e DISABLE abilitano o disabilitano, rispettivamente, i vincoli.
PARALLEL, assieme a DEGREE e INSTANCES, specifica le caratteristiche parallele della
tabella. DEGREE specifica il numero di server da utilizzare per le query; INSTANCES specifica
il modo in cui la tabella deve essere suddivisa tra le istanze di Real Application Clusters per
l’elaborazione in parallelo delle query. Un intero n indica che la tabella dev’essere suddivisa tra
il numero specificato di istanze disponibili.
Le clausole PARTITION controllano come vengono partizionati i dati della tabella: per inter-
vallo, per hash oppure con una composizione di più metodi di partizionamento. Per i dettagli sul
partizionamento, si consulti il Capitolo 18.
Una tabella temporanea contiene dei dati che sono visibili solo per la sessione che li ha
creati. Se una tabella temporanea viene definita come GLOBAL la sua definizione può essere
visibile a tutti gli utenti. Le tabelle temporanee possono anche non essere partizionate e non
sono in grado di supportare molte caratteristiche standard delle tabelle (come i tipi di dati array
variabile, i tipi di dati LOB e l’organizzazione di solo indice). Per esempio, il comando seguente
crea una tabella le cui righe verranno cancellate alla fine della sessione corrente
La clausola AS crea le righe della nuova tabella attraverso le righe restituite dalla query. Le
colonne e i tipi della query devono corrispondere a quelli definiti in CREATE TABLE. La query
utilizzata nella clausola AS non può contenere alcuna colonna di tipo LONG. Durante l’opera-
zione create table... as select, si possono disattivare le operazioni di log tramite la parola chiave
NOLOGGING. Questa opzione disabilita le voci redo log che verrebbero normalmente scritte
durante il riempimento della nuova tabella, migliorando così le prestazioni ma compromettendo
la possibilità da parte dell’utente di recuperare questi dati nel caso si verificasse un fallimento
dell’istanza prima del successivo backup.
La clausola LOB specifica la memorizzazione dei dati fuori linea per dati LOB (BLOB,
CLOB e NCLOB) memorizzati internamente. Per i dettagli sulla gestione dei dati LOB si riman-
da al Capitolo 35.
La sezione relativa alla definizione della tabella oggetto si applica alle tabelle oggetto in cui
ciascuna riga contiene l’ID di un oggetto (OID). Vedere il Capitolo 36.
GUIDA DI RIFERIMENTO ALFABETICA 1081
CREATE TABLESPACE
VEDERE ANCHE ALTER TABLESPACE, DROP TABLESPACE, Capitoli 20 e 46.
SINTASSI
create_tablespace::=
BIGFILE
permanent_tablespace_clause
SMALLFILE
CREATE temporary_tablespace_clause ;
undo_tablespace_clause
permanent_tablespace_clause::=
DATAFILE file_specification
TABLESPACE tablespace
M
MINIMUM EXTENT integer
K
BLOCKSIZE integer
logging_clause
FORCE LOGGING
table_compression
DEFAULT storage_clause ;
ONLINE
OFFLINE
extent_management_clause
segment_management_clause
flashback_mode_clause
logging_clause::=
LOGGING
NOLOGGING
1082 CAPITOLO 48
table_compression::=
COMPRESS
NOCOMPRESS
extent_management_clause::=
DICTIONARY
AUTOALLOCATE
EXTENT MANAGEMENT
SIZE size_clause
UNIFORM
LOCAL
size_clause::=
T
integer
segment_management_clause::=
MANUAL
SEGMENT SPACE MANAGEMENT
AUTO
flashback_mode_clause::=
ON
FLASHBACK
OFF
temporary_tablespace_clause::=
TEMPFILE file_specification
TEMPORARY TABLESPACE tablespace
tablespace_group_clause extent_management_clause
GUIDA DI RIFERIMENTO ALFABETICA 1083
tablespace_group_clause::=
tablespace_group_name
TABLESPACE GROUP
’ ’
undo_tablespace_clause::=
DATAFILE file_specification
UNDO TABLESPACE tablespace
extent_management_clause tablespace_retention_clause
tablespace_retention_clause::=
GUARANTEE
RETENTION
NOGUARANTEE
Il formato del file dipende dal sistema operativo. SIZE rappresenta il numero di byte riserva-
ti per questo file. Se si specifica il suffisso K, il valore viene moltiplicato per 1024; il suffisso M
lo moltiplica per 1048576. DEFAULT STORAGE definisce la memorizzazione predefinita di tutti
gli oggetti creati nella tablespace, a meno che questi valori predefiniti non vengano sostituiti nel
comando CREATE TABLE. ONLINE, il valore predefinito, indica che questa tablespace sarà di-
sponibile agli utenti subito dopo la sua creazione. OFFLINE impedisce l’accesso alla tablespace
fino a che il comando ALTER TABLESPACE non la modifica in ONLINE. DBA_TABLESPACES
fornisce lo stato di tutte le tablespace.
SIZE e REUSE utilizzate insieme comunicano ad Oracle di riutilizzare il file se esiste già (il
suo contenuto viene distrutto), oppure di crearlo se non esiste ancora. SIZE senza REUSE crea
un file che non esiste ma restituisce un errore nel caso in cui il file esista già. Senza SIZE, il file
deve esistere già.
Il parametro di dimensionamento MINIMUM EXTENT specifica la dimensione minima per
gli extent all’interno della tablespace. Il valore predefinito è specifico per ciascun sistema opera-
tivo e dipende dalla dimensione dei blocchi del database.
Quando attivata (ON), l’opzione AUTOEXTEND estende in modo dinamico un file di dati in
base alle esigenze con incrementi di dimensione pari a NEXT, fino a un massimo di MAXSIZE (o
UNLIMITED, illimitato). Se una tablespace viene utilizzata solo per segmenti temporanei creati
durante l’elaborazione della query, è possibile crearla come una tablespace TEMPORARY. Se
1084 CAPITOLO 48
CREATE TRIGGER
VEDERE ANCHE ALTER TABLE; ALTER TRIGGER; BLOCCO, STRUTTURA; DROP
TRIGGER, Capitoli 30 e 33.
SINTASSI
create_trigger::=
BEFORE
OR REPLACE schema .
CREATE TRIGGER trigger AFTER
INSTEAD OF
dml_event_clause
OR
ddl_event schema .
SCHEMA
OR ON
DATABASE
database_event
call_procedure_statement
DML_event_clause::=
OR
DELETE
INSERT
OF column
UPDATE
(segue)
GUIDA DI RIFERIMENTO ALFABETICA 1085
(continua)
schema .
table
ON NESTED TABLE nested_table_column OF schema .
view
referencing_clause::=
AS
OLD old
AS
REFERENCING NEW new
AS
PARENT parent
DESCRIZIONE CREATE TRIGGER crea e abilita un trigger per un database, ovvero il blocco di
una stored procedure associata a una tabella, indicata nella clausola on, che Oracle esegue auto-
maticamente quando l’istruzione SQL specificata viene eseguita sulla tabella. I trigger possono
essere utilizzati per imporre vincoli complessi e per propagare le modifiche in tutto il database
anziché eseguire questa operazione nelle applicazioni. In questo modo, è sufficiente implemen-
tare il codice per il trigger una volta sola anziché doverlo ripetere per ogni applicazione.
La clausola principale del comando CREATE TRIGGER specifica l’operazione SQL che
attiva il blocco (come cancellazioni, inserimenti o aggiornamenti) e il momento di attivazione
del trigger prima, dopo o al posto (BEFORE, AFTER o INSTEAD OF) dell’esecuzione dell’ope-
razione di trigger. Se si specifica una clausola OF su un trigger di tipo UPDATE, il trigger si
attiva solo quando si aggiornano uno o più delle colonne specificate. Si osservi che è anche
possibile creare trigger che si attivano quando si verificano eventi DDL (compresi create, alter e
drop) e quando si verificano eventi di database specifici (connessioni, disconnessioni, avvii e
chiusure del database ed errori del server).
La clausola REFERENCING specifica un nome di correlazione per la tabella per quanto
riguarda la versione vecchia e nuova (OLD e NEW) della tabella. Ciò consente di utilizzare il
nome come riferimento alle colonne per evitare confusione, in modo particolare quando il nome
della tabella è OLD o NEW. I nomi predefiniti sono OLD e NEW.
La clausola FOR EACH ROW specifica un trigger di riga: il trigger si attiva una volta per
ciascuna riga coinvolta da un’operazione di trigger. La clausola WHEN limita l’esecuzione del
trigger in modo che avvenga solo quando la condizione è soddisfatta. Si tratta di una condizione
SQL, non PL/SQL.
I comandi ALTER TRIGGER e ALTER TABLE consentono di disattivare e attivare i trigger.
Se un trigger è disattivato, Oracle non lo attiva nel caso in cui si verifichi un’operazione poten-
zialmente associata a trigger. Il comando CREATE TRIGGER abilita automaticamente il trigger.
1086 CAPITOLO 48
Per creare un trigger su una tabella che si possiede, è necessario disporre del privilegio di
sistema CREATE TRIGGER. Per creare un trigger sulla tabella di un altro utente, occorre essere
in possesso del privilegio di sistema CREATE ANY TRIGGER. Tutti i privilegi necessari all’ese-
cuzione delle strored procedure devono essere concessi direttamente all’utente.
CREATE TYPE
VEDERE ANCHE CREATE TABLE, CREATE TYPE BODY, Capitoli 33 e 34.
SINTASSI
create_type::=
create_incomplete_type
create_object_type
create_varray_type
create_nested_table_type
create_incomplete_type::=
OR REPLACE schema .
CREATE TYPE type_name ;
create_object_type::=
OR REPLACE schema .
CREATE TYPE type_name
IS
OBJECT
AS sqlj_object_type
schema .
UNDER supertype
, ,
sqlj_object_type_attr , element_spec
( attribute datatype )
NOT NOT
FINAL INSTANTIABLE
;
GUIDA DI RIFERIMENTO ALFABETICA 1087
invoker_rights_clause::=
CURRENT_USER
AUTHID
DEFINER
sqlj_object_type::=
SQLData
OraData
sqlj_object_type_attr::=
element_spec::=
subprogram_spec
inheritance_clauses , pragma_clause
constructor_spec
map_order_function_spec
inheritance_clauses::=
OVERRIDING
NOT
FINAL
INSTANTIABLE
subprogram_spec::=
MEMBER procedure_spec
STATIC function_spec
procedure_spec::=
IS
, call_spec
AS
PROCEDURE name ( parameter datatype )
1088 CAPITOLO 48
function_spec::=
constructor_spec::=
FINAL INSTANTIABLE
CONSTRUCTOR FUNCTION datatype
,
SELF IN OUT datatype ,
( parameter datatype )
IS
call_spec
AS
RETURN SELF AS RESULT
map_order_function_spec::=
MAP
MEMBER function_spec
ORDER
return_clause::=
IS
call_spec
AS
RETURN datatype
sqlj_object_type_sig
sqlj_object_type_sig::=
pragma_clause::=
RNDS
WNDS
method_name
PRAGMA RESTRICT_REFERENCES ( , RNPS )
DEFAULT
WNPS
TRUST
call_spec::=
Java_declaration
LANGUAGE
C_declaration
Java_declaration::=
C_declaration::=
create_varray_type::=
OR REPLACE schema .
CREATE TYPE type_name
create_nested_table_type::=
OR REPLACE schema. .
CREATE TYPE type_name
OID ’ object_identifier ’ IS
TABLE OF datatype ;
AS
DESCRIZIONE CREATE TYPE crea un tipo di dati astratto chiamato array variabile (VARRAY),
un tipo di tabella annidata oppure un tipo di oggetto incompleto. Per creare o sostituire un tipo,
è necessario disporre del privilegio CREATE TYPE. Per creare un tipo nello schema di un altro
utente, si deve disporre dei privilegi di sistema CREATE ANY TYPE.
Quando si crea un tipo di dati astratto, lo si può basare sui tipi di dati forniti da Oracle (come
DATE e NUMBER) e sui tipi di dati astratti definiti precedentemente.
Un tipo “incompleto” possiede un nome ma non ha attributi o metodi. Tuttavia, altri tipi di
oggetti possono farvi riferimento quindi, può essere utilizzato per definire tipi di oggetti che
fanno riferimento l’uno all’altro. Se due tipi fanno riferimento l’uno all’altro, uno dei due de-
v’essere creato come tipo incompleto, quindi occorre creare il secondo tipo e infine creare nuo-
vamente il primo con una definizione adeguata.
Se si intende creare dei metodi per il tipo, è necessario dichiarare i nomi dei metodi nella
specifica del tipo.
ESEMPI
Creazione di un tipo con metodi associati:
OR REPLACE schema .
CREATE TYPE BODY type_name
IS subprogram_declaration
END ;
AS map_order_func_declaration
subprogram_declaration::=
procedure_declaration
MEMBER
function_declaration
STATIC
constructor_declaration
procedure_declaration::=
,
IS pl/sql_block
PROCEDURE name ( parameter datatype )
AS call_spec
function_declaration::=
,
IS pl/sql_block
FUNCTION name ( parameter datatype ) RETURN datatype
AS call_spec
constructor_declaration::=
FINAL INSTANTIABLE
CONSTRUCTOR FUNCTION datatype
,
SELF IN OUT datatype ,
( parameter datatype )
IS pl/sql_block
RETURN SELF AS RESULT
AS call_spec
1092 CAPITOLO 48
map_order_func_declaration::=
MAP
MEMBER function_spec
ORDER
call_spec::=
Java_declaration
LANGUAGE
C_declaration
Java_declaration::=
C_declaration::=
DESCRIZIONE CREATE TYPE BODY specifica i metodi da applicare ai tipi creati tramite CRE-
ATE TYPE. Per creare i corpi dei tipi, è necessario disporre del privilegio CREATE TYPE. Per
creare il corpo di un tipo nello schema di un altro utente, occorre possedere il privilegio CREATE
ANY TYPE.
ESEMPIO
CREATE USER
VEDERE ANCHE ALTER USER, CREATE PROFILE, CREATE ROLE, CREATE
TABLESPACE, GRANT, Capitolo 18.
SINTASSI
GUIDA DI RIFERIMENTO ALFABETICA 1093
create_user::=
BY password
GLOBALLY AS ’ external_name ’
tablespace
TEMPORARY TABLESPACE
tablespace_group_name
M
integer
QUOTA ON tablespace
UNLIMITED
PROFILE profile
PASSWORD EXPIRE
LOCK
ACCOUNT
UNLOCK
;
DESCRIZIONE CREATE USER crea l’account di un utente che consente di accedere al database
disponendo di un certo gruppo di privilegi e di impostazioni di memorizzazione. Se si specifica
una password, al momento del collegamento si deve fornire questa password; se si specifica
l’opzione EXTERNALLY, l’accesso viene sottoposto a verifica attraverso le funzionalità di sicu-
rezza del sistema operativo. La verifica di collegamenti esterni utilizza il parametro di
inizializzazione OS_AUTHENT_PREFIX per anteporre l’ID dell’utente all’interno del sistema
operativo, quindi il nome dell’utente specificato in CREATE USER deve possedere questo pre-
fisso (solitamente OPS$).
DEFAULT TABLESPACE è la tablespace in cui gli utenti creano gli oggetti. TEMPORARY
TABLESPACE è la tablespace in cui vengono creati gli oggetti temporanei per le operazioni
dell’utente.
Per entrambe le tablespace è possibile stabilire un valore QUOTA che limita la quantità di
spazio, in byte (kilobyte o megabyte rispettivamente per le opzioni K o M), che un utente può
allocare. La clausola profile assegna un certo profilo all’utente per limitare l’uso delle risorse del
database. Se non si specifica un profilo, Oracle assegna all’utente il profilo DEFAULT.
La prima volta che si crea un utente, questo non ha privilegi. Per concedere ruoli e privilegi
all’utente, è necessario il comando GRANT. Normalmente, come minimo privilegio viene con-
cesso CREATE SESSION.
Per ulteriori informazioni sulle scadenze delle password e il blocco dell’account, si consulti
la voce CREATE PROFILE e il Capitolo 18.
1094 CAPITOLO 48
CREATE VIEW
VEDERE ANCHE CREATE SYNONYM, CREATE TABLE, DROP VIEW, RENAME, VIN-
COLO DI INTEGRITÀ, Capitoli 17 e 33.
SINTASSI
create_view::=
NO
OR REPLACE FORCE schema .
CREATE VIEW view
inline_constraint
alias
( )
out_of_line_constraint
object_view_clause
XMLType_view_clause subquery_restriction_clause
AS subquery ;
object_view_clause::=
DEFAULT
out_of_line_constraint
( )
attribute inline_constraint
XMLType_view_clause::=
DEFAULT
XMLSchema_spec
OF XMLTYPE WITH OBJECT IDENTIFIER ,
( expr )
GUIDA DI RIFERIMENTO ALFABETICA 1095
XMLSchema_spec::=
subquery_restriction_clause::=
READ ONLY
WITH CONSTRAINT constraint
CHECK OPTION
DESCRIZIONE CREATE VIEW definisce una vista di nome vista. utente è il nome dell’utente
per il quale si crea la vista. L’opzione OR REPLACE ricrea la vista se questa esiste già. L’opzio-
ne FORCE crea la vista indipendentemente dal fatto che le tabelle cui essa fa riferimento esista-
no o meno, o se l’utente possiede i privilegi su queste tabelle. L’utente non può ancora eseguire
la vista, ma la può creare. L’opzione NO FORCE crea la vista solo se le tabelle di base esistono
e se l’utente possiede dei privilegi su di esse.
Se si specifica un alias, la vista lo utilizza come nome della colonna corrispondente all’inter-
no della query. Se non si specifica alcun alias, la vista eredita il nome della colonna dalla query;
in questo caso, ciascuna colonna della query deve possedere un nome univoco, conforme alle
normali convenzioni di denominazione di Oracle. Non può essere un’espressione. Anche un
alias presente nella query può servire per cambiare nome alla colonna.
AS query identifica le colonne delle tabelle e le altre viste destinate a comparire in questa
vista. La clausola where di questa vista stabilisce quali righe debbano essere recuperate.
WITH CHECK OPTION limita gli inserimenti e gli aggiornamenti eseguiti attraverso la vista
per evitare che creino righe che la vista stessa non è in grado di selezionare, in base alla clausola
where dell’istruzione CREATE VIEW. WITH CHECK OPTION può essere utilizzato in una vista
che si basa su un’altra vista; tuttavia, se la vista di base possiede già un’opzione WITH CHECK
OPTION, viene ignorato.
vincolo è il nome assegnato a CHECK OPTION; si tratta di un nome facoltativo assegnato a
questo vincolo. Senza di esso, Oracle assegna un nome nella forma SYS_Cn, dove n è un intero.
Un nome assegnato da Oracle in genere non rimane uguale durante le importazioni, cosa che non
accade con i nomi assegnati dall’utente.
UPDATE e DELETE funzionano sulle righe di una vista se la vista si basa su un’unica tabella
e la sua query non contiene la clausola group by, la clausola distinct, funzioni di gruppo o riferi-
menti alla pseudocolonna RowNum. Si possono aggiornare le viste contenenti altre pseudocolonne
o espressioni, purché non abbiano riferimenti all’interno di UPDATE.
Si possono inserire righe attraverso una vista se la vista si basa su un’unica tabella e se la sua
query non contiene la clausola group by, la clausola distinct, funzioni di gruppo, riferimenti a
qualsiasi pseudocolonna o espressione; le righe possono essere inserite anche tramite una vista
con più di una tabella usando i trigger INSTEAD OF. Se la vista viene creata specificando
l’opzione WITH READ ONLY, le uniche operazioni consentite dalla vista sono le selezioni, men-
tre non è concessa alcuna manipolazione dei dati.
Si possono creare viste oggetto per sovrapporre tipi di dati astratti su tabelle relazionali già
esistenti. Vedere il Capitolo 33.
1096 CAPITOLO 48
Per creare una vista, è necessario disporre del privilegio di sistema CREATE VIEW. Per
creare una vista nello schema di un altro utente, occorre avere il privilegio di sistema CREATE
ANY VIEW.
CREAZIONE DI UN DATABASE
La creazione di un database è il processo con cui si rende pronto un database per l’uso iniziale.
Questa operazione comprende la pulizia dei file del database e il caricamento delle tabelle ini-
ziali del database richieste dall’RDBMS. Tutto ciò viene effettuato attraverso l’istruzione SQL
CREATE DATABASE.
CTXCAT, INDICE
Un indice testuale CTXCAT, disponibile in Oracle Text, supporta le query di testo eseguite con
l’operatore CATSEARCH . Per ulteriori informazioni su Oracle Text, si consulti il Capitolo 25.
CUBE
VEDERE ANCHE GROUPING, ROLLUP, Capitolo 12.
SINTASSI
DESCRIZIONE CUBE raggruppa le righe che si basano sui valori di tutte le possibili combina-
zioni di espressioni per ogni riga, e restituisce un’unica riga di informazioni di riepilogo per
ciascun gruppo. L’operazione CUBE può essere utilizzata per creare report a campi incrociati.
Vedere il Capitolo 12.
CUME_DIST
VEDERE ANCHE FUNZIONI DI AGGREGAZIONE.
SINTASSI
Per gli aggregati:
CURRENT_DATE
VEDERE ANCHE DATE, FUNZIONI.
SINTASSI
CURRENT_DATE
DESCRIZIONE CURRENT_DATE restituisce la data corrente nel fuso orario della sessione, con
un valore del calendario Gregoriano del tipo di dati DATE.
ESEMPIO
CURRENT_TIMESTAMP
VEDERE ANCHE DATE, FUNZIONI.
SINTASSI
CURRENT_TIMESTAMP [ ( precisione ) ]
DESCRIZIONE CURRENT_TIMESTAMP restituisce la data e l’ora correnti nel fuso orario della
sessione, con un valore del tipo di dati TIMESTAMP WITH TIME ZONE. Il cambiamento del
fuso orario riflette l’ora locale corrente della sessione SQL. Se si tralascia il parametro relativo
alla precisione, il valore predefinito è 6. La differenza tra questa funzione e LOCALTIMESTAMP
è che CURRENT_TIMESTAMP restituisce un valore TIMESTAMP WITH TIME ZONE, mentre
LOCALTIMESTAMP restituisce un valore TIMESTAMP. precisione specifica la precisione al
secondo frazionario del valore orario restituito.
ESEMPIO
CURRVAL
Vedere PSEUDOCOLONNE.
CURSOR, PL/SQL
VEDERE ANCHE CREATE PACKAGE, CREATE PACKAGE BODY, Capitolo 29.
SINTASSI
CURSORE
Cursore è anche un sinonimo di area di contesto, un’area di lavoro all’interno della memoria in
cui Oracle memorizza l’istruzione SQL corrente. Per una query, l’area in memoria include anche
le intestazioni delle colonne e una riga recuperata dalla query stessa.
CURSORE SQL
VEDERE ANCHE %FOUND, %ISOPEN, %NOTFOUND, %ROWCOUNT, Capitolo 29.
DESCRIZIONE SQL è il nome del cursore implicitamente aperto ogni volta che l’istruzione
SQL elaborata non fa parte di un cursore esplicitamente aperto e nominato (vedere DECLARE).
Ne può esistere solo uno per volta. Gli attributi del cursore %FOUND e %NOTFOUND possono
essere controllati verificando il valore di SQL%FOUND e SQL%NOTFOUND prima o dopo un
inserimento, aggiornamento o cancellazione (che non sono mai associati a cursori espliciti) o
dopo la selezione di una singola riga eseguita senza cursori espliciti.
Per ulteriori dettagli riguardanti queste verifiche, si consulti %FOUND. Per dettagli sui
valori che questi attributi presentano in condizioni differenti, si consulti %ROWCOUNT.
SQL%ISOPEN vale sempre FALSE poiché Oracle chiude il cursore SQL automaticamente dopo
aver eseguito l’istruzione SQL.
CV
SINTASSI
CV([colonna_dimensioni])
DESCRIZIONE CV può essere utilizzato solo nella clausola MODEL di un’istruzione SELECT.
Esso restituisce il valore corrente di una colonna di dimensioni portata dal lato sinistro al lato
destro di una regola per fornire un’indicizzazione relativa rispetto alla colonna di dimensioni.
DATABASE
Database può avere una di queste due definizioni:
■ un insieme di tabelle del dizionario dati e di tabelle dell’utente trattate come un’unità;
■ uno o più file del sistema operativo in cui Oracle memorizza le tabelle, le viste e altri ogget-
ti; inoltre, può essere l’insieme di oggetti del database utilizzati da una certa applicazione.
DATABASE CHIUSO
Un database chiuso è un database associato a un’istanza (il database risulta montato) ma non
aperto. I database inutilizzati vanno chiusi per ridurre il lavoro delle funzioni di gestione del
database. Ciò può essere ottenuto attraverso l’istruzione SQL ALTER DATABASE.
DATABASE DISTRIBUITO
Un database distribuito è una collezione di database che possono essere gestiti separatamente e
condividere informazioni.
DATABASE LINK
Un database link è un oggetto memorizzato nel database locale che identifica un database remo-
to, un percorso di comunicazione al database remoto e, facoltativamente, il nome di un utente e
una password per questo database. Una volta definito, il database link viene utilizzato per ese-
guire query su tabelle nel database remoto. Vedere il Capitolo 22.
DATABASE LOCALE
Un database locale è in genere un database che si trova su un computer host. Vedere per confron-
to DATABASE REMOTO.
DATABASE, NOME
Il nome di un database è un identificatore unico utilizzato per riconoscere un database. Viene
assegnato tramite il comando create database o nel file dei parametri di inzializzazione.
DATABASE, OGGETTO
Un oggetto di database è qualcosa creato e memorizzato in un database. Le tabelle, le viste, i
sinonimi, gli indici, le sequenze, i cluster e le colonne sono tutti tipi di oggetti del database.
1100 CAPITOLO 48
DATABASE REMOTO
Un database remoto è un database che risiede su un computer remoto. Vi si accede attraverso un
database link.
DATAZIONE GIULIANA
La datazione giuliana è un metodo di conversione per cui qualsiasi data può essere espressa
come un unico numero intero. Le date giuliane possono essere ottenute utilizzando la maschera
di formato ‘J’ nelle funzioni i cui argomenti sono date. Vedere DATE, FORMATI.
DATE
DATE è uno tipo di dati standard di Oracle per memorizzare dati relativi alla data e all’ora. Il
formato standard per le date è 22-APR-02. Una colonna DATE può contenere una data e un’ora
comprese tra il primo gennaio del 4712 a.C. e il trentuno dicembre del 9999 d.C.
DATE, FORMATI
VEDERE ANCHE DATE, FUNZIONI; Capitolo 10.
DESCRIZIONE I modelli dei formati di date vengono utilizzati nelle funzioni di conversione. I
componenti dei modelli di date sono elencati nella tabella seguente.
/,-:.; Punteggiatura da incorporare nella visualizzazione per TO_CHAR o ignorata nel formato per TO_DATE.
A.M. o AM Visualizza A.M. o P.M., a seconda dell’ora del giorno con o senza punti.
(segue)
GUIDA DI RIFERIMENTO ALFABETICA 1101
(continua)
FF (1..9) Secondi frazionari; il numero che segue FF specifica il numero di cifre visualizzate nella parte frazionaria
dei secondi.
FM Sopprime gli spazi iniziali e finali; senza FM, tutti i mesi e i giorni sono visualizzati con la medesima
larghezza.
FX Formato esatto: specifica il formato esatto corrispondente all’argomento carattere e il modello del for-
mato di data.
Q Numero di trimestre: 3.
(segue)
1102 CAPITOLO 48
(continua)
W Numero di settimane nel mese, dove la settimana 1 inizia il primo giorno del mese.
WW Numero della settimana nell’anno, dove la settimana 1 inizia il primo giorno dell’anno.
YEAR o SYEAR Anno scritto per esteso: la S contrassegna le date BC con un segno – iniziale.
YYYY o SYYYY Anno scritto per esteso a quattro cifre: la S contrassegna le date BC con un segno – iniziale.
I formati di data seguenti funzionano solo con TO_CHAR. Non funzionano con TO_DATE.
TH Suffisso per un numero: ddTH o DDTH produce 24th o 24TH. Le lettere minuscole o maiuscole dipendo-
no da come viene scritto il numero, DD, non da come viene scritto TH. Funziona con qualsiasi numero di
una data: YYYY, DD, MM, HH, MI, SS e così via.
SP Suffisso per un numero che lo forza a essere scritto per esteso: DDSP, DdSP o ddSP produce THREE,
Three o three. La scrittura maiuscola o minuscola dipende da come è scritto il numero, DD, non da come
sono scritte le lettere SP. Funziona con qualsiasi numero di una data: YYYY, DD, MM, HH, MI, SS e così via.
SPTH Suffisso combinazione di TH e SP che forza un numero a essere sia specificato per esteso che ad avere
un suffisso ordinale. Mspth produce Third. La scrittura maiuscola o minuscola dipende da come è
scritto il numero, DD, non da come sono scritte le lettere SP. Funziona con qualsiasi numero di una data:
YYYY, DD, MM, HH, MI, SS e così via.
DATE, FUNZIONI
VEDERE ANCHE DATE, FORMATI; Capitolo 10.
DESCRIZIONE Questo è un elenco alfabetico di tutte le funzioni di data correnti in SQL di
Oracle. Ciascuna viene riportata altrove in questa guida, assieme alla sintassi e ad esempi d’uso.
■ ADD_MONTHS(conta,data) Somma conta mesi a data.
■ CURRENT_DATE restituisce la data corrente nel fuso orario della sessione.
■ CURRENT_TIMESTAMP Restituisce la data corrente nel fuso orario della sessione.
■ DBTIMEZONE Restituisce il fuso orario corrente del database, in formato UTC.
■ EXTRACT (dataora) Estrae una porzione di una data da un valore data, come l’estrazione
del valore del mese dai valori di una colonna di date.
■ FROM_TZ Converte un valore di indicatore orario in un indicatore orario con il valore di
fuso orario.
GUIDA DI RIFERIMENTO ALFABETICA 1103
■ LAST_DAY(data) Fornisce la data dell’ultimo giorno del mese a cui appartiene data.
■ LOCALTIMESTAMP Restituisce l’indicatore orario nel fuso orario attivo, senza mostrare
informazioni su quest’ultimo.
■ MONTHS_BETWEEN(data2,data1) Fornisce data2–data1 in mesi (può essere un numero
frazionario).
■ NEW_TIME(data,‘questo’, ‘altro’) Fornisce la data (e l’ora) nel fuso orario questo, che de-
v’essere sostituito da un’abbreviazione di tre lettere per indicare il fuso orario corrente. altro
dev’essere sostituito da un’abbreviazione di tre lettere per il fuso orario di cui si desidera cono-
scere la data e l’ora. I fusi orari sono i seguenti:
AST/ADT Standard Atlantico/ora solare.
BST/BDT Standard di Bering/ora solare.
CST/CDT Standard Centrale/ ora solare.
EST/EDT Standard Orientale/ora solare.
GMT Ora di Greenwich.
HST/HDT Standard Alaska-Hawaii/ora solare.
MST/MDT Standard Mountain/ora solare.
NST Tempo standard di Newfoundland.
PST/PDT Standard Pacifico/ora solare.
YST/YDT Standard dello Yukon/ora solare.
■ NEXT_DAY(data,‘giorno’) fornisce la data del giorno successivo a data, dove ‘giorno’ è ‘Lu-
nedì’, ‘Martedì’ e così via.
■ NUMTODSINTERVAL(n,'valore') Converte un numero o un’espressione n in un valore let-
terale INTERVAL DAY TO SECOND dove valore è l’unità di n: 'Day', 'HOUR', 'MINUTE', 'SECOND'.
■ NUMTOYMINTERVAL (n,'valore') Converte un numero o un’espressione in un valore lettera-
le INTERVALLO YEAR TO MONTH dove valore è l’unità di n: 'YEAR', 'MONTH'.
■ ROUND(data,‘formato’) Senza un formato specificato arrotonda una data a 12 A.M. (mezza-
notte, l’inizio del giorno) se l’ora della data è prima di mezzogiorno; altrimenti, l’arrotonda al
giorno successivo. Per l’uso di un formato per l’arrotondamento, si consulti la voce “ROUND”
in questo capitolo.
■ SESSIONTIMEZONE Restituisce il valore del fuso orario della sessione corrente.
■ SYS_EXTRACT_UTC(dataora_con_fusoorario) Estrae Coordinated Universal Time (UTC)
da una data/ora con la differenza di fuso orario.
■ SYSDATE Restituisce la data e ora correnti.
■ SYSTIMESTAMP Restituisce la data di sistema, compresi i secondi frazionari e il fuso
orario del database.
■ TO_CHAR(data,‘formato’) Riformatta la data secondo il formato specificato
■ TO_DATE(stringa,‘formato’) Converte una stringa da un particolare formato in una data
Oracle. Accetta anche un numero al posto di una stringa, con determinati limiti. ‘formato’ è
ristretto
■ TO_DSINTERVAL(‘valore’) Converte il valore di un tipo di dati CHAR, VARCHAR2, NCHAR
o NVARCHAR2 in un tipo INTERVAL DAY TO SECOND.
■ TO_TIMESTAMP(‘valore’) Converte il valore di un tipo di dati CHAR, VARCHAR2, NCHAR
o NVARCHAR2 in un valore di tipo TIMESTAMP.
■ TO_TIMESTAMP_TZ(‘valore’) Converte il valore di un tipo di dati CHAR, VARCHAR2,
NCHAR o NVARCHAR2 in un valore di tipo TIMESTAMP WITH TIMEZONE.
1104 CAPITOLO 48
DATI, FILE
Un file di dati è qualsiasi file utilizzato per memorizzare dei dati in un database. Un database è
composto da una o più tablespace, che a loro volta sono composte da uno o più file di dati.
DATI, INDIPENDENZA
L’indipendenza dai dati è la proprietà di tabelle ben definite che consente di modificare la strut-
tura fisica e logica di una tabella senza che vengano influenzate le applicazioni che vi accedono.
DATI, TIPI
VEDERE ANCHE CARATTERI, FUNZIONI; CONVERSIONE, FUNZIONI; DATE, FUN-
ZIONI; FUNZIONI DI ELENCO, NUMERI, FUNZIONI; ALTRE FUNZIONI.
DESCRIZIONE Quando si crea una tabella e si definiscono le colonne in essa contenute, ciascu-
na colonna deve appartenere a un certo tipo di dati. I tipi di dati principali di Oracle sono
VARCHAR2, CHAR, DATE, LONG, LONG RAW, NUMBER, RAW e ROWID, ma per que-
stioni di compatibilità con gli altri database SQL, le istruzioni create table di Oracle accettano
diverse versioni di questi tipi. La tabella seguente elenca i tipi di dati di Oracle incorporati:
NVARCHAR2(dimensione) Stringa di caratteri a lunghezza variabile con una dimensione massima in byte (fino a 4000) o in carat-
teri, a seconda del set di caratteri nazionali scelto.
NUMBER(dimensione,d) Per colonne NUMBER di dimensione specifica con d cifre dopo il punto decimale. Per esempio,
NUMBER(5,2) non può contenere un valore maggiore di 999.99, altrimenti si verifica un errore.
DATE Intervallo di dati valide dal 1 Gennaio 4712 A.C. al 31 Dicembre 9999 D.C.
TIMESTAMP (precisione) Data più orario, in cui precisione è il numero di cifre nella parte frazionaria del campo dei secondi
(l’intervallo dei valori è da 0 a 9, il valore predefinito è 6).
TIMESTAMP (precisione) TIMESTAMP più il valore relativo al cambio di fuso orario; precisione è il numero di cifre nella parte
WITH TIME ZONE frazionaria del campo dei secondi (l’intervallo dei valori è da 0 a 9, il valore predefinito è 6).
(segue)
GUIDA DI RIFERIMENTO ALFABETICA 1105
(continua)
INTERVAL YEAR Lasso di tempo espresso in anni e mesi, in cui precisione è il numero di cifre nel campo data/ora
(precisione) TO MONTH ANNO (il valore predefinito è 2).
INTERVAL DAY Lasso di tempo espresso in giorni, ore, minuti e secondi in cui precisione_giorno è il numero di cifre
(precisione_giorno) nel campo data/ora GIORNO (il valore predefinito è 2) mentre precisione_secondo è il numero di cifre
TO SECOND nella parte frazionaria del campo dei secondi (l’intervallo dei valori è da 0 a 9, il valore predefinito è 6).
(precisione_secondo)
RAW(dimensione) Dati binari di tipo RAW, lunghi un numero di byte pari a dimensione. La dimensione massima è 255 byte.
ROWID Stringa a base 64 Valore che rappresenta l’indirizzo univoco di una riga nella sua tabella.
INTEGER (dimensione) Stringa a base 64 per l’indirizzo logico di una riga in una tabella di solo indice; la dimensione massima è
di 4000 byte.
CHAR(dimensione) Dati carattere a lunghezza fissa, pari a dimensione. La dimensione massima è 2000. Quella predefinita è
di 1 byte. Riempito a destra con spazi vuoti per raggiungere la lunghezza prefissata.
DBTIMEZONE
VEDERE ANCHE DATE, FUNZIONI.
SINTASSI
DBTIMEZONE
DBWR, PROCESSO
Uno dei processi di background utilizzati da Oracle. Il processo Database Writer scrive nuovi
dati nel database. Viene definito anche come DBWn.
1106 CAPITOLO 48
DCL
Vedere ISTRUZIONI DEL LINGUAGGIO DI CONTROLLO DEI DATI (DCL DATA CONTROL
LANGUAGE).
DDL
Vedere ISTRUZIONI DEL LINGUAGGIO DI DEFINIZIONE DEI DATI (DDL DATA
DEFINITION LANGUAGE).
DDL, BLOCCO
Quando un utente esegue un comando DDL, Oracle blocca gli oggetti cui si fa riferimento nel
comando con blocchi di DDL. Un blocco DDL blocca gli oggetti nel dizionario dati (si confronti
questo tipo di blocco con i blocchi di analisi, ovvero gli altri tipi di blocchi nel dizionario dati).
DEADLOCK
Un deadlock è una situazione rara che si riscontra quando due o più processi utente di un database
non riescono a completare le proprie transazioni. Ciò accade perché ciascun processo trattiene
una risorsa che l’altro richiede (come una riga in una tabella) per poter terminare il processo.
Nonostante queste situazioni accadano di raro, Oracle rileva e risolve i deadlock eseguendo un
rollback del lavoro di uno dei processi.
DECLARE
Il comando DECLARE consente di dichiarare cursori, variabili ed eccezioni da utilizzare all’in-
terno dei blocchi PL/SQL. Vedere il Capitolo 29.
DESCRIZIONE Un cursore è un’area di lavoro che Oracle utilizza per controllare la riga attual-
mente elaborata. DECLARE CURSOR assegna un nome a un cursore e dichiara che esso è (IS) il
risultato di una certa istruzione_select. L’istruzione_select è necessaria e può anche non conte-
nere una clausola INTO. Il cursore deve essere dichiarato. A questo punto, può essere aperto
(OPEN) ed è possibile eseguire l’operazione di FETCH delle righe all’interno di esso. Infine,
può essere chiuso (CLOSE).
Le variabili non possono essere utilizzate direttamente nella clausola WHERE dell’istru-
zione_select, a meno che non siano state prima identificate come parametri, in un elenco che
precede la selezione. Si osservi che DECLARE CURSOR non esegue l’istruzione select e i para-
metri non possiedono valori fino a che non vengono assegnati in un’istruzione OPEN. I parame-
tri hanno nomi di oggetti standard e tipi di dati, inclusi VARCHAR2, CHAR, NUMBER, DATE e
BOOLEAN, tuttavia tutti senza dimensione o scala.
FOR UPDATE OF è richiesto nel caso si desideri modificare la riga corrente all’interno del
cursore utilizzando il comando update o il comando delete con la clausola CURRENT OF.
DECLARE TABLE
VEDERE ANCHE CREATE TABLE, Programmer’s Guide to Oracle Precompilers.
SINTASSI
DESCRIZIONE tabella è il nome della tabella da dichiarare. colonna è il nome di una colonna e
tipodato è il suo tipo di dati. Questa struttura è praticamente identica a quella di create table,
compreso l’uso di NULL e NOT NULL.
Si utilizza DECLARE TABLE per comunicare ai precompilatori di ignorare le definizioni
delle tabelle reali del database Oracle quando si esegue un’esecuzione con SQLCHECK=FULL.
In questo caso, i precompilatori considereranno la descrizione della tabella come rilevante per il
programma e ignoreranno le definizioni delle tabelle nel database. Si utilizzi questa soluzione
quando le definizioni delle tabelle cambiano, oppure quando una tabella non è ancora stata crea-
ta. Se SQLCHECK non è uguale a FULL (il che significa che le tabelle e le colonne non vengono
comunque controllate nel database), questo comando viene ignorato dal precompilatore e diven-
ta semplicemente una documentazione.
ESEMPIO
DECODE
VEDERE ANCHE ALTRE FUNZIONI, CASE, TRANSLATE, Capitolo 16.
SINTASSI
DECODE(valore,if1,then1[,if2,then2,]... ,else)
DESCRIZIONE valore rappresenta qualsiasi colonna in una tabella, a prescindere dal tipo di
dati, o qualsiasi risultato di un’operazione di calcolo, quale la sottrazione di una data da un’altra,
una SUBSTR di una colonna di caratteri, un numero moltiplicato un altro e così via. Per ciascuna
riga viene controllato valore. Se è uguale a if1, il risultato di DECODE è uguale a then1; se il
valore è uguale a if2, il risultato di DECODE risulta uguale a then2 e così via, per tutti gli if/then
GUIDA DI RIFERIMENTO ALFABETICA 1109
che si riesce a costruire. Se valore non è uguale a nessuno degli if, il risultato di DECODE è else.
Ciascuno degli if, then e else può essere una colonna o il risultato di una funzione o di un calcolo.
Il Capitolo 16 è interamente dedicato a DECODE.
ESEMPIO
DECOMPOSE
VEDERE ANCHE CONVERSIONE, FUNZIONI.
SINTASSI
DECOMPOSE (“stringa”)
DESCRIZIONE DECOMPOSE traduce una stringa in qualunque tipo di dati in una stringa
UNICODE dopo la sua scomposizione canonica nel medesimo set di caratteri della stringa di
input.
DEFAULT
Default è una clausola o il valore di un’opzione che viene utilizzato se non si specifica nessun’al-
tra alternativa. Si può specificare il valore predefinito per una colonna di una tabella tramite il
vincolo di colonna DEFAULT.
DEFINE (SQL*PLUS)
Vedere SET, EDIT.
SINTASSI
DESCRIZIONE variable è una variabile utente o predefinita di cui si desidera assegnare o elencare
il valore. testo è il nuovo valore della variabile; dev’essere un valore CHAR e dev’essere racchiuso
tra apici singoli se contiene segni di punteggiatura o spazi. DEFINE senza una variabile elencherà
tutte le variabili.
Le variabili che seguono sono quelle predefinite da Oracle per ciascuna sessione:
VARIABILE DESCRIZIONE
_CONNECT_IDENTIFIER Identificatore di connessione utilizzato per realiazzare la connessione corrente.
(segue)
1110 CAPITOLO 48
(continua)
DEL (SQL*Plus)
VEDERE ANCHE APPEND, CHANGE, EDIT, INPUT, LIST, Capitolo 6.
SINTASSI
DEL
DESCRIZIONE DEL elimina la linea corrente del buffer attivo in quel momento. Con un unico
comando DEL si possono cancellare più righe.
ESEMPIO
del
del 2 8
del 4*
where_clause returning_clause
;
DML_table_expression_clause::=
PARTITION ( partition )
SUBPARTITION ( subpartition )
@ dblink
schema . table
view @ dblink
materialized view
subquery_restriction_clause
( subquery )
table_collection_expression
subquery_restriction_clause::=
READ ONLY
WITH CONSTRAINT constraint
CHECK OPTION
table_collection_expression::=
( + )
TABLE ( collection_expression )
where_clause::=
WHERE condition
returning_clause::=
, ,
DESCRIZIONE DELETE elimina da tabella tutte le righe che soddisfano condizione. La condi-
zione può includere una query correlata e utilizzare l’alias per la correlazione. Se la tabella è
remota, si deve definire preventivamente un database link. In tal caso, @link ne specifica il
nome. Se si specifica link ma non utente, la query cerca una tabella di proprietà dello stesso
utente sul database remoto.
Quando si usa il commando DELETE, si può specificare una partizione o una partizione
secondaria. Per cancellare le righe da una tabella, è necessario disporre dei privilegi DELETE
sulla tabella. Se il parametro di inizializzazione SQL92_SECURITY è impostato a TRUE, si
deve disporre anche dei privilegi SELECT se DELETE si riferisce a colonne nella tabella.
ESEMPIO
Nell’esempio seguente, vengono eliminate tutte le righe della città di Keene dalla tabella
COMFORT:
SINTASSI
DESCRIZIONE Questa forma del comando DELETE consente di eliminare righe (da una tabel-
la, una vista o una tabella di solo indice) dall’interno di un programma di precompilatore.
DENSE_RANK
VEDERE ANCHE FUNZIONI DI GRUPPO, Capitolo 12.
SINTASSI
DESCRIZIONE DENSE_RANK calcola l’ordine di una riga in un gruppo ordinato di righe. Per
esempi correlati, si consulti il Capitolo 13.
DEPTH
SINTASSI
DEPTH(intero)
GUIDA DI RIFERIMENTO ALFABETICA 1113
DESCRIZIONE DEPTH è una funzione ausiliaria utilizzata solo con le condizioni UNDER_PATH
ed EQUALS_PATH conditions. Restituisce il numero di livelli nel percorso specificato dalla
condizione UNDER_PATH con la stessa variabile di correlazione. Il valore intero può esse un
qualunque numero intero.
DEREF
L’operatore DEREF restituisce il valore di un oggetto di riferimento. Vedere il Capitolo 36.
DESC[RIBE] [utente.]tabella
describe COMFORT
DIMENSIONE
Una dimensione è un insieme specifico di gerarchie tra le colonne delle tabelle. Per esempio,
nella dimensione geografia, i Paesi fanno parte dei continenti e gli Stati fanno parte dei Paesi.
1114 CAPITOLO 48
Quando si definiscono le relazioni tra le dimensioni, Oracle potrà utilizzare queste informazioni
quando valuta le opzioni dell’ottimizzatore. Se esistono viste materializzate che contengono dati
aggregati, l’ottimizzatore potrà usare le definizioni delle dimensioni per stabilire se è possibile
accedere alla vista materializzata invece che alla tabella di base. Vedere CREATE DIMENSION.
DIRECTORY
Un nome logico che punta a una directory fisica, utilizzata dai LOB di BFILE e dalle tabelle
esterne. Vedere CREATE DIRECTORY e il Capitolo 26.
DISASSOCIATE STATISTICS
VEDERE ANCHE ASSOCIATE STATISTICS.
SINTASSI
disassociate_statistics::=
schema .
COLUMNS table . column
schema .
FUNCTIONS function
schema .
PACKAGES package
FORCE
,
;
schema .
TYPES type
schema .
INDEXES index
schema .
INDEXTYPES indextype
DESCRIZIONE ASSOCIATE STATISTICS associa un set di funzioni statistiche con una o più
colonne, funzioni standalone, package, tipi o indici. DISASSOCIATE STATISTICS revoca le
associazioni. Si deve disporre del privilegio ALTER sull’oggetto di base.
GUIDA DI RIFERIMENTO ALFABETICA 1115
DISCONNECT
VEDERE ANCHE CONNECT, EXIT, QUIT.
SINTASSI
DISC[ONNECT]
DISTINCT
Distinct significa unico. Viene utilizzato all’interno di costrutti select e funzioni di gruppo. Ve-
dere le parti relative alle FUNZIONI DI GRUPPO e al costrutto SELECT.
DIZIONARIO, BLOCCHI
Un blocco relativo a un dizionario è un blocco condiviso posseduto da utenti che analizzano
istruzioni DML, oppure un blocco esclusivo di proprietà degli utenti che eseguono comandi
DDL, per evitare che una tabella venga alterata mentre si eseguono query sui dizionari. Possono
esistere più blocchi di questo tipo contemporaneamente.
DIZIONARIO, CACHE
La cache del dizionario memorizza le informazioni del dizionario dati nella SGA. Le informa-
zioni del dizionario presenti nella cache migliorano le prestazioni, in quanto le informazioni del
dizionario vengono utilizzate di frequente. La cache del dizionario dati fa parte dello Shared
SQL Pool.
DIZIONARIO DATI
Il dizionario dati rappresenta un insieme completo delle tabelle e delle viste di proprietà degli
utenti SYS e SYSTEM del DBA, che viene attivato la prima volta che si installa Oracle ed è una
fonte centrale di informazioni per gli RDBMS Oracle e per tutti gli utenti. Le tabelle vengono
gestite automaticamente da Oracle e includono un gruppo di viste e tabelle contenenti informa-
zioni relative agli oggetti, agli utenti, ai privilegi, agli eventi e all’utilizzo del database. Vedere il
Capitolo 42.
DML
Vedere ISTRUZIONI DEL LINGUAGGIO DI MANIPOLAZIONE DEI DATI (DML).
1116 CAPITOLO 48
DML LOCK
Quando un utente esegue un’istruzione SQL, i dati cui fa riferimento l’istruzione vengono bloc-
cati in una certa modalità. L’utente può anche bloccare i dati in modo esplicito con un’istruzione
LOCK.
DROP CLUSTER
VEDERE ANCHE CREATE CLUSTER, DROP TABLE, Capitolo 17.
SINTASSI
DESCRIZIONE DROP CLUSTER elimina un cluster dal database. Se il cluster non fa parte del
proprio schema, è necessario possedere il privilegio DROP ANY CLUSTER. Non è possibile
eliminare un cluster che contiene delle tabelle. Per prima cosa, è necessario eliminare le tabelle.
La clausola INCLUDING TABLES cancella automaticamente tutte le tabelle contenute all’interno
dei cluster. L’opzione CASCADE CONSTRAINTS elimina tutti i vincoli di integrità referenziale
dalle tabelle esterne al cluster che però fanno riferimento alle chiavi contenute nelle tabelle
raccolte in cluster.
Non è possibile rimuovere da un cluster le singole tabelle. Per ottenere lo stesso effetto, è
necessario copiare la tabella con un nome nuovo (si utilizzi CREATE TABLE assieme ad AS
SELECT), eliminare la tabella vecchia (rimuovendola così dal cluster), assegnare alla copia lo
stesso nome della tabella appena eliminata (mediante l’istruzione RENAME) quindi concedere i
privilegi opportuni e creare gli indici necessari.
DROP CONTEXT
VEDERE ANCHE CREATE CONTEXT.
SINTASSI
DESCRIZIONE DROP CONTEXT elimina uno spazio di nomi contestuale dal database. Si deve
disporre del privilegio di sistema DROP ANY CONTEXT.
DROP DATABASE
VEDERE ANCHE CREATE DATABASE, Capitolo 46.
SINTASSI
DROP DATABASE ;
DESCRIZIONE DROP DATABASE elimina il database corrente (che dev’essere montato con
MOUNT e chiuso) ed elimina tutti i control file e i file di dati elencati nel control file. Viene
anche eliminato qualunque spfile correlato. I file log archiviati e i backup non vengono rimossi.
Se il database si trova su dischi raw, DROP DATABASE non elimina i file speciali del disco raw.
GUIDA DI RIFERIMENTO ALFABETICA 1117
DESCRIZIONE DROP DATABASE LINK elimina un database link di proprietà dell’utente. Nel
caso si tratti di un collegamento pubblico, è necessario utilizzare la parola chiave facoltativa
PUBLIC, e per usarla occorre essere un DBA. PUBLIC non può essere utilizzata per eliminare un
collegamento privato. collegamento è il nome del collegamento da eliminare. Per poter elimina-
re un database link pubblico, occorre disporre del privilegio di sistema DROP PUBLIC DATABASE
LINK. All’interno del proprio account è possibile eliminare database link privati.
ESEMPIO
La linea seguente elimina un database link di nome SEDE_DI_ADA:
DROP DIMENSION
VEDERE ANCHE CREATE DIMENSION, Capitolo 24.
SINTASSI
DROP DIRECTORY
VEDERE ANCHE CREATE DIRECTORY, Capitoli 22, 26 e 35.
SINTASSI
DESCRIZIONE DROP DIRECTORY elimina una directory già esistente. Per eliminare una
directory è indispensabile avere il privilegio DROP ANY DIRECTORY.
NOTA Non si deve eliminare una directory mentre i suoi file sono in uso.
ESEMPIO
La linea seguente elimina la directory di nome RECENSIONI:
DROP DISKGROUP
VEDERE ANCHE ALTER DISKGROUP, CREATE DISKGROUP, Capitolo 46.
SINTASSI
DROP FUNCTION
VEDERE ANCHE ALTER FUNCTION, CREATE FUNCTION, Capitolo 31.
SINTASSI
DROP INDEX
VEDERE ANCHE ALTER INDEX, CREATE INDEX, CREATE TABLE, Capitoli 17 e 46.
SINTASSI
DROP INDEXTYPE
VEDERE ANCHE CREATE INDEXTYPE.
SINTASSI
DROP JAVA
VEDERE ANCHE CREATE JAVA, Capitolo 37.
GUIDA DI RIFERIMENTO ALFABETICA 1119
SINTASSI
DESCRIZIONE DROP JAVA elimina la classe, la sorgente o la risorsa Java specificata. Si deve
disporre del privilegio di sistema DROP PROCEDURE. Se l’oggetto si trova nello schema di un
altro utente, si deve possedere il privilegio di sistema DROP ANY PROCEDURE.
DROP LIBRARY
VEDERE ANCHE CREATE LIBRARY, Capitolo 31.
SINTASSI
DESCRIZIONE DROP MATERIALIZED VIEW LOG elimina la tabella di log indicata. Per elimi-
nare il log di una vista materializzata si deve disporre dei privilegi necessari per eliminare una
1120 CAPITOLO 48
tabella. Dopo l’eliminazione del log, qualsiasi vista materializzata sulla tabella master verrà
aggiornata completamente, ma non tramite aggiornamenti rapidi.
La parola chiave SNAPSHOT è accettata in sostituzione di MATERIALIZED VIEW per
garantire la compatibilità con le versioni precedenti.
DROP OPERATOR
VEDERE ANCHE ALTER OPERATOR.
SINTASSI
DROP OUTLINE
VEDERE ANCHE CREATE OUTLINE.
SINTASSI
DESCRIZIONE DROP OUTLINE elimina una struttura memorizzata dal database. Si deve pos-
sedere il privilegio di sistema DROP ANY OUTLINE. I percorsi esecutivi delle esecuzioni suc-
cessive di istruzioni SQL, che utilizzavano questa struttura, verranno valutati al momento del-
l’esecuzione.
DROP PACKAGE
VEDERE ANCHE ALTER PACKAGE CREATE PACKAGE, Capitolo 31.
SINTASSI
DROP PROCEDURE
VEDERE ANCHE ALTER PROCEDURE, CREATE PROCEDURE, Capitolo 31.
SINTASSI
DROP PROFILE
VEDERE ANCHE ALTER PROFILE, CREATE PROFILE, Capitolo 18.
SINTASSI
DROP ROLE
VEDERE ANCHE ALTER ROLE, CREATE ROLE, Capitolo 18.
SINTASSI
DESCRIZIONE DROP ROLE elimina il ruolo specificato. Si deve disporre del ruolo WITH
ADMIN OPTION oppure essere in possesso del privilegio di sistema DROP ANY ROLE.
DROP SEQUENCE
VEDERE ANCHE ALTER SEQUENCE, CREATE SEQUENCE, Capitolo 17.
SINTASSI
DROP SYNONYM
VEDERE ANCHE CREATE SYNONYM, Capitolo 23.
SINTASSI
DROP TABLE
VEDERE ANCHE ALTER TABLE, CREATE INDEX, CREATE TABLE, DROP CLUSTER,
Capitolo 17.
SINTASSI
DESCRIZIONE DROP TABLE elimina la tabella specificata. Per eliminare una tabella è necessa-
rio esserne il proprietario o possedere il privilegio di sistema DROP ANY TABLE. Quando viene
eliminata una tabella, di fatto vengono soppressi anche tutti gli indici e le concessioni a essa
associati. Gli oggetti contenuti in tabelle in corso di cancellazione vengono marcati come non
validi e cessano di funzionare.
L’opzione CASCADE CONSTRAINTS elimina tutti i vincoli di integrità referenziale che
fanno riferimento alle chiavi della tabella in corso di cancellazione.
È possibile eliminare un cluster con tutte le tabelle relative utilizzando la clausola INCLUDING
TABLES del comando DROP CLUSTER.
A partire da Oracle Database 10g, l’uso dell’istruzione DROP TABLE sposta una tabella o
una tabella di oggetti nel cestino o rimuove interamente la tabella e tutti i suoi dati dal database.
A meno di specificare la clausola PURGE, l’istruzione DROP TABLE non produce la restituzione
dello spazio alla tablespace perché lo utilizzi per altri oggetti; lo spazio pertanto continua a
contribuire alla quota di spazio dell’utente. Gli oggetti possono essere eliminati automaticamente
dal cestino se la tablespace esaurisce lo spazio a disposizione per i nuovi oggetti.
DROP TABLESPACE
VEDERE ANCHE ALTER TABLESPACE, CREATE DATABASE, CREATE TABLESPACE,
Capitoo 46.
SINTASSI
DROP TRIGGER
VEDERE ANCHE ALTER TRIGGER, CREATE TRIGGER, Capitoli 30 e 33.
SINTASSI
DROP TYPE
VEDERE ANCHE CREATE TYPE, Capitolo 33.
SINTASSI
DESCRIZIONE DROP TYPE elimina la specifica e il corpo di un tipo di dati astratto. Si deve
possedere il tipo o disporre del privilegio di sistema DROP ANY TYPE. Non è possibile elimi-
nare un tipo se una tabella o qualsiasi altro oggetto vi sta ancora facendo riferimento.
DESCRIZIONE DROP TYPE BODY elimina il corpo del tipo di dati specificato. È necessario
esserne il proprietario o disporre del privilegio di sistema DROP ANY TYPE.
DROP USER
VEDERE ANCHE ALTER USER, CREATE USER, Capitolo 18.
SINTASSI
DESCRIZIONE DROP USER elimina l’utente specificato. Si deve disporre del privilegio di
sistema DROP USER. L’opzione CASCADE elimina tutti gli oggetti nello schema dell’utente
1124 CAPITOLO 48
DROP VIEW
VEDERE ANCHE CREATE SYNONYM, CREATE TABLE, CREATE VIEW, Capitolo 17.
SINTASSI
DESCRIZIONE DROP VIEW elimina la vista specificata. La vista da eliminare deve essere di
proprietà dell’utente, oppure questi deve possedere il privilegio di sistema DROP ANY VIEW.
DROPJAVA
DROPJAVA è una utility che serve per rimuovere le classi Java dal database. Vedere LOADJAVA.
DUAL
VEDERE ANCHE FROM, SELECT, Capitolo 10.
DESCRIZIONE DUAL è una tabella costituita da una sola riga e da una sola colonna. Dato che la
maggior parte delle funzioni di Oracle opera sia sulle colonne sia sui letterali, è possibile dimo-
strare alcune delle sue funzionalità usando semplicemente i letterali o le pseudocolonne. In tal
caso, l’istruzione SELECT non verifica quali colonne sono contenute nella tabella e una sola riga
è più che sufficiente per la dimostrazione di un punto.
ESEMPIO
L’esempio seguente mostra l’utente e la data di sistema correnti:
DUMP
VEDERE ANCHE RAWTOHEX.
SINTASSI
DESCRIZIONE DUMP visualizza il valore di stringa nel formato interno, in ASCII, in notazione
ottale, decimale, esadecimale o in formato carattere. formato vale per default ASCII o EBCDIC,
a seconda della macchina; 8 produce la notazione ottale, 10 quella decimale, 16 quella esadecimale
mentre 17 rappresenta la modalità carattere (analoga ad ASCII o EBCDIC). inizio rappresenta la
posizione iniziale all’interno della stringa, mentre lunghezza è il numero di caratteri da visua-
lizzare. stringa può essere un qualsiasi valore letterale o un’espressione.
ESEMPIO
L’esempio seguente mostra come rappresentare in formato esadecimale i caratteri dal primo
all’ottavo per il valore Città della prima riga della tabella COMFORT:
GUIDA DI RIFERIMENTO ALFABETICA 1125
CITTA DUMP(CITTA,16,1,8)
------------- --------------------------------------
SAN FRANCISCO Typ=1 Len= 13: 53,41,4e,20,46,52,41,4e
ECHO (SQL*Plus)
Vedere SET.
EDIT
VEDERE ANCHE DEFINE, SET, Capitolo 6.
SINTASSI
EDIT [file[.est]]
DESCRIZIONE EDIT chiama un editor di testo esterno standard e gli passa come argomento il
nome del file. Se si omette est, viene aggiunta per default l’estensione ‘SQL’. Se si omettono sia
file sia est, viene chiamato l’editor e gli viene passato il nome di un file (inventato da SQLPLUS).
Questo file include il contenuto del buffer corrente. La variabile utente locale _EDITOR deter-
mina quale editor di testo debba essere utilizzato da EDIT. _EDITOR può essere modificata
mediante DEFINE, operazione che in genere viene eseguita al meglio all’interno del file
LOGIN.SQL che viene letto ogni volta che si invoca SQL*PLUS.
EDIT provoca la visualizzazione di un messaggio di errore se il buffer corrente è vuoto e se
EDIT viene chiamato senza un nome di file. È possibile utilizzare il comando SET EDITFILE per
impostare il nome predefinito del file creato dal comando EDIT.
ELABORAZIONE DISTRIBUITA
L’elaborazione distribuita è una computazione effettuata su diverse CPU per ottenere un singolo
risultato.
EMBEDDED (SQL*Plus)
Vedere SET.
EMPTY_BLOB
VEDERE ANCHE Capitolo 35.
SINTASSI
EMPTY_BLOB()
1126 CAPITOLO 48
DESCRIZIONE EMPTY_BLOB restituisce un locator LOB vuoto che può essere utilizzato per
inizializzare una variabile LOB o, in un’istruzione INSERT o UPDATE, per inizializzare una
colonna di tipo LOB o un attributo a EMPTY. EMPTY significa che il LOB è inizializzato ma
non ancora popolato con i dati.
ESEMPIO
EMPTY_CLOB
VEDERE ANCHE Capitolo 35.
SINTASSI
EMPTY_CLOB()
DESCRIZIONE EMPTY_CLOB restituisce un locator LOB vuoto che può essere utilizzato per
inizializzare una variabile LOB o, in un’istruzione INSERT o UPDATE, per inizializzare una
colonna di tipo LOB o un attributo a EMPTY. EMPTY significa che il LOB è inizializzato ma
non ancora popolato con i dati.
ESEMPIO
END
VEDERE ANCHE BEGIN; BLOCCO, STRUTTURA; Capitolo 29.
SINTASSI
DESCRIZIONE END non ha alcuna relazione con le istruzioni END IF ed END LOOP. Per
ulteriori dettagli al riguardo, si consulti IF e LOOP.
END è l’istruzione di chiusura della sezione eseguibile di un blocco PL/SQL (e del blocco
intero). Se nell’istruzione BEGIN è stato assegnato un nome al blocco, questo deve necessaria-
mente seguire anche la parola END. Tra BEGIN ed END è richiesta la presenza di almeno un’istru-
zione eseguibile. Per ulteriori informazioni, si consulti la voce BLOCCO, STRUTTURA e i
Capitoli 29 e 31.
ENQUEUE
L’enqueue (accodamento) è un meccanismo di limitazione degli accessi di una particolare risor-
sa. Gli utenti o i processi in attesa della disponibilità della risorsa in questione non hanno ancora
ottenuto l’enqueue. La maggior parte delle risorse contenute nei database consente l’utilizzo di
questo meccanismo.
ENTITÀ
Un’entità è una persona, un luogo o una cosa rappresentata da una tabella. In una tabella, ogni
riga rappresenta un’occorrenza di questa entità.
GUIDA DI RIFERIMENTO ALFABETICA 1127
ENTITÀ-RELAZIONI, MODELLO
Un modello entità-relazioni è una struttura utilizzata nella realizzazione di modelli di sistemi per
un database. Questo modello divide tutti gli elementi di un sistema in due categorie: le entità e le
relazioni.
EQUI-JOIN
Un equi-join è un join in cui l’operatore di confronto è un simbolo di uguaglianza. Per esempio:
ESADECIMALE, NOTAZIONE
La notazione esadecimale è un sistema di numerazione in cui viene utilizzata la base 16 al posto
della tradizionale base 10. I numeri tra 10 e 15 sono rappresentati con le lettere dalla A alla F.
Questo sistema viene utilizzato spesso per visualizzare i dati interni memorizzati nei sistemi di
elaborazione.
ESCAPE (SQL*PLUS)
Vedere SET.
ESPRESSIONE
Un’espressione è un qualsiasi tipo di colonna. Il suo contenuto può essere un valore letterale,
una variabile, un calcolo matematico, una funzione o una qualsiasi combinazione dei tipi appena
enunciati; il risultato finale deve comunque essere un singolo valore, per esempio una stringa, un
numero o una data.
ESPRESSIONE LOGICA
Un’espressione logica è un’espressione che può assumere due soli valori: TRUE o FALSE. È un
sinonimo di condizione.
EXCEPTION
VEDERE ANCHE BLOCCO, STRUTTURA; DECLARE EXCEPTION; RAISE; Capitolo 29.
SINTASSI
EXCEPTION
{WHEN {OTHERS | eccezione [OR eccezione]...}
THEN istruzione; [istruzione;]...}
[ WHEN {OTHER | eccezione [OR eccezione]...}
THEN istruzione; [istruzione;]...]...
DESCRIZIONE La sezione EXCEPTION di un blocco PL/SQL è quella cui passa il controllo del
programma quando viene identificato un flag di eccezione. Questi possono essere definiti dal-
1128 CAPITOLO 48
l’utente o far parte delle eccezioni di sistema sollevate automaticamente da PL/SQL. Per ulterio-
ri informazioni sui flag di eccezione definibili dall’utente, si consulti RAISE. I flag di eccezione
del sistema sono tutti variabili BOOLEAN (che possono essere TRUE oppure FALSE). L’opzio-
ne WHEN viene impiegata per la loro valutazione. Per esempio, il flag NOT_LOGGED_ON
viene sollevato quando si cerca di impartire un comando a Oracle senza aver effettuato l’accesso
al sistema. Non è necessario dichiarare questo tipo di eccezione o sollevarne il flag. PL/SQL
gestisce questa ed altre condizioni automaticamente.
All’atto dell’attivazione di un flag di eccezione, il programma si arresta immediatamente e
il flusso dell’esecuzione passa alla sezione EXCEPTION del blocco corrente. Tuttavia, questa
sezione non sa automaticamente quale flag di eccezione sia stato sollevato e non sa neanche cosa
fare. Per questo motivo, occorre codificare prima la sezione EXCEPTION per controllare tutti i
flag di eccezione che potrebbero essersi verificati, quindi impartire istruzioni per ciascuno. Que-
sto è quanto viene svolto dal costrutto logico WHEN...THEN. È possibile utilizzare WHEN
OTHERS come catch-all per gestire tutti gli errori inattesi per i quali non sono state dichiarate
eccezioni.
ESEMPIO
Nell’esempio che segue, viene valutato un flag di eccezione all’interno di una sezione EXCEPTION.
Il flag ZERO_DIVIDE viene sollevato quando si cerca di dividere per zero.
declare
pi constant NUMBER(9,7) := 3.1415927;
raggio INTEGER(5);
area NUMBER(14,2);
una_variabile NUMBER(14,2);
begin
raggio := 3;
loop
una_variabile := 1/(raggio-4);
area := pi*power(raggio,2);
insert into AREE values (raggio, area);
raggio := raggio+1;
exit when area >100;
end loop;
exception
when ZERO_DIVIDE
then insert into AREE values (0,0);
end;
ACCESS_INTO_NULL Il programma cerca di assegnare dei valori agli attributi di un oggetto non inizializzato (automaticamente
nullo).
CASE_NOT_FOUND Nessuna delle opzioni nelle clausole WHEN di un’istruzione CASE è stata selezionata, e non esiste una
clausola ELSE.
COLLECTION_IS_NULL Il programma cerca di applicare metodi di collezione diversi da EXISTS a una tabella annidata o un array
variabile non inizializzati (automaticamente nulli), oppure il programma cerca di assegnare dei valori agli
elementi di una tabella annidata o di un array variabile non inizializzati.
CURSOR_ALREADY_OPEN Il programma cerca di aprire un cursore già aperto. Prima di poter essere riaperto, un cursore deve
essere stato chiuso. Un ciclo FOR a cursore apre automaticamente il cursore cui fa riferimento. Quindi,
il programma non è in grado di aprire questo cursore all’interno del ciclo.
(segue)
GUIDA DI RIFERIMENTO ALFABETICA 1129
(continua)
DUP_VAL_ON_INDEX Il programma cerca di memorizzare valori duplicati nella colonna di un database che è vincolata da un
indice unico.
INVALID_CURSOR Il programma cerca di eseguire un’operazione di cursore non valida, come la chiusura di un cursore già
chiuso.
INVALID_NUMBER In un’istruzione SQL, la conversione di una stringa di caratteri in un numero non riesce perché la stringa
non rappresenta un numero valido (nelle istruzioni procedurali, viene sollevata VALUE_ERROR). Questa
eccezione viene sollevata anche quando l’espressione della clausola LIMIT in un’istruzione FETCH di
tipo bulk non è valutata a un numero positivo.
LOGIN_DENIED Il programma cerca di collegarsi a Oracle con un nome utente e/o una password non validi.
NO_DATA_FOUND Un’istruzione SELECT INTO non restituisce righe, oppure il programma fa riferimento a un elemento
cancellato in una tabella annidata o ad un elemento non inizializzato in una tabella a indice. Le funzioni di
aggregazione SQL, come AVG e SUM, restituiscono sempre un valore oppure un valore NULL. Pertanto,
un’istruzione SELECT INTO che chiama una funzione di aggregazione non solleva mai una
NO_DATA_FOUND. Solitamente, l’istruzione FETCH non restituisce righe, pertanto, quando questa situa-
zione si verifica, non viene sollevata alcuna eccezione.
ROWTYPE_MISMATCH La variabile host del cursore e la variabile del cursore PL/SQL coinvolte in un assegnamento hanno tipi di
restituzione incompatibili. Per esempio, quando una variabile host del cursore aperta viene passata a un
sottoprogramma memorizzato, i tipi di restituzione dei parametri effettivi e di quelli formali devono esse-
re compatibili.
SELF_IS_NULL Il programma cerca di chiamare un metodo MEMBER in un’istanza NULL. In altre parole, il parametro
incorporato SELF (che è sempre il primo parametro passato a un metodo MEMBER) è NULL.
SUBSCRIPT_BEYOND Il programma fa riferimento a un elemento di una tabella nidificata o di un array variabile con un numero
_COUNT di indice maggiore del numero di elementi nella collezione.
SUBSCRIPT_OUTSIDE Il programma fa riferimento a un elemento di una tabella nidificata o di un array variabile con un numero
_LIMIT di indice (per esempio, –1) che non rientra nell’intervallo valido.
SYS_INVALID_ROWID La conversione di una stringa di caratteri in un valore di Rowid universale non riesce perché la stringa di
caratteri non rappresenta un valore di Rowid valido.
VALUE_ERROR Si verifica un errore in un’operazione aritmetica, in una conversione, in un troncamento oppure di vincolo
di dimensione. Per esempio, quando il programma seleziona il valore di una colonna in una variabile
carattere, se il valore è più lungo della lunghezza dichiarata della variabile, PL/SQL interrompe l’assegna-
mento e solleva una VALUE_ERROR. Nelle istruzioni procedurali, viene sollevata una VALUE_ERROR se
la conversione di una stringa di caratteri in un numero non riesce (nelle istruzioni SQL, viene sollevata
INVALID_NUMBER).
I numeri di errore e i valori del codice SQL impostati in Oracle sono i seguenti:
(segue)
1130 CAPITOLO 48
(continua)
DUP_VAL_ON_INDEX ORA-00001 -1
OTHERS è l’opzione che permette di gestire tutti i flag di eccezione non valutati nella sezio-
ne EXCEPTION. Dev’essere sempre l’ultima istruzione WHEN a comparire e deve rimanere da
sola. Non può essere inclusa in altre eccezioni.
La gestione delle eccezioni, specie quando si tratta di eccezioni dichiarate dall’utente, do-
vrebbe limitarsi agli errori irreversibili, ovvero quelli che provocano l’arresto della normale
elaborazione.
Se viene attivato un flag di eccezione che non è stato controllato all’interno del blocco
corrente, il programma salta alla sezione EXCEPTION del blocco via via più esterno, fino a che
non trova l’eccezione sollevata, oppure il controllo torna al programma principale.
Le sezioni EXCEPTION possono riferirsi alle variabili nello stesso modo in cui lo fanno i
blocchi dell’esecuzione. In altre parole, possono fare un riferimento diretto alle variabili locali o
alle variabili prese da altri blocchi facendole precedere dal nome del blocco in cui sono state
definite.
Si presti particolare attenzione quando si controllano alcuni tipi di eccezioni. Per esempio,
se la sezione EXCEPTION accetta il messaggio di errore e lo inserisce in una tabella del database,
un’eccezione NOT_LOGGED_ON farebbe entrare la sezione EXCEPTION in un ciclo infinito.
Si progettino le istruzioni che seguono THEN in modo da non rigenerare l’errore che si sta
GUIDA DI RIFERIMENTO ALFABETICA 1131
gestendo in un certo momento. È possibile utilizzare l’istruzione RAISE senza specificare alcun
nome di eccezione. In questo modo, il controllo passa automaticamente alla sezione di gestione
delle eccezioni del blocco più esterno, o al programma principale. Per ulteriori dettagli, si con-
sulti RAISE.
EXCEPTION_INIT
VEDERE ANCHE DECLARE EXCEPTION, EXCEPTION, SQLCODE, Programmer’s Guide
to Oracle Precompilers..
SINTASSI
DECLARE
qualche_spiacevole_errore exception;
pragma exception_init(qualche_spiacevole_errore, -660);
BEGIN
...
EXCEPTION
when qualche_spiacevole_errore
then ...
END;
EXECUTE
VEDERE ANCHE CALL, CREATE PROCEDURE, CREATE FUNCTION, CREATE
PACKAGE, CREATE PACKAGE BODY, GRANT, Capitolo 31.
SINTASSI
DESCRIZIONE EXECUTE esegue una procedura, un package o una funzione. Per eseguire un
procedura all’interno di un package, è necessario specificare sia il nome del package sia quello
della procedura sulla linea di comando, come risulta dall’esempio seguente. In questo esempio,
1132 CAPITOLO 48
DESCRIZIONE intero è una variabile host che serve per limitare il numero di iterazioni quando
la clausola where utilizza degli array. id_istruzione è l’identificativo per un’istruzione insert,
delete o update pronta per essere eseguita (select non è ammessa). L’opzione USING introduce
un elenco di sostituzioni a livello di variabili host delle istruzioni eseguite precedentemente.
EXISTS
VEDERE ANCHE ANY, ALL, IN, NOT EXISTS, Capitolo 13.
SINTASSI
select...
where EXISTS (select...)
DESCRIZIONE EXISTS restituisce true in una clausola where se la subquery che la segue resti-
tuisce almeno una riga. La clausola select nella subquery può essere una colonna, un letterale
oppure un asterisco, non è importante (le convenzioni consigliano l’impiego di un asterisco o di
una lettera ‘x’).
Molti programmatori preferiscono EXISTS a ANY e ALL in quanto risulta più semplice da
ricordare e comprendere. Inoltre, la maggior parte delle formule gestibili con ANY e ALL può
essere ricostruita con EXISTS.
ESEMPIO
La query mostrata nell’esempio seguente si serve di EXISTS per elencare dalla tabella BIBLIO-
TECA tutti gli editori i cui libri sono stati presi in prestito:
select Editore
from BIBLIOTECA B
where EXISTS
(select 'x' from BIBLIOTECA_PRESTITO
where BIBLIOTECA_PRESTITO.Titolo = B.Titolo);
EXISTSNODE
VEDERE ANCHE Capitolo 47.
SINTASSI
DESCRIZIONE Senza nessuna di queste opzioni, EXIT esce semplicemente dal ciclo in corso e
sposta il controllo all’istruzione immediatamente successiva al ciclo. Se ci si trova in un ciclo
annidato, è possibile uscire da qualsiasi livello del ciclo specificando il nome di quest’ultimo. Se
si specifica una condizione, si potrà uscire dal ciclo quando la condizione risulta TRUE. Al-
1134 CAPITOLO 48
l’uscita, qualsiasi cursore eventualmente aperto all’interno del ciclo viene chiuso automatica-
mente.
DESCRIZIONE EXIT termina una sessione SQL*PLUS e riporta l’utente al sistema operativo, al
programma chiamante o al menu principale. A meno che ROLLBACK non sia stato specificato,
EXIT conclude qualsiasi operazione aperta sul database. Viene restituito anche un codice di ritor-
no. SUCCESS, FAILURE e WARNING hanno valori che sono specifici per ogni sistema operati-
vo; FAILURE e WARNING possono essere uguali su alcuni sistemi operativi.
intero è un valore che si può restituire esplicitamente come codice di ritorno; variabile
permette di impostare questo valore dinamicamente. Si può trattare di una variabile definita
dall’utente oppure di una variabile di sistema come sql.sqlcode, che contiene sempre il codice
SQL dell’ultima istruzione SQL eseguita in SQL*PLUS o in un blocco PL/SQL incorporato.
EXP
VEDERE ANCHE LN; NUMERI, FUNZIONI; Capitolo 9.
SINTASSI
EXP(n)
EXPLAIN PLAN
VEDERE ANCHE Capitolo 43.
SINTASSI
DESCRIZIONE nome identifica la spiegazione di questo piano per questa istruzione quando
appare nella tabella di output, e segue le normali convenzioni di denominazione degli oggetti. Se
nome non viene specificato, la colonna STATEMENT_ID della tabella risulta NULL. tabella è il
nome della tabella di output in cui devono comparire le informazioni relative al piano. La tabella
dev’essere creata prima dell’esecuzione della procedura. Il file di avvio UTLXPLAN.SQL con-
tiene il formato da utilizzare e può essere impiegato per creare la tabella prededfinita (chiamata
PLAN_TABLE). Se non si specifica il parametro tabella, EXPLAIN PLAN utilizza PLAN_TABLE.
istruzione_sql è il testo semplice di una qualsiasi istruzione SELECT, INSERT, UPDATE o DELETE
per la quale si desidera esaminare il piano di esecuzione di Oracle.
GUIDA DI RIFERIMENTO ALFABETICA 1135
EXPORT
Esportare significa usare una delle utility di Oracle per scrivere i dati della tabella selezionata in
un file per recuperarli in un secondo tempo con una utility di importazione. Le utility di
esportazione sono due: Export e and Data Pump Export. Data Pump Export è disponibile a
partire da Oracle Database 10g; vedere il Capitolo 22 per maggiori dettagli. L’utility Export è
disponibile per tutte le versioni di Oracle. Per dettagli sulla utility Export, vedere il Capitolo 46.
Entrambe le utility sono descritte nella documentazione Oracle Database Utilities 10g Release 1
fornita con il software Oracle.
EXTENT LIBERI
Gli extent liberi sono extent di blocchi del database non ancora allocati per alcuna tabella o
segmento di indice. Extent liberi è quindi sinonimo di spazio libero.
EXTENT USATI
I cosiddetti “extent usati” sono le zone di memoria che sono già state allocate a segmenti di dati
(tabelle), pertanto possiedono già dei dati, oppure sono state riservate per i dati.
EXTRACT (datetime)
VEDERE ANCHE DATE, FUNZIONI; Capitolo 10.
SINTASSI
EXTRACT
( { { YEAR
| MONTH
| DAY
| HOUR
| MINUTE
| SECOND }
| { TIMEZONE_HOUR
| TIMEZONE_MINUTE }
| { TIMEZONE_REGION
| TIMEZONE_ABBR
} }
FROM { espressione_valore_dataora | espressione_valore_intervallo } )
DESCRIZIONE EXTRACT estrae e restituisce il valore del campo di una data/ora specificata da
una data/ora oppure da un’espressione del valore di intervallo.
ESEMPIO
select Datanascita,
EXTRACT(Mese from Datanascita) AS Mese
from COMPLEANNO
where Nome = 'VICTORIA';
DATANASCITA MESE
----------- ---------
20-MAY-49 5
1136 CAPITOLO 48
EXTRACT (XML)
VEDERE ANCHE Capitolo 47.
SINTASSI
EXTRACTVALUE
VEDERE ANCHE XMLType.
SINTASSI
FEEDBACK (SQL*PLUS)
Vedere SET.
FETCH
Una delle fasi dell’esecuzione di una query è quella di fetch: le righe di dati che soddisfano i
criteri di ricerca vengono recuperati dal database.
DESCRIZIONE intero è una variabile host che imposta il numero massimo di righe da inserire
nelle variabili di output. cursore è il nome di un cursore configurato precedentemente da DECLARE
CURSOR. :variabile_host corrisponde a una o più variabili host in cui vengono inseriti i dati
recuperati tramite FETCH. Se anche solo una delle variabili host è un array, allora anche tutte le
altre eventualmente presenti nell’elenco INTO devono essere array. La parola chiave INDICATOR
è facoltativa.
GUIDA DI RIFERIMENTO ALFABETICA 1137
DESCRIZIONE FETCH recupera una riga di dati. L’istruzione di selezione relativa al cursore
indicato determina le colonne da recuperare, mentre la relativa istruzione where determina quali
e quante righe possono essere recuperate. Questo prende il nome di “blocco attivo”, ma non può
essere elaborato fino a che non lo si recupera riga per riga con l’istruzione FETCH. L’istruzione
FETCH ottiene una riga dal blocco attivo e scarica i valori della riga all’interno del record (o
nella stringa di variabili), che è stato definito in DECLARE.
Se si utilizza il metodo dell’elenco di variabili, a ciascuna colonna nel select list del cursore
deve corrispondere una variabile e ognuna di esse dev’essere dichiarata nella sezione DECLARE.
I tipi di dati devono essere uguali o al più compatibili.
Se invece si utilizza il metodo dei record, questi devono essere dichiarati con l’attributo
%ROWTYPE secondo il quale la struttura del record è uguale (con i medesimi tipi di dati) a
quella dell’elenco di colonne nella selezione. A ciascuna variabile del record si potrà accedere
singolarmente usando come prefisso il nome del record, e il nome di una variabile identico al
nome della colonna.
ESEMPIO
declare
pi constant NUMBER(9,7) := 3.1415927;
area NUMBER(14,2);
cursore rag_cursore is
select * from VALORI_RAGGIO;
val_rag rag_cursore%ROWTYPE;
begin
open rag_cursore;
loop
fetch rag_cursore into val_rag;
exit when rag_cursore%NOTFOUND;
area := pi*power(val_rag.raggio,2);
insert into AREE values (val_rag.raggio, area);
end loop;
close rag_cursore;
end;
FILE, TIPI
Solitamente i file hanno un nome e un’estensione. Per esempio nel file comfort.tab, comfort
rappresenta il nome mentre tab è l’estensione o “tipo” del file. In SQL*PLUS, ai file di avvio
creati con EDIT viene assegnata l’estensione predefinita SQL se non viene specificata alcuna
estensione. In altre parole, il codice seguente:
1138 CAPITOLO 48
edit misti
start misti
cerca di avviare un file di nome misti.sql dato che non è stata specificata alcuna estensione.
Analogamente:
spool bellwood
crea un file di output chiamato bellwood.lst, dato che LST è l’estensione predefinita dei file di
spool. Naturalmente, quando edit e spool sono seguiti sia da un nome di file sia da un’estensione
si ricorrerà all’estensione fornita e non a quella predefinita.
file_specification
VEDERE ANCHE ALTER TABLESPACE, CREATE CONTROLFILE, CREATE DATABASE,
CREATE LIBRARY, CREATE TABLESPACE.
SINTASSI
file_specification::=
datafile_tempfile_spec
redo_log_file_spec
datafile_tempfile_spec::=
filename
’ ’
ASM_filename SIZE size_clause REUSE autoextend_clause
redo_log_file_spec::=
filename
’ ’
ASM_filename
filename
( ’ ’ )
ASM_filename SIZE size_clause REUSE
GUIDA DI RIFERIMENTO ALFABETICA 1139
size_clause::=
T
integer
ASM_filename::=
fully_qualified_file_name
numeric_file_name
incomplete_file_name
alias_file_name
fully_qualified_file_name::=
numeric_file_name::=
incomplete_file_name::=
( template_name )
+ diskgroup_name
alias_file_name::=
( template_name )
+ diskgroup_name / alias_name
autoextend_clause::=
OFF
AUTOEXTEND NEXT size_clause maxsize_clause
ON
1140 CAPITOLO 48
maxsize_clause::=
UNLIMITED
MAXSIZE
size_clause
FIRST
DESCRIZIONE DENSE_RANK, LAST.
SINTASSI
funzione_aggregazione KEEP
( DENSE_RANK FIRST ORDER BY
expr [ DESC | ASC ] [ NULLS { FIRST | LAST }]
[, expr [ DESC | ASC ] [ NULLS { FIRST | LAST }]]...
) [OVER clausola_partizionamento_query]
DESCRIZIONE FIRST è sia una funzione di aggregazione sia una funzione analitica che opera
su un gruppo di valori presi da un insieme di righe che sono le prime a comparire rispetto a una
determinata specifica di ordinamento. funzione_aggregazione è una delle funzioni di gruppo
numeriche standard (come MIN, MAX, AVG e STDDEV).
FIRST_VALUE
VEDERE ANCHE LAST_VALUE.
SINTASSI
FLASHBACK DATABASE
DESCRIZIONE FLASHBACK TABLE, Capitolo 28.
SINTASSI
flashback_database::=
SCN
TO expr
STANDBY database TIMESTAMP
FLASHBACK DATABASE ;
SCN
TO BEFORE expr
TIMESTAMP
GUIDA DI RIFERIMENTO ALFABETICA 1141
È possibile stabilire fino a che punto tornare indietro per ripristinare il database eseguendo
una query sulla vista V$FLASHBACK_DATABASE_LOG. La quantità di dati flashback
conservati nel database è controllata dal parametro di inizializzazione
DB_FLASHBACK_RETENTION_TARGET e la dimensione dell’area di recupero flashback.
Per ulteriori limitazioni ed esempi, si rimanda al Capitolo 28.
ESEMPIO
Dopo che il database è rimasto aperto per più di un’ora, ecco come riportarlo alla versione
precedente:
SHUTDOWN DATABASE;
STARTUP MOUNT EXCLUSIVE;
FLASHBACK DATABASE TO TIMESTAMP SYSDATE-1/24;
FLASHBACK TABLE
VEDERE ANCHE FLASHBACK DATABASE, Capitolo 28.
SINTASSI
flashback_table::=
schema .
FLASHBACK TABLE table
ENABLE
TRIGGERS
SCN DISABLE
expr
TIMESTAMP
TO ;
RENAME TO table
BEFORE DROP
DESCRIZIONE FLASHBACK TABLE ripristina uno stato precedente di una tabella nel caso in
cui l’utente commetta un errore oppure si verifichi un errore nell’applicazione. Oracle non è in
1142 CAPITOLO 48
grado di ripristinare una tabella a uno stato precedente attraversando qualsiasi operazione DDL
che modifichi la struttura della tabella.
È necessario disporre del privilegio di oggetto FLASHBACK sulla tabella oppure il privilegio
di sistema FLASHBACK ANY TABLE. Si deve disporre anche dei privilegi di oggetto SELECT,
INSERT, DELETE e ALTER sulla tabella. Gli spostamenti delle righe devono essere abilitati per
tutte le tabelle nella lista di flashback. Per ripristinare una tabella a un momento precedente a
un’operazione DROP TABLE, sono sufficienti i privilegi richiesti per eliminare la tabella.
Durante un’operazione FLASHBACK TABLE, Oracle acquisisce blocchi DML esclusivi in
tutte le tabelle specificate. Il comando viene eseguito in un’unica transazione in tutte le tabelle;
se qualcuna fallisce, l’intera istruzione fallisce.
Quando una tabella viene ripristinata, lo stesso non accade alle sue statiche. Gli indici
presenti nella tabella vengono ripristinati, pertanto riflettono lo stato della tabella al punto di
flashback. Gli indici eliminati a partire dal punto di flashback non vengono ripristinati. Gli
indici creati a partire dal punto di flashback continueranno a esistere e saranno aggiornati in
modo da riflettere i dati meno recenti.
Per vedere il contenuto del cestino è possibile interrogare USER_RECYCLEBIN.
Per ulteriori limitazioni ed esempi, si rimanda al Capitolo 28.
ESEMPIO
FLASHBACK QUERY
Una query flashback mostra com’erano i dati prima di un comando COMMIT. Vedere il Capitolo
27 per gli esempi e le limitazioni relative alle query flashback.
FLOOR
VEDERE ANCHE CEI; NUMERI FUNZIONI; Capitolo 9.
SINTASSI
FLOOR(valore)
GUIDA DI RIFERIMENTO ALFABETICA 1143
DESCRIZIONE FLOOR è il valore intero più grande, minore o uguale al valore specificato.
ESEMPIO
FLOOR(2) = 2
FLOOR(-2.3) = -3
FLUSH (SQL*PLUS)
Vedere SET.
FOR
Vedere LOOP e CICLI A CURSORE.
FORMATO, MODELLO
Un modello di formato è un’opzione che controlla l’aspetto di numeri, date e stringhe di caratte-
ri. I modelli di formato per le colonne di tipo DATE sono utilizzati nelle funzioni di conversione
della data, come TO_CHAR e TO_DATE.
FROM
VEDERE ANCHE DELETE, SELECT, Capitolo 5.
SINTASSI
FROM_TZ
VEDERE ANCHE TIMESTAMP WITH TIME ZONE, Capitolo 10.
SINTASSI
FUNZIONE
Una funzione è un’operazione predefinita, come “converti in maiuscole”, e può essere eseguita
specificandone il nome e gli eventuali argomenti in un’istruzione SQL. Vedere CARATTERI,
FUNZIONI; CONVERSIONE, FUNZIONI; DATA, FUNZIONI; FUNZIONI DI GRUPPO,
FUNZIONI DI ELENCO, NUMERI, FUNZIONI e funzioni individuali.
FUNZIONI ANALITICHE
Le funzioni analitiche calcolano il valore di un aggregato in base a un gruppo di righe e
restituiscono più righe per ciascun gruppo. Molte delle funzioni analitiche sono elencate sotto la
voce FUNZIONI DI AGGREGAZIONE; quando sono utilizzate come funzioni analitiche, possono
essere usate solo nella clausola ORDER BY.
Nell’elenco di funzioni analitiche riportato di seguito (fare riferimento alle singole voci per
la descrizione della sintassi), quelle seguite da un asterisco consentono l’uso di una clausola di
windowing: AVG*, CORR*, COVAR_POP*, COVAR_SAMP*, COUNT*, CUME_DIST,
DENSE_RANK, FIRST, FIRST_VALUE*, LAG, LAST, LAST_VALUE*, LEAD, MAX*, MIN*, NTILE,
PERCENT_RANK, PERCENTILE_CONT, PERCENTILE_DISC, RANK, RATIO_TO_REPORT,
REGR_*, ROW_NUMBER, STDDEV*, STDDEV_POP, STDDEV_SAMP, SUM*, VAR_POP*,
VAR_SAMP*, VARIANCE*.
FUNZIONI DI AGGREGAZIONE
VEDERE ANCHE Capitolo 9.
DESCRIZIONE Una funzione di aggregazione calcola un singolo valore riassuntivo (come una
somma o una media) dai singoli valori numerici in un gruppo di valori. Questo è un elenco
alfabetico di tutte le funzioni di aggregazione correnti in SQL di Oracle. Ciascuna viene riporta-
ta altrove in questa guida, assieme alla sintassi e ad esempi d’uso. Le funzioni di aggregazione
risultano utili solo all’interno di query e subquery. DISTINCT fa in modo che una funzione di
aggregazione riassuma solo valori distinti (unici).
NOME E IMPIEGO DELLE FUNZIONI
AVG fornisce la media dei valori contenuti in un gruppo di righe.
COLLECT prende il valore della colonna di input e crea una tabella nidificata del tipo di input
con le righe selezionate.
GUIDA DI RIFERIMENTO ALFABETICA 1145
VAR_POP restituisce la varianza della popolazione di un insieme di numeri dopo aver scartato i
valori NULL contenuti in questo gruppo.
VAR_SAMP restituisce la varianza del campione di un insieme di numeri dopo aver scartato i
valori NULL contenuti in questo gruppo.
VARIANCE fornisce la varianza di tutti i valori di un gruppo di righe.
FUNZIONI DI ELENCO
VEDERE ANCHE Tutti gli altri elenchi di funzioni, Capitolo 10.
DESCRIZIONE Di seguito sono elencate, in ordine alfabetico, tutte le funzioni di elenco corren-
ti di SQL di Oracle. Ciascuna viene riportata altrove in questa guida, assieme alla sintassi e ad
esempi d’uso.
Questa funzione fornisce il primo valore non NULL del gruppo:
FUNZIONI DI MODELLO
Le funzioni di modello sono rilevanti solo per i calcoli interriga e possono essere utilizzate solo
nella clausola MODEL dell’istruzione SELECT. Sono funzioni non ricorsive. Le funzioni di
modello sono CV, ITERATION_NUMBER, PRESENTNNV, PRESENTV e PREVIOUS.
FUNZIONI DI RACCOLTA
Le funzioni di raccolta operano sulle tabelle nidificate e con gli array variabili; fare riferimento
al Capitolo 34 per maggiori dettagli. Tra le funzioni di raccolta disponibili troviamo CARDINALITY,
COLLECT, POWERMULTISET, POWERMULTISET_BY_CARDINALITY e SET.
FUNZIONI DI REGRESSIONE
A partire da Oracle9i, Oracle supporta le seguenti funzioni di regressione: REGR_SLOPE,
REGR_INTERCEPT, REGR_COUNT, REGR_R2, REGR_AVGX, REGR_AVGY, REGR_SXX,
REGR_SYY e REGR_SXY. Per la sintassi ed esempi di queste funzioni analitiche, si consulti la
Oracle SQL Reference Guide.
GET
VEDERE ANCHE EDIT, SAVE.
SINTASSI
DESCRIZIONE GET carica il file di un sistema host, di nome file, nel buffer corrente (ossia
quello di SQL o uno definito dall’utente). Se il tipo di file non viene specificato, GET suppone si
tratti di un file SQL. LIST fa in modo che SQL*PLUS elenchi le linee che sono state caricate nel
buffer. Questa è l’impostazione prededfinita. NOLIST carica il file senza elencarne il contenuto.
ESEMPIO
L’esempio seguente ottiene un file di nome lavoro.sql:
get lavoro
GOTO
VEDERE ANCHE BLOCCO, STRUTTURA; Capitolo 29.
SINTASSI
GOTO etichetta;
DECLARE
...
BEGIN
x := 0;
y := 1;
<<alpha>>
x := x + 1;
y := x*y;
insert ...
if y > 10000
then goto beta;
goto alpha;
<<beta>>
exit;
1148 CAPITOLO 48
GRANT
VEDERE ANCHE ALTER USER, CREATE USER, PRIVILEGI, REVOKE, RUOLI, Capitolo 18.
SINTASSI
grant::=
grant_system_privileges
GRANT ;
grant_object_privileges
grant_system_privileges::=
system_privilege
role TO grantee_clause
ALL PRIVILEGES
grant_object_privileges::=
,
object_privilege ( column )
PRIVILEGES on_object_clause
ALL
on_object_clause::=
schema . object
ON DIRECTORY directory_name
SOURCE schema .
JAVA object
RESOURCE
GUIDA DI RIFERIMENTO ALFABETICA 1149
grantee_clause::=
user
role
PUBLIC
DESCRIZIONE La prima forma di GRANT estende uno o più privilegi di sistema a utenti e ruoli.
Un privilegio di sistema non è altro che un’autorizzazione all’esecuzione di particolari comandi
per il controllo o la definizione dei dati, come ALTER SYSTEM, CREATE ROLE o GRANT. Per
ulteriori informazioni sui privilegi, si consulti PRIVILEGI. Gli utenti vengono creati con CRE-
ATE USER, in seguito vengono concessi i privilegi di sistema che permettono loro la connessio-
ne al database e l’esecuzione di alcune operazioni. Un utente privo di concessioni non è in grado
di eseguire alcuna operazione in Oracle. Un ruolo è una collezione di privilegi creata con il
comando CREATE ROLE. Come accade per gli utenti, anche un ruolo quando viene creato non
dispone di alcun privilegio. A entrambe le entità i privilegi vengono assegnati per mezzo di uno
o più GRANT. Inoltre, è possibile concedere ruoli ad altri ruoli per creare una rete annidata di
permessi, che offre all’amministratore del database un’ampia libertà nella gestione della sicu-
rezza del database.
L’opzione WITH ADMIN OPTION consente all’utente o al ruolo (il concessionario), di con-
cedere il sistema di privilegio o il ruolo ad altri concessionari. Il concessionario può anche mo-
dificare o cancellare l’opzione WITH ADMIN OPTION concessa a un ruolo.
La seconda forma del comando GRANT concede privilegi relativi agli oggetti, ovvero privi-
legi che riguardano tipi specifici di oggetti nei database Oracle, di qualunque utente o ruolo.
oggetto può essere una tabella, vista, sequenza, procedura, funzione, package, vista materializzata
o un sinonimo per uno di questi oggetti. Le concessioni di privilegi a un sinonimo equivalgono
alle concessioni dei medesimi privilegi agli oggetti di base cui fa riferimento il sinonimo. Per un
elenco completo dei privilegi degli oggetti e del loro significato, si consulti la parte relativa ai
PRIVILEGI.
Se si concedono privilegi INSERT, REFERENCES o UPDATE su una tabella o vista, il co-
mando GRANT può anche specificare un elenco di colonne della tabella o della vista cui applica-
re i permessi. Il comando GRANT verrà applicato soltanto a queste colonne. Se GRANT non
specifica un elenco di colonne, i permessi vengono applicati a tutte le colonne della tabella o
della vista.
PUBLIC concede i privilegi a tutti gli utenti attuali e futuri.
L’opzione WITH GRANT OPTION concede agli utenti (o ai ruoli) di destinazione il permes-
so di concedere il medesimo privilegio ad altri utenti o ruoli.
GREATEST
VEDERE ANCHE ORDINAMENTO, LEAST, MAX, FUNZIONI DI ELENCO, Capitoli 9 e 10.
SINTASSI
DESCRIZIONE GREATEST sceglie il numero più grande da un elenco di valori. Questi possono
essere colonne, valori letterali o espressioni, e tipi di dati CHAR, VARCHAR2, NUMBER e
1150 CAPITOLO 48
DATE. Un numero con un valore più grande è considerato “maggiore” di quello con il valore più
piccolo. Tutti i numeri negativi vengono considerati minori di quelli positivi. Perciò –10 è mino-
re di 10; –100 è minore di –10. Una data successiva è considerata maggiore di una precedente.
Le stringhe di caratteri vengono confrontate lettera per lettera a partire da quella più a sini-
stra fino al primo carattere differente. La stringa che ha il carattere più grande in quella posizione
è considerata la “maggiore”. Un carattere è considerato più grande di un altro quando ha un
codice ASCII (o EBCDIC) più elevato. Questo significa generalmente che B è maggiore di A ma
anche che il valore di A in rapporto ad “a” o a “1” varia da piattaforma a piattaforma.
Se due stringhe sono identiche fino alla fine di quella più piccola, la stringa più lunga è
considerata maggiore. Se due stringhe sono identiche e per di più hanno la stessa lunghezza sono
considerate uguali. In SQL, è essenziale che tutti i letterali numerici vengano inseriti senza apici:
‘10’ verrebbe considerato minore di ‘6’ poiché gli apici indicano a SQL di considerarli come
stringhe di caratteri; il ‘6’ è più grande della cifra 1 di ‘10’.
A differenza della maggior parte delle funzioni e degli operatori logici di Oracle, GREATEST
e LEAST non considerano come date le stringhe di caratteri eventualmente corrispondenti a tale
formato. Per fare in modo che LEAST e GREATEST funzionino correttamente, si deve applicare
per prima la funzione TO_DATE ai letterali da valutare.
GROUP BY
VEDERE ANCHE CUBE, HAVING, ORDER BY, ROLLUP, WHERE, Capitolo 12.
SINTASSI
DESCRIZIONE GROUP BY fa in modo che una clausola select produca una riga di riepilogo per
tutte le righe selezionate che hanno valori identici in una o più colonne o espressioni specificate
dall’utente. Ogni espressione nella clausola select deve essere una di queste:
■ una costante;
■ una funzione senza parametri (SysDate, User);
■ una funzione di gruppo come SUM, AVG, MIN, MAX, COUNT;
■ un’espressione identica a quelle specificate nella clausola GROUP BY.
Le colonne specificate nella clausola GROUP BY possono anche non essere ripetute nella
clausola select; mentre devono essere presenti all’interno della tabella.
Per determinare quali gruppi includere nella clausola GROUP BY si deve utilizzare HAVING.
Una clausola where, invece, stabilisce quali righe includere nei gruppi.
GROUP BY e HAVING seguono WHERE, CONNECT BY e START WITH. La clausola ORDER
BY viene eseguita dopo le clausole WHERE, GROUP BY e HAVING (le quali a loro volta vengo-
no eseguite in questo ordine). Inoltre, può implementare funzioni di gruppo o colonne tratte da
GROUP BY, oppure una combinazione di entrambe. Se utilizza una funzione di gruppo, questa
funzione agisce sui gruppi, poi ORDER BY ordina i risultati della funzione. Se ORDER BY
impiega una colonna di GROUP BY, ordina le righe restituite in base a questa colonna. Le fun-
zioni di gruppo e le singole colonne possono essere combinate in ORDER BY (purché la colonna
si trovi in GROUP BY).
GUIDA DI RIFERIMENTO ALFABETICA 1151
Nella clausola ORDER BY è possibile specificare una funzione di gruppo e la colonna su cui
agisce, anche se queste non hanno nulla a che vedere con le funzioni di gruppo e le colonne delle
clausole SELECT, GROUP BY o HAVING. D’altra parte, se si specifica una colonna in ORDER
BY che non appartiene a una funzione di gruppo, questa colonna deve essere contenuta nella
clausola GROUP BY.
ESEMPIO
GROUP_ID
VEDERE ANCHE GROUP BY, GROUPING_ID, FUNZIONI DI AGGREGAZIONE, Capitolo 12.
SINTASSI
GROUP_ID ( )
DESCRIZIONE GROUP_ID distingue i gruppi duplicati che vengono prodotti da una specifica
GROUP BY.
GROUPING
GROUPING è una funzione utilizzata insieme alle funzioni ROLLUP e CUBE per rilevare i valo-
ri NULL. Vedere ROLLUP.
GROUPING_ID
GROUPING_ID restituisce un numero che corrisponde al vettore bit di GROUPING associato a
una riga. Si consultino ROLLUP, CUBE, e il Capitolo 12.
HASH JOIN
Un hash join è un metodo che permette di unire tramite join due tabelle. Questo metodo utilizza
algoritmi di hash (simili a quelli utilizzati per i cluster di hash) per valutare quali righe soddisfa-
no i criteri di join. Sebbene utilizzino algoritmi simili, non esiste alcuna relazione diretta tra gli
hash join e i cluster di hash.
HAVING
Vedere GROUP BY.
HEADING (SQL*PLUS)
Vedere SET.
1152 CAPITOLO 48
HEADSEP (SQL*PLUS)
Vedere SET.
HELP (SQL*PLUS)
SINTASSI
HELP [argomento]
HEXTORAW
VEDERE ANCHE RAWTOHEX.
SINTASSI
HEXTORAW(stringa_esadecimale)
HOST (SQL*Plus)
VEDERE ANCHE $, @, @@, START.
SINTASSI
DESCRIZIONE Un host è un computer su cui viene eseguito Oracle RDBMS. Il comando HOST
in SQL*Plus restituisce qualsiasi comando dell’host al sistema operativo in modo che possa
essere eseguito senza uscire da SQL*Plus. SQL*Plus permette di incorporare variabili locali o
PL/SQL nella stringa di comando dell’host. Questa funzione purtroppo non garantisce il funzio-
namento su tutte le possibili piattaforme e sistemi operativi. HOST non è disponibile in iSQL*Plus
IF
VEDERE ANCHE CICLI, Capitolo 29.
SINTASSI
DESCRIZIONE L’istruzione IF esegue una o più istruzioni se condizione vale TRUE, quindi il
programma salta alla riga che segue END IF. Se condizione vale FALSE, vengono valutate tutte
GUIDA DI RIFERIMENTO ALFABETICA 1153
le condizioni ELSIF facoltative. Se una vale TRUE, vengono eseguite le istruzioni associate
(quelle che seguono THEN) e quindi il programma salta a END IF. Se nessuna delle condizioni
ELSIF è TRUE (e la condizione IF originale non era TRUE), vengono eseguite le istruzioni che
seguono l’istruzione ELSE facoltativa. Si noti che ELSE finale non ha alcuna condizione.
ESEMPIO
declare
pi constant NUMBER(9,7) := 3.1415927;
area NUMBER(14,2);
cursore rag_cursore is
select * from VALORI_RAGGIO;
val_rag rag_cursore%ROWTYPE;
begin
open rag_cursore;
fetch rag_cursore into val_rag;
area := pi*power(val_rag.raggio,2);
if area >30
then
insert into AREE values (val_rag.raggio, area);
end if;
close rag_cursore;
end;
IMPORT
Importare significa usare una delle utility di Oracle per leggere i dati da un file di dump di
esportazione e inserirli in un database con una utility di importazione. Le utility di importazione
sono due: Import e and Data Pump Import. Data Pump Import è disponibile a partire da Oracle
Database 10g; vedere il Capitolo 22 per maggiori dettagli. L’utility Import è disponibile per tutte
le versioni di Oracle. Per dettagli sulla utility IMport, vedere il Capitolo 46. Entrambe le utility
sono descritte nella documentazione Oracle Database Utilities 10g Release 1 fornita con il software
Oracle.
IN
VEDERE ANCHE ALL, ANY, OPERATORI LOGICI, WHERE, Capitolo 5.
SINTASSI
DESCRIZIONE IN equivale a =ANY. Nella prima opzione, IN significa che l’espressione è ugua-
le a qualsiasi membro dell’elenco seguente di stringhe letterali. Nella seconda opzione, significa
che l’espressione è uguale a qualsiasi valore in qualsiasi riga selezionata dalla subquery. Si tratta
di due costrutti logicamente equivalenti, con il primo che fornisce un elenco composto da strin-
ghe letterali e il secondo che crea un elenco da una query. IN funziona con i tipi di dati VARCHAR2,
CHAR, DATE e NUMBER, e anche con i tipi RowID.
INDICE
Indice è un termine generale che identifica una caratteristica di Oracle/SQL utilizzata principal-
mente per velocizzare l’esecuzione e imporre l’univocità di alcuni dati. In generale, gli indici
1154 CAPITOLO 48
offrono un metodo di accesso più rapido ai dati di una tabella rispetto all’esecuzione di una
scansione intera di tabella. Esistono diversi tipi di indici; vedere INDICE CONCATENATO,
INDICE COMPRESSO e INDICE UNICO. Un indice ha una voce per ciascun valore che si
trova nei campi indicizzati della tabella (eccetto quelli con un valore NULL) e puntatori alle righe
che hanno questo valore.
INDICE COMPRESSO
Un indice compresso è un indice per il quale vengono memorizzate solo le informazioni neces-
sarie a identificare le voci non duplicate; le informazioni che un indice memorizza con la chiave
precedente o successiva sono “compresse” (troncate) e non registrate per ridurre lo spazio ri-
chiesto dall’indice.
INDICE GLOBALE
Quando si partiziona una tabella, i suoi dati vengono memorizzati in segmenti separati. Quando
sulla tabella partizionata viene creato un indice, questo può essere partizionato a sua volta per
rispecchiare ogni partizione della tabella. Se le partizioni degli indici non coincidono con quelle
delle tabelle, l’indice si dice globale. Vedere il Capitolo 17.
INDICE LOCALE
Quando si partiziona una tabella, i suoi dati vengono memorizzati all’interno di tabelle diverse.
Quando su una tabella partizionata si crea un indice, questo può essere partizionato in modo da
rispecchiare ogni partizione della tabella. Queste partizioni indicizzate prendono il nome di
indici locali. Vedere il Capitolo 17.
INDICE REVERSE
In un indice Reverse, i byte del valore indicizzato vengono invertiti prima di essere memorizzati
nell’indice stesso. Pertanto, valori come 1234 e 1235 vengono indicizzati come se fossero 4321
e 5321. Come conseguenza di questa inversione, i due valori vengono memorizzati in locazioni
ancora più distanti. Se si esegue spesso una query sulla colonna per trovare una corrispondenza
esatta (colonna=1234) un indice Reverse potrebbe ridurre i conflitti di blocco all’interno del-
l’indice. Se si eseguono spesso query di intervallo (colonna1234 o colonna like ‘123%’) allora
gli indici tradizionali sono più adatti alle proprie esigenze. Vedere CREATE INDEX.
INDICE TESTUALE
Un indice testuale è un insieme di tabelle e indici utilizzati dai programmi per le ricerche di
testo. Come l’indice di un libro, un indice testuale contiene le tabelle con le voci di testo e le
relative posizioni. Vedere il Capitolo 25.
INDICE UNICO
Un indice unico è un indice che impone l’univocità di ogni valore che indicizza. L’indice può
essere un’unica colonna o un tipo di dati concatenato (formato di diverse colonne). Vedere VIN-
COLO DI INTEGRITÀ.
GUIDA DI RIFERIMENTO ALFABETICA 1155
INDICI, SEGMENTO
Il segmento di un indice è la memoria allocata per un indice, in contrapposizione alla memoria
allocata per i dati di una tabella.
init.ora
init.ora è un file dei parametri di sistema del database che contiene impostazioni e nomi di file
utilizzati all’avvio di un sistema mediante il comando CREATE DATABASE o i comandi di avvio
e di uscita. In Oracle9i è possibile utilizzare un file init.ora oppure si può creare un file dei
parametri di sistema mediante il comando CREATE SPFILE. Vedere CREATE PFILE e CREATE
SPFILE.
INITCAP
VEDERE ANCHE CARATTERI, FUNZIONI; LOWER; UPPER; Capitolo 7.
SINTASSI
INITCAP(stringa)
DESCRIZIONE INITCAP rende maiuscola la prima lettera di una o più parole. Inoltre, tiene
conto della presenza di simboli e opera le modifiche sulle lettere che seguono spazi e simboli
come virgole, punti, due punti, punto e virgola, !, @, #, $ e così via.
ESEMPIO
INITCAP('ecco.qui,un-esempio di!come@initcap#funziona')
produce:
Ecco.Qui,Un-Esempio Di!Come@Initcap#Funziona
INPUT (SQL*Plus)
VEDERE ANCHE APPEND, CHANGE, DEL, EDIT, Capitolo 6.
SINTASSI
I[NPUT] [testo]
DESCRIZIONE INPUT aggiunge una nuova linea di testo dopo la linea corrente nel buffer cor-
rente. INPUT senza parametri permette di inserire più linee dopo la linea corrente, che si inter-
rompe quando il sistema incontra un carattere di INVIO su una linea vuota. Lo spazio tra INPUT e
testo non viene aggiunto alla linea, mentre qualsiasi altro spazio viene aggiunto. Per una discus-
sione relativa alla linea corrente, si consulti DEL. INPUT non è disponibile in iSQL*Plus.
SINTASSI
DESCRIZIONE La modalità di impiego di INSERT in PL/SQL è identica alla sua forma genera-
le (Forma 3 del paragrafo seguente) salvo le seguenti eccezioni.
■ È possibile utilizzare una variabile PL/SQL in un’espressione per il valore dell’elenco
VALUES.
■ Ogni variabile viene trattata allo stesso modo di una costante contenente il valore della
variabile.
■ Se si usa la versione query. . . di INSERT, non si può utilizzare la clausola INTO di select.
hint single_table_insert
INSERT ;
multi_table_insert
GUIDA DI RIFERIMENTO ALFABETICA 1157
single_table_insert::=
returning_clause
values_clause
insert_into_clause
subquery
insert_into_clause::=
t_alias ( column )
INTO dml_table_expression_clause
values_clause::=
expr
VALUES ( )
DEFAULT
returning_clause::=
, ,
multi_table_insert::=
values_clause
ALL insert_into_clause
subquery
conditional_insert_clause
conditional_insert_clause::=
ALL
FIRST values_clause
WHEN condition THEN insert_into_clause
values_clause
ELSE insert_into_clause
1158 CAPITOLO 48
DML_table_expression_clause::=
PARTITION ( partition )
SUBPARTITION ( subpartition )
@ dblink
schema . table
view @ dblink
materialized view
subquery_restriction_clause
( subquery )
table_collection_expression
subquery_restriction_clause::=
READ ONLY
WITH CONSTRAINT constraint
CHECK OPTION
table_collection_expression::=
( + )
TABLE ( collection_expression )
DESCRIZIONE INSERT aggiunge una o più righe nuove alla tabella o alla vista. Il campo
facoltativo schema dev’essere un utente per la cui tabella è stato concesso il privilegio di inseri-
mento. tabella è la tabella in cui inserire le righe. Se viene fornito un elenco di colonne, per
ciascuna dev’essere verificata un’espressione SQL. Le colonne non presenti in elenco ricevono
il valore NULL e nessuna di esse deve essere stata definita NOT NULL altrimenti INSERT fallisce.
Se non viene fornito un elenco di colonne, per tutte le colonne della tabella si dovranno specifi-
care dei valori.
INSERT con una subquery aggiunge il numero di righe risultanti dalla query associando,
posizione per posizione, ogni colonna della query alle colonne contenute nell’elenco. Se non
viene fornito alcun elenco di colonne, le tabelle dovranno avere lo stesso numero e tipo di colon-
ne. La vista del dizionario dati USER_TAB_COLUMNS fornisce un esempio, così come
DESCRIBE in SQL*PLUS.
ESEMPIO
Di seguito, viene inserita una riga nella tabella COMFORT:
Questa riga invece inserisce Città, DataCampione (entrambe colonne NOT NULL) e Preci-
pitazione in COMFORT:
GUIDA DI RIFERIMENTO ALFABETICA 1159
Per copiare soltanto i dati della città di KEENE in una nuova tabella di nome
NEW_HAMPSHIRE si può utilizzare:
Per informazioni riguardanti l’inserimento di righe all’interno di tabelle che utilizzano tipi
di dati astratti, si rimanda al Capitolo 33. Per dettagli sull’inserimento di righe in tabelle annidate
e array variabili, si consulti il Capitolo 34.
INSTR
VEDERE ANCHE CARATTERI, FUNZIONI; SUBSTR; Capitolo 7.
SINTASSI
DESCRIZIONE INSTR trova la posizione di un set di caratteri in una stringa, partendo dalla
posizione di inizio della stringa e cercando la prima, seconda, terza... occorrenza del set. Questa
funzione opera anche con i tipi di dati NUMBER e DATE. Anche inizio può essere un numero
negativo, in tal caso la ricerca comincia con i caratteri alla fine della stringa e procede all’indietro.
ESEMPIO
Per trovare la terza occorrenza di ‘PI’ nella stringa seguente, si può utilizzare:
INTEGRITÀ REFERENZIALE
L’integrità referenziale è la proprietà che garantisce che i valori di una colonna dipendono da
quelli presenti in un’altra colonna. Questa proprietà viene imposta tramite vincoli di integrità.
Vedere VINCOLO DI INTEGRITÀ.
INTERSECT
VEDERE ANCHE MINUS, OPERATORI DI QUERY, UNION, Capitolo 13.
SINTASSI
select...
INTERSECT
select...
1160 CAPITOLO 48
DESCRIZIONE INTERSECT combina due query e restituisce solo le righe dalla prima istruzio-
ne select che sono identiche ad almeno una riga di quelle della seconda istruzione select. Tra le
istruzioni select, il numero di colonne e i tipi di dati devono essere identici, condizione non
richiesta per i nomi delle colonne. Tuttavia, per far sì che l’intersezione passi i dati, questi do-
vranno essere identici nelle righe prodotte.
INTESTAZIONE DI RIGA
È quella parte della riga che contiene le informazioni sulla riga che non riguardano i dati della
riga, ossia il numero di campi, i tipi delle colonne e così via.
IS A SET
VEDERE ANCHE IS EMPTY, Capitolo 34.
SINTASSI
DESCRIZIONE La condizione IS A SET viene utilizzata per verificare se una tabella nidificata
specificata è composta da elementi unici. La condizione restituisce TRUE se la tabella nidificata
è un insieme, anche se è di lunghezza zero, altrimenti restituisce FALSE. Restituisce NULL se la
tabella nidificata è vuota.
IS ANY
VEDERE ANCHE SELECT.
SINTASSI
colonna_dimensioni IS ANY
DESCRIZIONE La clausola IS ANY è rilevante solo per i calcoli interriga e può essere utilizzate
solo nella clausola MODEL di un’istruzione SELECT. Utilizzare questa condizione per qualificare
GUIDA DI RIFERIMENTO ALFABETICA 1161
tutti i valori di una colonna di dimensioni, compreso NULL. La condizione restituisce sempre un
valore booleano pari a TRUE per qualificare tutti i valori della colonna.
IS EMPTY
VEDERE ANCHE IS A SET, Capitolo 34.
SINTASSI
DESCRIZIONE La condizione IS [NOT] EMPTY viene utilizzata per verificare se una tabella
nidificata specificata è vuota, a prescindere dal fatto che alcuni elementi della collezione siano
NULL. La condizione restituisce un valore booleano: TRUE per una condizione IS EMPTY se la
condizione è vuota, TRUE per una condizione IS NOT EMPTY se la condizione non è vuota. Se
si specifica NULL per la tabella nidificata o l’array, il risultato è NULL.
IS NULL
VEDERE ANCHE OPERATORI LOGICI, Capitoli 5 e 9.
SINTASSI
DESCRIZIONE IS NULL verifica che in una colonna (o in un’espressione) non vi siano dati. Un
test di nullità è differente da un test di uguaglianza in quanto NULL significa che un valore è
sconosciuto o irrilevante e perciò non si può dire che sia uguale a qualche altra cosa, ivi compre-
so un altro valore NULL.
IS OF tipo
VEDERE ANCHE VALUE, Capitolo 33.
SINTASSI
is_of_type_conditions::=
DESCRIZIONE La condizione IS OF tipo viene utilizzata per testare le istanze degli oggetti in
base al tipo specifico delle loro informazioni. La condizione viene valutata NULL se espr è
NULL. In caso contrario, la condizione viene valutata TRUE (o FALSE se si specifica la parola
chiave NOT) in una di queste circostanze:
■ Il tipo più specifico di espr è il sottotipo di uno dei tipi specificati nell’elenco tipo e non è
stato specificato ONLY per il tipo.
■ Il tipo più specifico di espr viene specificato esplicitamente nell’elenco tipo.
espr spesso assume la forma della funzione VALUE con una variabile di correlazione.
1162 CAPITOLO 48
IS PRESENT
VEDERE ANCHE SELECT.
SINTASSI
riferimento_cella IS PRESENT
DESCRIZIONE La condizione IS PRESENT è rilevante solo per i calcoli interriga e può essere
utilizzata solo nella clausola MODEL di un’istruzione SELECT. Utilizzare questa condizione
per verificare se la cella cui si fa riferimento è presente prima dell’esecuzione della clausola
MODEL. La condizione restituisce TRUE se la cella esiste prima dell’esecuzione della clausola
MODEL, altrimenti restituisce FALSE.
ISTANZA
Un’istanza è tutto ciò che serve per eseguire Oracle: processi in background (programmi), me-
moria e così via. Un’istanza è il mezzo attraverso cui si accede a un database.
ISTANZA, IDENTIFICATIVO
Un identificativo d’istanza è lo strumento con cui è possibile distinguere un’istanza dall’altra
quando su un host ne esistono diverse.
ISTOGRAMMA
Un istogramma mostra la distribuzione dei dati di una colonna. L’ottimizzatore di Oracle può
utilizzare gli istogrammi per determinare l’efficienza degli indici per particolari intervalli di
valori. Vedere ANALYZE.
JAVA
Java è un linguaggio di programmazione sviluppato in origine da Sun Microsystems. Gli oggetti
procedurali memorizzati possono essere scritti sia con PL/SQL sia con Java. Vedere il Capitolo 37.
JDBC
JDBC è l’acronimo di Java Database Connectivity, un’interfaccia di database per la programma-
zione di applicazioni industriali standard. Oracle supporta le connessioni JDBC. Vedere il Capi-
tolo 35.
JOIN
VEDERE ANCHE SELECT, Capitolo 5.
SINTASSI
oppure:
oppure:
oppure:
DESCRIZIONE Un join combina colonne e dati da due o più tabelle (e raramente da parti
diverse della stessa tabella). Le tabelle sono tutte elencate nella clausola from dell’istruzione
select e la relazione tra le due tabelle può essere specificata nella clausola where generalmente
attraverso una semplice eguaglianza del tipo:
Questo costrutto viene spesso indicato col nome di equi-join poiché utilizza il segno di
uguale nella clausola where. Si possono unire tramite join delle tabelle anche con altre forme di
uguaglianza come >=, < e così via, che raramente danno risultati significativi. Molto spesso uno
o entrambi i membri del segno di uguale possono contenere un’espressione, talvolta una SUBSTR
oppure una combinazione di colonne, che viene utilizzata per stabilire l’uguaglianza con l’altro
membro. Si tratta di un impiego abbastanza comune.
L’unione tramite join di due tabelle senza una clausola di join, specificata nella clausola
from oppure nella clausola where, dà come risultato un prodotto cartesiano, che associa ogni riga
in una tabella ad ogni riga di un’altra tabella. Una tabella di 80 righe combinata con un’altra di
100 righe produce un risultato di 8000 righe (in genere ben poco significativo).
Un outer join è un metodo che permette di recuperare intenzionalmente le righe di una
tabella che non corrispondono a quelle di un’altra tabella. A partire da Oracle9i è possibile
utilizzare le opzioni di sintassi degli outer join dello standard ANSI (LEFT OUTER JOIN, RIGHT
OUTER JOIN e FULL OUTER JOIN). Per esempi sulla sintassi degli outer join, si rimanda al
Capitolo 13.
JOIN INTERNO
I join interni restituiscono delle righe in base ai valori chiave che due tabelle hanno in comune.
Supportano sia la clausola ON sia la clausola USING. Per esempio, la query seguente unisce
tramite join LIBRO_ORDINE a BIBLIOTECA basandosi sui valori della colonna Titolo:
select BO.Titolo
from LIBRO_ORDINE BO inner join BIBLIOTECA B
on BO.Titolo = B.Titolo;
select Titolo
from LIBRO_ORDINE BO inner join BIBLIOTECA B
1164 CAPITOLO 48
using (Titolo);
JOIN NATURALE
Un join naturale unisce due tabelle basandosi sulle colonne di chiave che esse hanno in comune.
Di seguito ne è riportata la sintassi:
che equivale a:
Per esempi dei tipi diversi di sintassi di join, si rimanda al Capitolo 13.
LABEL (PL/SQL)
Un’etichetta è una parola associata a un’istruzione eseguibile, in genere per fungere da destina-
zione di un’istruzione GOTO.
LAG
VEDERE ANCHE LEAD.
SINTASSI
DESCRIZIONE LAG consente di accedere contemporaneamente a più righe di una tabella senza
un self-join. Con una serie di righe restituite da una query e una posizione del cursore, LAG
consente di accedere a una riga che si trova in un determinato offset fisico che precede questa
posizione.
LANCIARE
In Java, i programmi lanciano le eccezioni tramite la clausola try, e le elaborano con la clausole
catch e finally. Vedere il Capitolo 37.
LAST
VEDERE ANCHE DENSE_RANK, FIRST.
SINTASSI
funzione_aggregazione_ KEEP
( DENSE_RANK LAST ORDER BY
expr [ DESC | ASC ] [ NULLS { FIRST | LAST }]
[, expr [ DESC | ASC ] [ NULLS { FIRST | LAST }]]...
) [OVER clausola_partizionamento_query]
GUIDA DI RIFERIMENTO ALFABETICA 1165
DESCRIZIONE LAST è sia una funzione di aggregazione sia una funzione analitica che opera su
un gruppo di valori tratti da un gruppo di righe che compaiono per ultime rispetto a una determi-
nata specifica di ordinamento. funzione_aggregazione è una delle funzioni di gruppo numeriche
standard (come MIN, MAX, AVG e STDDEV).
LAST_DAY
VEDERE ANCHE ADD_MONTHS; DATE, FUNZIONI; Capitolo 10.
SINTASSI
LAST_DAY (data)
DESCRIZIONE LAST_DAY fornisce la data dell’ultimo giorno del mese cui appartiene la data
indicata.
ESEMPIO
Questa istruzione:
LAST_DAY ('05.11.01')
LAST_VALUE
VEDERE ANCHE FIRST_VALUE.
SINTASSI
LEAD
VEDERE ANCHE LAG.
SINTASSI
LEAS T
VEDERE ANCHE GREATEST, FUNZIONI DI ELENCO, Capitolo 10.
SINTASSI
LENGTH
VEDERE ANCHE CARATTERI, FUNZIONI; VSIZE; Capitolo 7.
SINTASSI
LENGTH(stringa)
DESCRIZIONE LENGTH indica la lunghezza di una stringa, di un numero, di una data o di una
espressione. La stringa può essere di tipo CHAR (la lunghezza restituita includerà tutti gli spazi
iniziali), VARCHAR2, NCHAR, NVARCHAR2, CLOB o NCLOB. Esistono diverse funzioni
LENGTH, che seguono tutte il medesimo formato:
■ LENGTH calcola la lunghezza utilizzando i caratteri nel modo definito dal set di caratteri di
input.
■ LENGTHB utilizza i byte invece dei caratteri.
■ LENGTHC utilizza tutti i caratteri del set Unicode.
■ LENGTH2 utilizza i punti del codice UCS2.
■ LENGTH4 utilizza i punti del codice UCS4.
LEVEL
VEDERE ANCHE CONNECT BY, PSEUDOCOLONNE, Capitolo 13.
SINTASSI
LEVEL
DESCRIZIONE Level è una pseudocolonna, utilizzata con CONNECT BY, il cui valore è 1 nel
nodo principale, 2 per un figlio di primo livello, 3 per un figlio di secondo livello e così via.
Level fornisce un’indicazione di quanti livelli dell’albero sono stati analizzati.
LGWR
LGWR (LoG WRiter process) scrive voci redo log dalla SGA nei redo log in linea. Vedere
BACKGROUND, PROCESSO.
LIBRERIA
I blocchi PL/SQL possono fare riferimento a sottoprogrammi esterni, memorizzati in librerie.
Vedere CREATE LIBRARY.
GUIDA DI RIFERIMENTO ALFABETICA 1167
LIKE
VEDERE ANCHE OPERATORI LOGICI, Capitolo 3.
SINTASSI
DESCRIZIONE LIKE esegue una ricerca per modelli. Un carattere di sottolineatura rappresenta
uno e un solo spazio. Un segno di percentuale rappresenta un numero qualsiasi di spazi o carat-
teri, incluso il valore zero. Se LIKE ha un _ o un % nella prima posizione di un confronto (come
nel secondo e nel terzo degli esempi proposti) qualsiasi indice sulla colonna viene ignorato.
ESEMPI
LIMITAZIONE
Una regola o una limitazione riguardante una parte di dati (come una limitazione NOT NULL su
una colonna) che viene imposta a livello di dati, anziché a livello di applicazione o di oggetto.
Vedere VINCOLO DI INTEGRITÀ.
LINESIZE (SQL*Plus)
Vedere SET.
LIST (SQL*Plus)
VEDERE ANCHE APPEND, CHANGE, EDIT, INPUT, RUN, Capitolo 6.
SINTASSI
DESCRIZIONE LIST elenca le linee del buffer corrente a partire da inizio fino a fine. Gli estremi
sono entrambi numeri interi. La riga finale diventa la riga corrente del buffer e viene evidenziata
con un asterisco. LIST senza parametri elenca tutte le linee. Un asterisco in una delle due posi-
zioni la imposta alla linea corrente. LIST con un solo parametro visualizza solo la linea richiesta,
mentre LIST * visualizza la sola linea corrente. Lo spazio tra LIST e inizio non è necessario ma
aiuta la leggibilità. LIST n* elenca tutte le linee dalla n alla fine. LIST *n elenca tutte le linee
dall’inizio alla linea specificata.
ESEMPIO
Per elencare il buffer corrente di SQL, si utilizzi quanto segue:
LIST
Un asterisco indica la linea corrente. Per elencare solo la seconda linea, si digiti:
1168 CAPITOLO 48
LIST 2
Con questa chiamata anche 2 si trasforma nella linea del buffer corrente.
LN
VEDERE ANCHE NUMERI, FUNZIONI ; Capitolo 9.
SINTASSI
LN(numero)
LNNVL
VEDERE ANCHE SELECT.
SINTASSI
LNNVL ( condizione )
DESCRIZIONE LNNVL offre un modo per valutare una condizione quando uno o entrambi gli
operandi della condizione possono essere nulli. La funzione può essere utilizzato solo nella
clausola WHERE di una query. Come argomento accetta una condizione e restituisce TRUE se
quest’ultima è FALSE o UNKNOWN, oppure restituisce FALSE se la condizione è TRUE. LNNVL
può essere utilizzata ovunque possa apparire un’espressione scalare, anche in contesti in cui le
condizioni IS [NOT] NULL, AND o OR non sono valide ma sarebbero altrimenti richieste per
rendere conto dei null potenziali. LNNVL può apparire negli explain plan quando Oracle
internamente richiede condizioni NOT IN come condizioni NOT EXISTS.
ESEMPI
Se si desidera recuperare tutte le righe per le quali una colonna è maggiore di un dato valore, la
sintassi standard sarebbe la seguente:
Per restituire anche le righe per cui colonna è NULL, occorre utilizzare LNNVL:
LOADJAVA
LOADJAVA è un utility che serve per caricare le classi, le risorse e i sorgenti Java nel database.
Se si intende utilizzare le classi Java nelle stored procedure, le si dovrà caricare nel database. Per
rimuovere le classi Java dal database, si utilizzi l’utility DROPJAVA. Vedere il Capitolo 39.
LOB
Un LOB è un oggetto molto grande. Oracle supporta diversi tipi di dati di grandi dimensioni, tra
cui i BLOB (binary large object), i CLOB (character large object) e i BFILE (binary file, memo-
rizzati all’esterno del database). Vedere il Capitolo 32 e la clausola LOB di CREATE TABLE.
GUIDA DI RIFERIMENTO ALFABETICA 1169
LOBOFFSET (SQL*Plus)
Vedere SET.
LOBSOURCE (SQL*Plus)
Vedere SET.
LOCALTIMESTAMP
VEDERE ANCHE DATE, FUNZIONI; Capitolo 10.
SINTASSI
LOCALTIMESTAMP [( precisione_indicatore_orario )]
DESCRIZIONE LOCALTIMESTAMP restituisce la data o l’orario correnti nel fuso orario della
sessione come un valore del tipo di dati TIMESTAMP.
ESEMPIO
LOCK TABLE
VEDERE ANCHE COMMIT, DELETE, INSERT, ROLLBACK, SAVEPOINT, UPDATE.
SINTASSI
LOCK TABLE
[schema .] { tabella | vista }
[ { PARTITION ( partizione ) | SUBPARTITION ( partizione_secondaria ) }
| @ dblink ]
[, [schema .] { tabella | vista }
[ { PARTITION ( partizione ) | SUBPARTITION ( partizione_secondaria ) }
| @ dblink ] ]...
IN modalità_lock MODE [NOWAIT];
DESCRIZIONE LOCK TABLE blocca una tabella con una delle modalità specificate che ne per-
mettono la condivisione senza compromettere l’integrità dei dati. L’uso di LOCK TABLE permet-
te di concedere ad altri utenti l’accesso continuato ma parziale alla tabella. A prescindere dal-
l’opzione scelta, la tabella resta nella modalità di lock richiesta fino a che non si effettua un
COMMIT o un ROLLBACK sulle proprie transazioni.
Le modalità di lock comprendono ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE,
SHARE, SHARE ROW EXCLUSIVE ed EXCLUSIVE.
I blocchi di tipo EXCLUSIVE consentono agli utenti di eseguire solamente la query sulla
tabella bloccata e null’altro. Nessun altro utente può bloccare la tabella. I blocchi SHARE per-
mettono query concorrenti ma vietano qualsiasi aggiornamento della tabella bloccata.
Con un blocco di tipo ROW SHARE o SHARE UPDATE, nessun utente può bloccare l’in-
tera tabella per accedervi esclusivamente. Di fatto si permettono accessi concorrenti alla tabella
da parte di tutti gli utenti. I due tipi di blocchi sono sinonimi: SHARE UPDATE esiste solo per
compatibilità con versioni precedenti di Oracle.
1170 CAPITOLO 48
I blocchi ROW EXCLUSIVE sono simili a quelli di tipo ROW SHARE ma vietano i blocchi
condivisi (per cui un solo utente per volta può accedere alla tabella).
Se un comando LOCK TABLE ha dei problemi a portare a termine il proprio compito (in
genere quando qualcun altro ha eseguito un comando analogo quasi nello stesso momento) aspet-
terà fino alla conclusione della situazione concorrente. Se si vogliono evitare problematiche di
questo tipo e si desidera che il controllo torni al programma occorre utilizzare l’opzione NOWAIT.
Si noti che è possibile bloccare partizioni e partizioni secondarie specifiche.
LOG
VEDERE ANCHE NUMERI, FUNZIONI; Capitolo 9.
SINTASSI
LOG(base, numero)
LOGIN ACCOUNT
Un login account è un’accoppiata di nome utente e password che permette agli utenti di utilizza-
re l’RDBMS di Oracle. In genere, questo account è distinto da quello del sistema operativo.
LONG (SQL*Plus)
Vedere SET.
LOWER
VEDERE ANCHE CARATTERI, FUNZIONI; INITCAP; UPPER; Capitolo 7.
SINTASSI
LOWER(stringa)
LOWER('PeniSola') = penisola
LPAD
VEDERE ANCHE CARATTERI, FUNZIONI; LTRIM; RPAD; RTRIM; Capitolo 7.
SINTASSI
LPAD(stringa,lunghezza [,'set'])
DESCRIZIONE LPAD fa in modo che una stringa raggiunga una determinata lunghezza aggiun-
gendo un certo set di caratteri a sinistra della stringa. Se non si specifica set, il carattere di
riempimento predefinito è lo spazio.
ESEMPIO
LPAD('>',11,'- ')
produce
- - - - - >
LTRIM
VEDERE ANCHE CARATTERI, FUNZIONI; LPAD; RPAD; RTRIM; Capitolo 7.
SINTASSI
LTRIM(stringa [,'set'])
DESCRIZIONE LTRIM taglia tutte le occorrenze (anche parziali) di un set di caratteri dall’estre-
mità sinistra di una stringa.
ESEMPIO
LTRIM('NANCY','AN')
produce:
CY
1172 CAPITOLO 48
MAKE_REF
VEDERE ANCHE Capitolo 36.
SINTASSI
MAX
VEDERE ANCHE COMPUTE, FUNZIONI DI GRUPPO, MIN Capitolo 8.
SINTASSI
DESCRIZIONE MAX è il massimo di tutti i valori di un gruppo di righe. MAX ignora la presenza
di valori NULL. L’opzione DISTINCT non è significativa dato che il massimo di tutti i valori
coincide con il massimo dei valori separati.
MEDIAN
VEDERE ANCHE AVG, COUNT.
SINTASSI
MERGE
VEDERE ANCHE INSERT, UPDATE, Capitolo 15.
SINTASSI
merge::=
table
schema . t_alias
USING view ON ( condition )
subquery
merge_update_clause merge_insert_clause
GUIDA DI RIFERIMENTO ALFABETICA 1173
merge_update_clause::=
expr
WHEN MATCHED THEN UPDATE SET column =
DEFAULT
merge_insert_clause::=
( column )
WHEN NOT MATCHED THEN INSERT
expr where_clause
VALUES ( )
DEFAULT
where_clause::=
WHERE condition
NOTA Dal momento che MERGE esegue delle query, è possibile utilizzare i
suggerimenti.
METODO
Un metodo è un blocco di codice. Con riferimento ai tipi di dati astratti, un metodo è un blocco
di codice PL/SQL utilizzato per incapsulare i metodi di accesso ai dati di un oggetto. I metodi
sono specificati come parte della specifica dei tipi di dati astratti (vedere CREATE TYPE) men-
tre il loro corpo è specificato come parte del comando CREATE TYPE BODY. Gli utenti possono
1174 CAPITOLO 48
eseguire i metodi sui tipi di dati per cui sono stati definiti. Il constructor method creato per
ciascun tipo di dati astratto è un esempio di metodo. Per esempi di metodi si consulti il Capitolo 30.
In Java, un metodo è un membro di una classe. Si può chiamare il metodo di una classe e
passargli dei parametri in modo che li possa usare quando esegue i propri comandi. Per esempi,
si consulti il Capitolo 33.
MIN
VEDERE ANCHE COMPUTE, FUNZIONI DI GRUPPO, MAX, Capitolo 9.
SINTASSI
DESCRIZIONE MIN è il minimo di tutti i valori di un gruppo di righe. MIN ignora la presenza di
valori NULL. L’opzione DISTINCT non è significativa dato che il minimo di tutti i valori è identi-
co al minimo di valori presi distintamente.
MINUS
VEDERE ANCHE INTERSECT, OPERATORI DI QUERY, UNION, OPERATORI DI RICER-
CA TESTUALE, Capitoli 13 e 25.
SINTASSI
select
MINUS
select
select colonna
from TABELLA
where CONTAINS(Text,'text MINUS text') >0;
DESCRIZIONE MINUS combina due query. Restituisce solo le righe dalla prima istruzione
select che non sono prodotte dalla seconda istruzione select (il risultato della prima MENO il
risultato della seconda). Il numero di colonne e i tipi di dati devono essere identici tra le istruzio-
ni select, condizione non richiesta per i nomi delle colonne. Tuttavia, i dati devono essere uguali
nelle righe prodotte perché MINUS li possa rifiutare. Per una discussione sulle differenze impor-
tanti e sugli effetti di INTERSECT, MINUS e UNION, si consulti il Capitolo 12.
Nelle ricerche testuali eseguite sugli indici CONTEXT, MINUS indica alla ricerca di testo di
due termini di sottrarre il punteggio ottenuto dalla ricerca del secondo termine da quello della
ricerca del primo, prima di confrontare il risultato con il punteggio di soglia.
MOD
VEDERE ANCHE NUMERI, FUNZIONI; Capitolo 9.
SINTASSI
MOD(valore, divisore)
GUIDA DI RIFERIMENTO ALFABETICA 1175
DESCRIZIONE MOD divide un valore per un divisore e fornisce il resto. MOD(23,6) = 5 signi-
fica dividere 23 per 6. Il 6 nel 23 sta 3 volte col resto di 5, e questo è il risultato del modulo.
valore e divisore possono essere numeri reali qualsiasi, ma il divisore non può essere uguale a 0.
ESEMPI
MOD(100,10) = 0
MOD(22,23) = 22
MOD(10,3) = 1
MOD(-30.23,7) = -2.23
MOD(4.1,.3) = .2
Il secondo esempio mostra il comportamento di MOD qualora il divisore sia più grande del
dividendo (il numero da dividere). Il risultato è il dividendo stesso. Si noti anche il caso importante:
MOD(valore,1) = 0
è vera se valore è un numero intero. Questo è un ottimo trucco per verificare che un numero sia
effettivamente un intero.
MONTHS_BETWEEN
VEDERE ANCHE ADD_MONTHS; DATE, FUNZIONI; Capitolo 10.
SINTASSI
MONTHS_BETWEEN(data2,data1)
MOUNT DI UN DATABASE
L’esecuzione del MOUNT di un database equivale a renderlo disponibile all’amministratore del
database.
NANVL
VEDERE ANCHE LNNVL.
SINTASSI
MOD(valore, divisore)
NCHAR
NCHAR è una versione a più byte del tipo di dati CHAR. Memorizza dati carattere a lunghezza
fissa fino a 2.000 byte di lunghezza. Vedere DATI, TIPI.
NCHR
VEDERE ANCHE CHR.
SINTASSI
NCHR(numero)
DESCRIZIONE NCHR restituisce il carattere che nel set di caratteri nazionale possiede l’equi-
valente binario di numero.
NCLOB
Il tipo di dati NCLOB, è la versione a più byte del tipo di dati CLOB. NCLOB memorizza
oggetti di grandi dimensioni che contengono caratteri UNICODE, fino a una lunghezza massima
di 4GB. Vedere DATI, TIPI.
NEAR
VEDERE ANCHE CONTAINS, Capitolo 25.
DESCRIZIONE Negli indici CONTEXT, NEAR indica di eseguire una ricerca di prossimità per
le stringhe di testo specificate. Se i termini da cercare fossero ‘estate’ e ‘vacanza’, una ricerca di
prossimità potrebbe essere strutturata nella maniera seguente:
select Testo
from SONNET
where CONTAINS(Testo,'estate NEAR vacanza') >0;
Quando si valutano i risultati della ricerca testuale, le righe contenenti ‘estate’ e ‘vacanza’ in
stretta prossimità ottengono punteggi maggiori di quelle in cui le due parole distano di più.
NEWPAGE (SQL*Plus)
Vedere SET.
NEW_TIME
Vedere DATE, FUNZIONI.
NEXT_DAY
Vedere DATE, FUNZIONI.
GUIDA DI RIFERIMENTO ALFABETICA 1177
NEXTVAL
Vedere PSEUDOCOLONNE.
NLS_CHARSET_DECL_LEN
VEDERE ANCHE NCHAR.
SINTASSI
NLS_CHARSET_ID
VEDERE ANCHE NLS_CHARSET_NAME.
SINTASSI
NLS_CHARSET_ID ( testo )
NLS_CHARSET_NAME
VEDERE ANCHE NLS_CHARSET_ID.
SINTASSI
NLS_CHARSET_NAME ( numero )
NLS_INITCAP
VEDERE ANCHE CARATTERI, FUNZIONI, INITCAP, Capitolo 7.
SINTASSI
NLS_INITCAP(numero[, parametri_nls])
DESCRIZIONE NLS_INITCAP è analoga alla funzione INITCAP tranne per l’aggiunta di una
stringa di parametri. La stringa parametri NLS racchiusa tra apici fornisce una sequenza di ordi-
namento per rendere maiuscole alcune sequenze di caratteri particolari di alcuni linguaggi inter-
nazionali. INITCAP verrà utilizzata con la sequenza di ordinamento predefinita per la sessione,
tuttavia questa funzione consente di specificare l’esatta sequenza di ordinamento da utilizzare.
1178 CAPITOLO 48
NLS_LOWER
VEDERE ANCHE CARATTERI, FUNZIONI; LOWER; Capitolo 7.
SINTASSI
NLS_LOWER(numero[, parametri_nls])
DESCRIZIONE NLS_LOWER è analoga alla funzione LOWER salvo per l’aggiunta di una strin-
ga di parametri. La stringa parametri NLS racchiusa tra apici fornisce una sequenza di ordina-
mento per rendere minuscole delle sequenze di caratteri particolari di alcuni linguaggi interna-
zionali. LOWER verrà utilizzata con la sequenza di ordinamento predefinita per la sessione,
tuttavia questa funzione consente di specificare l’esatta sequenza di ordinamento da utilizzare.
NLS_UPPER
VEDERE ANCHE CARATTERI, FUNZIONI; UPPER; Capitolo 7.
SINTASSI
NLS_UPPER(numero[, parametri_nls])
DESCRIZIONE NLS_UPPER è analoga alla funzione UPPER salvo per l’aggiunta di una strin-
ga di parametri. La stringa parametri NLS racchiusa tra apici fornisce una sequenza di ordina-
mento per rendere maiuscole alcune sequenze di caratteri particolari di alcuni linguaggi interna-
zionali. UPPER verrà utilizzata con la sequenza di ordinamento predefinita per la sessione, tut-
tavia questa sessione consente di specificare l’esatta sequenza di ordinamento da utilizzare.
NLSSORT
VEDERE ANCHE CREATE DATABASE.
SINTASSI
NLSSORT(carattere[,parametri_nls])
DESCRIZIONE NLSSORT fornisce il valore (intero) della sequenza di ordinamento del caratte-
re specificato basato sull’opzione National Language Support selezionata per il sito. La stringa
parametri NLS racchiusa tra apici fornisce una sequenza di ordinamento per sequenze linguisti-
che particolari, se non si desidera ricorrere all’impostazione predefinita per la sessione o il
database.
NOAUDIT
VEDERE ANCHE AUDIT, PRIVILEGI.
SINTASSI
noaudit::=
,
NOT
sql_statement_clause
WHENEVER SUCCESSFUL
NOAUDIT , ;
schema_object_clause
GUIDA DI RIFERIMENTO ALFABETICA 1179
sql_statement_clause::=
statement_option
ALL
auditing_by_clause
,
system_privilege
ALL PRIVILEGES
auditing_by_clause::=
proxy
BY ,
user
schema_object_clause::=
object_option
auditing_on_clause
ALL
auditing_on_clause::=
schema .
object
ON DIRECTORY directory_name
DEFAULT
DESCRIZIONE NOAUDIT interrompe l’audit delle istruzioni SQL tenute sotto controllo a se-
guito del comando AUDIT. Interrompe l’audit sia di istruzioni semplici (vedere AUDIT) sia di
quelle autorizzate da privilegi di sistema (vedere PRIVILEGI). Se è presente la clausola BY e
una lista di utenti, il comando interrompe l’audit delle istruzioni da essi impartite. In caso con-
trario, Oracle interrompe l’audit delle istruzioni impartite da tutti gli utenti. L’opzione WHENEVER
SUCCESSFUL interrompe l’audit solo per le istruzioni completate con successo; WHENEVER
NOT SUCCESSFUL disabilita l’audit delle istruzioni che generano errori.
NOAUDIT interrompe anche l’audit di un’opzione per l’uso di una tabella, di una vista o di
un sinonimo. A tal fine, si devono possedere gli oggetti appena elencati o avere il privilegio
1180 CAPITOLO 48
DBA. opzione è una delle opzioni descritte di seguito. utente è il nome utente del proprietario
dell’oggetto. oggetto è una tabella, una vista o un sinonimo. opzione specifica per quali comandi
interrompere l’audit. ON oggetto assegna un nome agli oggetti controllati e include tabelle, viste
oppure sinonimi di tabelle, viste o sequenze. ALL interrompe l’audit di tutti questi.
Per dettagli sulle viste di audit del dizionario dati, si consulti il Capitolo 42.
ESEMPI
La riga seguente interrompe l’audit di tutti i tentativi di aggiornamento o cancellazione della
tabella BIBLIOTECA:
Questa riga interrompe l’audit di tutti gli accessi alla tabella BIBLIOTECA che non abbiano
avuto successo:
NODO
Esistono due definizioni di nodo:
■ Nelle tabelle strutturate ad albero un nodo non è altro che una riga.
■ In una rete, un nodo è il punto fisico nella rete a cui viene collegato un computer.
NODO TERMINALE
In una tabella strutturata ad albero, un nodo terminale è una riga che non ha alcuna riga figlia. È
equivalente a una foglia.
NOLOGGING
La clausola NOLOGGING nella creazione di oggetti (tabelle, LOB, indici, partizioni e così via)
specifica che questa operazione non verrà trascritta nei redo log file in linea; per questo motivo
non sarà recuperabile dopo un errore di disco. La creazione di oggetti non viene registrata, così
come alcuni tipi di transazioni sugli oggetti. NOLOGGING occupa lo spazio della parola chiave
UNRECOVERABLE introdotta con Oracle7.2. Si faccia riferimento ai Capitoli 21 e 46.
NOME DI SERVIZIO
Un nome di servizio, che si trova nel file tnsnames.ora, è un alias per un database cui si può
accedere con Oracle Net. Nel file tnsnames.ora, il nome di servizio viene associato a un host, a
una porta o a un’istanza. Quindi, è possibile modificare il nome di servizio di un database senza
cambiare il nome del database e si può anche spostare un database in un host diverso senza
modificare il suo nome di servizio.
■ Il nome di un oggetto può avere una lunghezza compresa tra 1 e 30 caratteri, tranne per i
nomi di database, che sono lunghi fino a otto caratteri, e i nomi dei file di host, la cui lunghezza
dipende dal sistema operativo.
■ I nomi non possono contenere virgolette.
■ Un nome deve iniziare con una lettera, contenere solo i caratteri A-Z, 0-9, $, #, e _, non deve
essere una parola riservata di Oracle (vedere PAROLE RISERVATE), non deve duplicare il nome
di un altro oggetto del database posseduto dallo stesso utente.
Lettere maiuscole o minuscole non fanno differenza nei nomi degli oggetti. I nomi degli
oggetti dovrebbero seguire una convenzione di denominazione sensata, come discusso nel Ca-
pitolo 2.
NON-EQUI-JOIN
Un non-equi-join è una condizione di join diversa da quella di uguaglianza (=). Vedere EQUI-
JOIN.
NOT
VEDERE ANCHE OPERATORI LOGICI, Capitolo 5.
DESCRIZIONE NOT precede e completa l’effetto di ciascuno dei seguenti operatori logici:
BETWEEN, IN, LIKE ed EXISTS. NOT può precedere anche NULL come in IS NOT NULL.
NOT EXISTS
VEDERE ANCHE ANY, ALL, EXISTS, IN, Capitolo 13.
SINTASSI
select ...
where NOT EXISTS (select...);
DESCRIZIONE NOT EXISTS restituisce un valore falso in una clausola where se la subquery
che lo segue restituisce una o più righe. La clausola select della subquery può essere una colon-
na, un letterale o un asterisco, non ha importanza. L’unica parte importante è se la clausola
where della subquery restituisce oppure no una riga.
ESEMPIO
NOT EXISTS viene utilizzato spesso per determinare quali record di una tabella non hanno
record corrispondenti in un’altra. Per esempi dell’uso di NOT EXISTS si rimanda al Capitolo 13.
NTILE
VEDERE ANCHE WIDTH_BUCKET.
SINTASSI
DESCRIZIONE NTILE è una funzione analitica. Divide un gruppo di dati ordinati in un numero
di bucket indicato da un’espressione e assegna il numero di bucket adeguato a ogni riga. I bucket
1182 CAPITOLO 48
sono numerati e l’espressione deve dare come risultato una costante positiva per ciascuna
partizione.
NULL;
DESCRIZIONE L’istruzione NULL non ha nulla a che vedere con i valori NULL. Il suo scopo
principale è rendere più leggibile una sezione di codice dicendo, letteralmente, di “non fare
nulla”. È anche un espediente per creare blocchi nulli (dato che PL/SQL vuole almeno un’istru-
zione eseguibile tra BEGIN ed END). In genere viene utilizzato come l’istruzione successiva
(solitamente l’ultima) a una di una serie di test condizionali.
ESEMPIO
Dato che NULL rappresenta un valore sconosciuto, due colonne NULL non sono uguali.
Perciò il segno di uguale e gli altri operatori logici (tranne IS NULL e IS NOT NULL) non funzio-
nano con valori NULL. Per esempio, questo listato:
non è una clausola where valida. NULL richiede necessariamente la parola chiave IS:
Durante gli ordinamenti di tipo order by, i valori NULL precedono sempre tutti gli altri negli
ordinamenti crescenti e vengono per ultimi in quelli decrescenti.
Quando si memorizzano valori NULL in un database, essi vengono rappresentati con un
unico byte se ricadono tra due colonne di valori reali e con nessun byte se cadono al fondo di una
riga (oltre il margine di colonna definito da create table). Se alcune colonne di una tabella sono
destinate a contenere spesso valori NULL conviene raggrupparle verso il fondo dell’elenco di
colonne di create table; in questo modo si riesce a risparmiare dello spazio su disco.
I valori NULL non compaiono negli indici; l’unico caso contrario è quello in cui tutti i valori
di una chiave di clusterizzazione sono NULL.
NULLIF
VEDERE ANCHE COALESCE, DECODE, NULL, Capitolo 16.
SINTASSI
DESCRIZIONE NULLIF confronta espr1 e espr2. Se sono uguali, la funzione restituisce NULL.
Altrimenti, la funzione restituisce espr1. Non si può specificare il letterale NULL per espr1.
La funzione NULLIF è logicamente equivalente alla seguente espressione CASE:
NUMERICI, FORMATI
VEDERE ANCHE COLONNA, Capitolo 9.
DESCRIZIONE Queste opzioni funzionano sia con il comando SET NUMFORMAT che con
COLUMN FORMAT:
1184 CAPITOLO 48
9999990 Il conteggio dei nove e zero determina le cifre massime che possono essere visualizzate.
B99999 Non viene visualizzato niente se il valore è zero. Questo è il valore predefinito.
99999MI Se il numero è negativo, un segno meno segue il numero. Per default il segno negativo è sulla sinistra.
S9999 Restituisce “+” per i valori positivi, "–" per quelli negativi.
. Visualizza un punto.
999V99 Moltiplica il numero per 10n, dove n rappresenta il numero di cifre alla destra di V. 999V99 trasforma
1234 in 123400.
U999 Restituisce il simbolo dell’Euro o un altro simbolo di valuta duale nella posizione specificata.
NUMERI, FUNZIONI
Di seguito è riportato un elenco ordinato di tutte le funzioni numeriche a singolo valore supportate
attualmente dal linguaggio SQL di Oracle. Ciascuna viene riportata altrove in questa guida,
assieme alla sintassi e ad esempi d’uso. Ogni funzione può essere utilizzata come una funzione
SQL normale così come una funzione PL/SQL. Si consultino anche FUNZIONI DI GRUPPO e
FUNZIONI DI ELENCO.
FUNZIONE DEFINIZIONE
valore1 + valore2 Addizione.
(segue)
GUIDA DI RIFERIMENTO ALFABETICA 1185
(continua)
BITAND(valore1, valore2) AND BIT per BIT di valore1 e valore2: entrambi devono dare come risultato interi non negativi e restituire
un valore intero.
NANVL(valore1, valore2) Per i numeri BINARY_FLOAT e BINARY_DOUBLE, restituisce valore2 se valore1 non è un numero.
NUMERO DI VERSIONE
Il numero di versione è il numero di identificazione principale del software Oracle. In Oracle9i
Release 9.0.1.0, 9 è il numero di versione.
NUMTODSINTERVAL
VEDERE ANCHE DATI, TIPI; Capitolo 11.
SINTASSI
NUMTODSINTERVAL ( n , 'espr_car' )
NUMTOYMINTERVAL
VEDERE ANCHE DATI, TIPI; Capitolo 11.
SINTASSI
NUMTOYMINTERVAL ( n , 'espr_car' )
NUMWIDTH (SQL*Plus)
Vedere SET.
NVARCHAR2
NVARCHAR2 è l’equivalente a più byte del tipo di dati VARCHAR2. La sua lunghezza massi-
ma è pari a 4.000 byte. Vedere DATI, TIPI.
NVL
VEDERE ANCHE FUNZIONI DI GRUPPO, NULL, ALTRE FUNZIONI, Capitolo 9.
GUIDA DI RIFERIMENTO ALFABETICA 1187
SINTASSI
NVL(valore, sostituto)
DESCRIZIONE Se valore è NULL, questa funzione restituisce sostituto. Se valore non è NULL,
questa funzione restituisce valore. valore può essere qualsiasi tipo di dati di Oracle. sostituto
può essere un letterale, un’altra colonna o un’espressione, ma deve essere dello stesso tipo di
valore.
NVL2
VEDERE ANCHE FUNZIONI DI GRUPPO, NULL, ALTRE FUNZIONI, Capitolo 9.
SINTASSI
DESCRIZIONE NVL2 è una versione estesa di NVL. In NVL2, espr1 non potrà mai essere resti-
tuita; al suo posto verranno restituire espr2 o espr3. Se espr1 non è NULL, NVL2 restituisce
espr2. Se espr1 è NULL, NVL2 restituisce espr3. L’argomento espr1 può avere qualsiasi tipo di
dati. Gli argomenti espr2 e espr3 possono avere qualunque tipo di dati tranne LONG.
OGGETTO
Un oggetto è un elemento del database Oracle cui è possibile assegnare un nome. Gli oggetti
possono dunque essere tabelle, indici, sinonimi, procedure e trigger.
OID
Un OID è un identificativo oggetto assegnato da Oracle a ciascun oggetto di un database. Per
esempio, ogni oggetto riga di una tabella oggetto ha un proprio OID che viene utilizzato per
risolvere i riferimenti agli oggetti riga. Oracle non riutilizza gli OID dopo che un oggetto è stato
cancellato. Vedere il Capitolo 36.
OPEN
VEDERE ANCHE CLOSE, DECLARE CURSOR, FETCH, LOOP, Capitolo 29.
SINTASSI
Esiste anche un metodo alternativo per associare i valori di OPEN a quelli dell’elenco di
SELECT:
DECLARE
cursor mycur(Titolo, Editore) is select ...
BEGIN
open my_cur(nuovo_libro = Titolo, 'PANDORAS' = Editore);
In questo caso, nuovo_libro, una variabile PL/SQL caricata forse da una schermata di im-
missione dei dati, punta a Titolo, quindi lo carica qualsiasi sia il valore contenuto attualmente
nella variabile. Editore viene caricato con il valore ‘PANDORAS’, e questi diventeranno i para-
metri del cursore my_cur (per ulteriori informazioni sui parametri nei cursori, si rimanda a
DECLARE CURSOR).
È inoltre possibile combinare associazioni puntate con associazioni posizionali, ma queste
ultime devono apparire per prime nell’elenco di OPEN.
Non è possibile riaprire un cursore già aperto, sebbene lo si possa chiudere e riaprire. Non si
può utilizzare un cursore per il quale vi sia un’istruzione OPEN pendente in un ciclo FOR.
OPERATORE
Un operatore è un carattere o una parola riservata impiegato in un’espressione per eseguire
un’operazione, come una somma o una comparazione, sugli elementi dell’espressione stessa.
GUIDA DI RIFERIMENTO ALFABETICA 1189
Alcuni esempi di operatori sono * (moltiplicazione), > (maggiore di) e ANY (confronta un valore
con tutti quelli restituiti da una subquery).
OPERATORE RELAZIONALE
Un operatore relazionale è un simbolo utilizzato in un’espressione di ricerca per indicare un
confronto tra due valori, come il segno di uguale in “where Importo = .10”. Vengono restituite
soltanto le righe per le quali il confronto risulta TRUE.
OPERATORI DI QUERY
Di seguito è riportato un elenco alfabetico di tutti gli operatori di query correnti del SQL di
Oracle. Ciascuno viene riportato altrove in questa guida, assieme alla sintassi e ad esempi d’uso.
Vedere anche il Capitolo 13.
OPERATORE SCOPO
INTERSECT Restituisce tutte le righe corrispondenti da due query (senza ripetizioni).
MINUS Restituisce tutte le righe distinte della prima query che non sono presenti nella seconda.
UNION ALL Restituisce tutte le righe di una coppia di query (con eventuali ripetizioni).
OPERATORI INSIEMISTICI
Gli operatori di tipo insiemistico sono UNION, INTERSECT e MINUS. Vedere anche OPERA-
TORI DI QUERY.
OPERATORI LOGICI
VEDERE ANCHE PRECEDENZE.
SINTASSI
L’elenco seguente mostra tutti gli operatori logici attualmente supportati dal linguaggio SQL di
Oracle. La maggior parte di essi è trattata altrove in questo stesso glossario assieme alla propria
sintassi e agli esempi d’uso. Tutti questi operatori lavorano con colonne o con letterali.
= espressione è uguale a
> espressione è maggiore di
>= espressione è maggiore o uguale a
< espressione è minore di
<= espressione è minore o uguale a
!= espressione è diverso da
^= espressione è diverso da
<> espressione è diverso da
1190 CAPITOLO 48
EXISTS (query)
NOT EXISTS (query)
LIKE espressione
NOT LIKE espressione
espressione IS NULL
espressione IS NOT NULL
ANY e ALL richiedono un operatore Uguale a come prefisso, per esempio >ANY, =ALL e così via.
+ Addizione
- Sottrazione
* Moltiplicazione
/ Divisione
** Elevamento a potenza
|| Concatenazione
() Ignora le normali regole di precedenza, o racchiude una subquery
NOT Inverte l'espressione logica
AND Combina espressioni logiche
OR Combina espressioni logiche
UNION Combina i risultati delle query
UNION ALL Combina i risultati delle espressioni senza eliminare i duplicati INTERSECT
INTERSECT Combina i risultati delle query
MINUS Combina i risultati delle query
OPERATORI SINTATTICI
VEDERE ANCHE OPERATORI LOGICI, PRECEDENZE.
DESCRIZIONE Gli operatori sintattici hanno la precedenza più alta tra tutti gli operatori, e
possono comparire ovunque all’interno di istruzioni SQL. Di seguito sono elencati in ordine
decrescente di precedenza. Gli operatori con la stessa precedenza vengono valutati da sinistra a
destra. La maggior parte di questi operatori è elencata e descritta separatamente in questo stesso
capitolo.
OPERATORE FUNZIONE
- Continuazione di un comando SQL*PLUS. Continua un comando sulla linea seguente.
& Prefisso dei parametri di un file di avvio di SQL*PLUS. Al posto di &1, &2, ecc. vengono sostituiti i
parametri della linea di comando. Vedere START.
(segue)
GUIDA DI RIFERIMENTO ALFABETICA 1191
(continua)
& && Prefisso di una variabile di sostituzione di un comando SQL in SQL*PLUS. SQL*PLUS richiede l’inseri-
mento di un valore se trova una variabile & o && non definita. && ha l’effetto di definire la variabile e
salva il valore; ‘&’ invece non lo fa. Vedere & e &&, DEFINE e ACCEPT.
. Separatore di variabili, utilizzato in SQL*PLUS per separare il nome di variabile da un suffisso in modo
che questo non sia considerato parte del nome stesso. In SQL separa nomi utente, nomi di tabella e
nomi di colonna.
' Racchiudono letterali, come stringhe di caratteri o date. Per includere un apice in una stringa, occorre
usarne due (non le virgolette).
" Racchiudono l’alias di una tabella o di una colonna che contiene caratteri speciali o spazi.
@ Precede il nome di un database nel comando COPY o il nome di un collegamento nella clausola from.
OPS$ LOGIN
Gli OPS$ LOGIN sono particolari nomi utente di Oracle, in cui OPS$ è anteposto all’ID di
account del sistema operativo dell’utente per semplificare l’accesso a Oracle da questo ID.
OR
VEDERE ANCHE AND, CONTAINS, Capitoli 5 e 25.
DESCRIZIONE OR combina espressioni logiche in modo che il risultato sia vero se almeno una
delle espressioni di partenza è vera.
ESEMPIO
L’esempio seguente produce dati sia per KEENE sia per SAN FRANCISCO:
select * from COMFORT
where Citta = 'KEENE' OR Citta = 'SAN FRANCISCO'
All’interno di query CONTEXT, l’operatore OR può essere utilizzato per ricerche che ri-
guardano più termini di ricerca. Nel caso in cui uno dei termini cercati venga trovato e il suo
punteggio superi il valore di soglia specificato, il testo viene restituito dalla ricerca. Vedere il
Capitolo 25.
ORA_HASH
SINTASSI
DESCRIZIONE ORA_HASH calcola un valore hash per una data espressione. Questa funzione
è utile per le operazioni l’analisi di un sottoinsieme di dati e la generazione di un campione
casuale. espr rappresenta i dati per i quali Oracle calcolerà un valore hash (in genere un nome di
colonna). max_bucket determina il valore massimo del bucket (da 0 a 4294967295). L’argomento
1192 CAPITOLO 48
ORDBMS
Vedere RELAZIONALE A OGGETTI, SISTEMA DI GESTIONE DI DATABASE.
ORDER BY
VEDERE ANCHE COLLATION, FROM, GROUP BY, HAVING, SELECT, WHERE, Capitolo 5.
SINTASSI
DESCRIZIONE La clausola ORDER BY fa sì che Oracle ordini i risultati di una query prima
della loro visualizzazione. Questo risultato può essere ottenuto tramite le espressioni, che posso-
no essere semplici nomi di colonna o insiemi complessi di funzioni, attraverso alias (vedere la
nota seguente) o mediante la posizione di una colonna nella clausola select (vedere la nota se-
guente). Le righe vengono ordinate in base alla prima espressione o posizione, poi in base alla
seconda e così via, seguendo la sequenza di ordinamento dell’host. Se non si specifica ORDER
BY, l’ordine con cui le righe vengono selezionate da una tabella è indeterminato e può cambiare
da una query all’altra.
NOTA Oracle supporta ancora l’uso delle posizioni di colonna nelle clausole
ORDER BY, ma questa caratteristica non fa più parte dello standard SQL e non è sicuro che
verrà supportata nelle release future. Al suo posto si utilizzano gli alias di colonna.
GUIDA DI RIFERIMENTO ALFABETICA 1193
ORDINAMENTO
VEDERE ANCHE GROUP BY, INDEX, ORDER BY, Capitolo 9.
DESCRIZIONE La sequenza di ordinamento è l’ordine in cui caratteri, numeri e simboli vengo-
no ordinati a causa di una clausola order by o group by. Queste sequenze differiscono in relazio-
ne alla sequenza di confronto del sistema operativo del computer o alla lingua della nazione. Le
sequenze EBCDIC (utilizzate solitamente per mainframe IBM e compatibili) e ASCII (utilizzate
nella maggior parte dei computer) differiscono tra loro in modo significativo. Nonostante queste
differenze, è sempre possibile applicare le seguenti regole:
■ un numero con un valore più grande viene considerato “maggiore” di quello con il valore
più piccolo; tutti i numeri negativi vengono considerati minori di quelli positivi; perciò –10 è
minore di 10; –100 è minore di –10.
■ Una data successiva è considerata maggiore di una precedente.
Le stringhe di caratteri vengono confrontate lettera per lettera a partire da quella più a sini-
stra fino al primo carattere differente. La stringa che possiede il carattere “maggiore” in quella
posizione viene considerata la più grande. Un carattere è considerato più grande di un altro
quando ha un codice ASCII (o EBCDIC) più elevato. Questo significa generalmente che B è
maggiore di A ma anche che il valore di A in rapporto ad “a” o a “1” varia da piattaforma a
piattaforma.
Queste sequenze di confronto variano leggermente a seconda se si stanno utilizzando strin-
ghe CHAR o VARCHAR2.
Se due stringhe VARCHAR2 sono identiche fino alla fine di quella più corta, la più lunga
viene considerata maggiore. Se due stringhe sono identiche e per di più hanno la stessa lunghez-
za sono considerate uguali.
Con stringhe di tipo CHAR, la stringa più breve viene riempita con spazi fino alla lunghezza
della stringa più lunga. Se dopo questa operazione le stringhe sono diverse, il confronto tratta gli
spazi aggiunti come minori di qualsiasi altro carattere, dando come risultato lo stesso valore del
confronto di tipo VARCHAR2. Se, dopo aver aggiunto gli spazi, ma non prima, le stringhe risul-
tano identiche, il confronto di tipo CHAR le tratta come uguali, a differenza di quanto fa il
confronto di tipo VARCHAR2.
In SQL è importante che i numeri letterali vengano scritti senza essere racchiusi da apici, in
quanto ‘10’ verrebbe considerato minore di ‘6’, poiché gli apici fanno in modo che vengano
considerati come stringhe di caratteri anziché numeri e ‘6’ viene considerato maggiore di ‘1’,
che si trova alla prima posizione di ‘10’.
1194 CAPITOLO 48
OTTIMIZZATORE
L’ottimizzatore è quella parte del kernel di Oracle che sceglie il modo migliore di utilizzare
tabelle e indici per completare la richiesta di un’istruzione SQL. Vedere il Capitolo 43.
OUTER JOIN
Vedere JOIN per una trattazione dettagliata. A partire da Oracle9i, si potranno utilizzare le op-
zioni per la sintassi degli outer join dello standard ANSI (LEFT OUTER JOIN, RIGHT OUTER
JOIN e FULL OUTER JOIN). Per dettagli e esempi, si rimanda al Capitolo 13.
PACKAGE
Un package è un oggetto PL/SQL che raggruppa tipi di dati PL/SQL, variabili, cursori SQL,
eccezioni, procedure e funzioni. Ogni package possiede una specifica e un corpo. La specifica
mostra gli oggetti cui si può accedere mentre si utilizza il package. Il corpo definisce completa-
mente tutti gli oggetti e può contenerne altri utilizzati solo per i processi interni. È possibile
modificare il corpo (per esempio aggiungendo nuove procedure al package) senza invalidare gli
oggetti utilizzati dal package.
Vedere CREATE PACKAGE, CREATE PACKAGE BODY, CURSORE, ECCEZIONE,
FUNZIONE, TABELLA (PL/SQL), RECORD (PL/SQL), PROCEDURA e il Capitolo 31.
PADRE
In un albero, un padre è un nodo che possiede un altro nodo sotto di lui (un figlio).
PAGESIZE (SQL*PLUS)
Vedere SET.
PARAMETRI
VEDERE ANCHE &, &&, ACCEPT, DEFINE.
DESCRIZIONE I parametri permettono di eseguire un file di avvio con valori passati dalla linea
di comando. Questi vengono inseriti semplicemente dopo il nome del file di avvio separati gli
uni gli altri da uno spazio. All’interno del file, essi sono indicati in base all’ordine in cui appari-
vano sulla linea di comando. &1 è il primo, &2 il secondo e così via. Le regole d’uso sono le
GUIDA DI RIFERIMENTO ALFABETICA 1195
stesse delle variabili caricate con DEFINE o ACCEPT e possono essere utilizzate allo stesso
modo anche nelle istruzioni SQL.
Esiste comunque una limitazione. Non esiste un modo per passare un argomento composto
da più parole a una variabile singola. Ciascuna variabile può accettare una sola parola, data o
numero. Se però si racchiudono i parametri tra apici sulla linea di comando, le parole vengono
concatenate senza particolari problemi.
ESEMPIO
Si supponga di avere un file di avvio di nome fred.sql che contiene il codice SQL seguente:
start fred.sql M
PARAMETRO
Un parametro è un valore, il nome di una colonna o un’espressione che in genere segue una
funzione o il nome di un modulo. Serve a specificare funzioni o controlli aggiuntivi che devono
essere rispettati dalla funzione o dal modulo chiamato. Per un esempio, vedere PARAMETRI.
PARENTESI
Vedere OPERATORI LOGICI e PAROLE CHIAVE E SIMBOLI PL/SQL.
PAROLE RISERVATE
VEDERE ANCHE NOMI DEGLI OGGETTI.
DESCRIZIONE Una parola riservata ha un significato particolare per SQL e per questo motivo
non può essere utilizzata come nome di un oggetto. Questo non vale per alcune parole chiave che
possono essere utilizzate come nomi di oggetti, ma in seguito possono diventare parole riservate.
Non tutte le parole sono riservate in tutti i prodotti, pertanto l’elenco seguente cerca di visualizzare
quali prodotti riservano le varie parole. Nella tabella seguente, le voci con gli asterischi sono
riservate sia in SQL sia in PL/SQL. Le voci senza asterisco sono riservate solo in PL/SQL.
(segue)
1196 CAPITOLO 48
(continua)
(segue)
GUIDA DI RIFERIMENTO ALFABETICA 1197
(continua)
PARTIZIONARE
Partizionare una tabella significa dividere sistematicamente le sue righe tra più tabelle, ciascuna
con la stessa struttura. È possibile imporre al database di partizionare automaticamente una
tabella e i relativi indici. Vedere il Capitolo 17.
PARTIZIONE COMPOSTA
Una partizione composta implica l’uso di più metodi di partizione, come una tabella partizionata
in base agli intervalli in cui le partizioni basate sugli intervalli vengono sottoposte all’hash
partitioning. Vedere il Capitolo 17.
PARTIZIONE HASH
In una partizione hash, i dati da partizionare vengono elaborati da un algoritmo di hash invece
che essere semplicemente partizionati per intervallo L’hash partitioning suddivide piccoli grup-
pi di dati sequenziali tra più partizioni rispetto al partizionamento a intervalli. Vedere CREATE
TABLE.
PARTIZIONE SECONDARIA
Una partizione secondaria è una partizione di una partizione. Solitamente, una partizione a inter-
valli viene partizionata con hash partitioning, creando così più partizioni secondarie hash per
ciascuna delle partizioni a intervalli. Vedere il Capitolo 17.
PASSW[ORD] [nomeutente]
ANY USER). Se si usa questo comando, la nuova password non compare sullo schermo mentre
la si digita. Gli utenti con autorità DBA possono modificare la password di un altro utente me-
diante il comando password; gli altri utenti possono modificare solo la propria password.
Quando si impartisce il comando password, il sistema chiede di inserire prima la vecchia
password e poi quella nuova.
ESEMPIO
password
Changing password for dora
Old password:
New password:
Retype new password:
Una volta che la password è stata cambiata con successo il sistema avvisa con il messaggio:
Password changed
PAU[SE] [testo];
DESCRIZIONE PAUSE è simile a PROMPT, ma visualizza prima una linea vuota, poi una linea
contenente testo, quindi attende che l’utente prema INVIO. Se non si è inserito alcun testo, PAUSE
visualizza due linee vuote e attende la pressione di INVIO.
NOTA PAUSE attende la pressione di INVIO dal terminale anche quando la sorgen-
te dei comandi è stata dirottata da un file. In altre parole, un file di avvio contenente SET
TERMOUT OFF potrebbe arrestarsi, attendere la pressione di INVIO senza fornire alcun messag-
gio del perché è in attesa (o per informare l’utente che è in attesa). Si usi questo comando con
molta cautela.
ESEMPIO
PCTFREE
PCTFREE è una porzione di un blocco di dati che non viene riempita dalle righe inserite in una
tabella, ma è riservata ad aggiornamenti successivi sulle righe del blocco stesso.
GUIDA DI RIFERIMENTO ALFABETICA 1199
PCTUSED
PCTUSED è la percentuale di spazio in un blocco di dati che Oracle cerca di mantenere pieno.
Se la percentuale impiegata è inferiore al valore di PCTUSED, allora il blocco viene aggiunto
all’elenco dei blocchi liberi nel segmento. PCTUSED può essere impostato su una base tabella
per tabella.
PERCENT_RANK
VEDERE ANCHE FUNZIONI DI AGGREGAZIONE, Capitolo 12.
SINTASSI
Per gli aggregati:
PERCENTILE_CONT
VEDERE ANCHE FUNZIONI DI AGGREGAZIONE, PERCENTILE_DISC, Capitolo 12.
SINTASSI
ordinamento e restituisce un valore interpolato che rientrerebbe in questo valore percentile ri-
spetto alla specifica di ordinamento. Nel calcolo i valori NULL vengono ignorati.
La prima espr deve essere valutata a un valore numerico compreso tra 0 e 1, poiché si tratta
di un valore percentile. Questa espr deve rimanere costante all’interno di ciascun gruppo di
aggregazione. La clausola ORDER BY accetta una singola espressione che deve essere un valore
numerico e un valore di data/ora, poiché questi sono i tipi per i quali Oracle può eseguire
un’interpolazione.
PERCENTILE_DISC
VEDERE ANCHE FUNZIONI DI AGGREGAZIONE, PERCENTILE_CONT, Capitolo 12.
SINTASSI
POWER
VEDERE ANCHE SQRT, Capitolo 9.
SINTASSI
POWER(valore,esponente)
POWER(2,4) = 16
POWERMULTISET
VEDERE ANCHE Capitolo 34.
SINTASSI
POWERMULTISET ( espr )
DESCRIZIONE POWERMULTISET prende come input una tabella nidificata e restituisce una
tabella nidificata di tabelle nidificate contenente tutti i sottoinsiemi non vuoti della tabella nidificata
GUIDA DI RIFERIMENTO ALFABETICA 1201
di input. espr può essere qualunque espressione che per valore ha una tabella nidificata; se quella
tabella nidificata è vuota, viene restituito un errore.
POWERMULTISET_BY_CARDINALITY
VEDERE ANCHE
POWERMULTISET.
SINTASSI
DESCRIZIONE
POWERMULTISET prende come input una tabella nidificata e restituisce una tabella nidificata
di tabelle nidificate contenente tutti i sottoinsiemi non vuoti della tabella nidificata di input. espr
può essere qualunque espressione che per valore ha una tabella nidificata; se quella tabella
nidificata è vuota, viene restituito un errore.
PRAGMA
Un’istruzione pragma è una direttiva del compilatore, piuttosto che una porzione di codice ese-
guibile. Nonostante assomigli al codice eseguibile e appaia nei listati dei programmi (come un
blocco PL/SQL), un’istruzione pragma non è effettivamente eseguibile, e per questo motivo non
appare nel codice di esecuzione del blocco. Il suo compito è quello di fornire istruzioni al com-
pilatore. Vedere EXCEPTION_ INIT e il Capitolo 30.
PRECEDENZE
VEDERE ANCHE OPERATORI LOGICI, OPERATORI DI QUERY, Capitolo 13.
DESCRIZIONE Gli operatori seguenti sono elencati in ordine decrescente di precedenza. Gli
operatori con uguale precedenza sono posti sulla stessa linea. Inoltre, vengono valutati in suc-
cessione da sinistra a destra. Tutti gli AND sono valutati prima di qualsiasi OR. Questi operatori
sono elencati e descritti separatamente al proprio simbolo o nome in questo stesso capitolo.
OPERATORE FUNZIONE
- Continuazione di un comando SQL*PLUS. Continua un comando sulla linea seguente.
& Prefisso dei parametri di un file di avvio di SQL*PLUS. &1, &2, ecc. vengono sostituiti da parole. Vedere
START.
& && Prefisso di sostituzione di un comando SQL in SQL*PLUS. SQL*PLUS richiede l’inserimento di un
valore se trova una variabile & o && non definita. && ha l’effetto di definire la variabile e salva il valore;
‘&’ invece non lo fa. Vedere & e &&, DEFINE e ACCEPT.
. Separatore di variabili, utilizzato in SQL*PLUS per separare il nome di una variabile da un suffisso in
modo che quest’ultimo non venga considerato parte del nome di variabile.
(segue)
1202 CAPITOLO 48
(continua)
‘ Racchiudono letterali, come stringhe di caratteri o costanti delle date. Per includere un apice in una
costante di stringa se ne usino due (non si usino le virgolette).
“ Racchiudono l’alias di una tabella o di una colonna nel caso contenga caratteri speciali o spazi.
@@ Precede il nome di un database nel comando COPY o il nome di un collegamento nella clausola from.
*/ Moltiplicazione e divisione.
+- Addizione e sottrazione.
|| Concatenazione di caratteri.
MINUS Restituisce tutte le righe separate della prima query che non abbiano corrispondenza nella seconda.
PRECOMPILATORE
Il precompilatore è un programma che legge un codice sorgente particolare e scrive un file del
programma sorgente modificato (precompilato) pronto per essere letto da un compilatore normale.
PREDICATO
Un predicato è la clausola where, e più esplicitamente un criterio di selezione basato su uno
degli operatori relazionali (=, !=, IS, IS NOT, >, >=) e non contenente alcun operatore logico
(AND, OR o NOT).
DESCRIZIONE PREPARE analizza SQL all’interno della variabile host :stringa_host o del
testo letterale. Inoltre assegna un istruzione_id come riferimento a SQL. Se istruzione_id è già
stato utilizzato precedentemente, questo riferimento lo sovrascrive. Quando l’istruzione fornita
è select vi si può includere una clausola for update of. :stringa_host non è il vero nome della
variabile host impiegata, ma un segnaposto. OPEN CURSOR assegna le variabili host di input
nella propria clausola using, mentre FETCH assegna le variabili host di output nella propria
clausola into, in base alla posizione. Un’istruzione deve essere preparata una sola volta. Quindi,
potrà essere eseguita più volte.
stringa_query : string(1..100)
get(stringa_query);
EXEC SQL prepare FRED from :stringa_query;
EXEC SQL execute FRED;
PRESENTNNV
VEDERE ANCHE PRESENTV
SINTASSI
DESCRIZIONE La funzione PRESENTNNV è rilevante solo per i calcoli interriga. Può essere
utilizzata solo nella clausola MODEL dell’istruzione SELECT e quindi solo sul lato destro di una
regola di modello. La funzione restituisce espr1 quando, prima dell’esecuzione della clausola
MODEL, cell_reference esiste e non è nullo. In caso contrario restituisce espr2.
PRESENTV
VEDERE ANCHE PRESENTNNV.
SINTASSI
DESCRIZIONE La funzione PRESENTV è rilevante solo per i calcoli interriga. Può essere
utilizzata solo nella clausola MODEL dell’istruzione SELECT e quindi solo sul lato destro di una
regola di modello. La funzione restituisce espr1 quando, prima dell’esecuzione della clausola
MODEL, cell_reference esiste (ma può essere nullo). In caso contrario restituisce espr2.
PREVIOUS
VEDERE ANCHE ITERATION_NUMBER.
SINTASSI
PREVIOUS ( riferimento_cella )
1204 CAPITOLO 48
DESCRIZIONE La funzione PREVIOUS è rilevante solo per i calcoli interriga. Può essere
utilizzata solo nella clausola MODEL dell’istruzione SELECT e quindi solo quando
ITERATE(numero) è specificato nella clausola MODEL RULES . Passerà poi il valore di
riferimento_cella all’inizio di ogni iterazione.
PRINT
VEDERE ANCHE BIND VARIABLE, VARIABLE, Capitolo 29.
SINTASSI
DESCRIZIONE Visualizza il valore corrente della variabile specificata (creata con il comando
VARIABLE). È possibile visualizzare i valori correnti di più variabili in un unico comando.
PRIOR
Vedere CONNECT BY.
PRIVILEGI
Un privilegio è un permesso concesso a un utente Oracle per l’esecuzione di alcune azioni. In
Oracle, nessun utente può eseguire nessuna azione senza aver prima ottenuto il privilegio opportuno.
Esistono due tipologie di privilegi: i privilegi di sistema e i privilegi sugli oggetti. I privilegi
di sistema sono permessi per l’esecuzione di comandi di definizione e controllo dei dati, come
CREATE TABLE o ALTER USER; è un privilegio di sistema persino quello che permette di colle-
garsi al database. I privilegi sugli oggetti consentono di operare su particolari oggetti del database.
I privilegi di sistema di Oracle comprendono CREATE, ALTER e DROP che permettono di
impartire i vari comandi CREATE, ALTER e DROP. I privilegi che contengono la parola chiave
ANY consentono all’utente di esercitare il privilegio su qualsiasi schema per il quale questo
privilegio è stato concesso, e non solo sugli schemi di sua proprietà. I privilegi standard, riportati
nell’elenco seguente, forniscono semplicemente il permesso di eseguire il comando indicato e
non richiedono ulteriori spiegazioni. Altri, invece, non sono così ovvi, quindi vengono spiegati
brevemente.
I privilegi di sistema includono:
TUNING
ADVISOR Accedere al framework dei consigli con i package PL/SQL che includono DBMS_ADVISOR e
DBMS_SQLTUNE.
ADMINISTER SQL TUNING SET Creare, eliminare, selezionare, caricare e cancellare un set di ottimizzazione SQL di proprietà di
chi ha concesso attraverso DBMS_SQLTUNE.
ADMINISTER ANY SQL TUNING SET Creare, eliminare, selezionare, caricare e cancellare un set di ottimizzazione SQL di proprietà di
qualunque utente attraverso DBMS_SQLTUNE.
(segue)
GUIDA DI RIFERIMENTO ALFABETICA 1205
(continua)
ALTER ANY SQL PROFILE Modificare gli attributi di un profilo SQL esistente.
CLUSTER
CREATE CLUSTER Creare dei cluster nello schema del concessionario.
CREATE ANY CLUSTER Creare un cluster in qualsiasi schema. Si comporta analogamente a CREATE ANY TABLE.
CONTEXT
CREATE ANY CONTEXT Creare qualsiasi spazio di nomi contestuale.
DATABASE
ALTER DATABASE Modificare il database.
DATABASE LINKS
CREATE DATABASE LINK Creare database link privati nello schema del concessionario.
DEBUGGING
DEBUG CONNECT SESSION Connettere la sessione corrente a un debugger.
DEBUG ANY PROCEDURE Effettuare il debug di tutto il codice PL/SQL e Java in qualunque oggetto di database. Visualizzare
informazioni su tutte le istruzioni SQL eseguite dall’applicazione.
DIMENSION
CREATE DIMENSION Creare dimensioni nello schema del concessionario.
(segue)
1206 CAPITOLO 48
(continua)
DIRECTORY
CREATE ANY DIRECTORY Creare oggetti di database della directory.
INDEXTYPE
CREATE INDEXTYPE Creare un tipo di indice nello schema del concessionario.
INDEX
CREATE ANY INDEX Creare un indice di dominio in qualsiasi schema oppure un indice su qualsiasi tabella di qua-
lunque schema.
CREATE ANY JOB Creare, modificare o eliminare processi, pianificazioni o programmi in qualunque schema.
EXECUTE ANY PROGRAM Utilizzare qualunque programma in un processo dello schema di chi beneficia della concessione.
EXECUTE ANY CLASS Specificare qualunque programma in un processo dello schema di chi beneficia della concessione.
MANAGE SCHEDULER Creare, modificare o eliminare qualunque classe di processi, finestra o gruppo di finestre.
LIBRARY
CREATE LIBRARY Creare librerie di procedure/funzioni esterne nello schema del concessionario.
MATERIALIZED VIEW
CREATE MATERIALIZED VIEW Creare una vista materializzata nello schema del concessionario.
(segue)
GUIDA DI RIFERIMENTO ALFABETICA 1207
(continua)
QUERY REWRITE Abilitare la riscrittura tramite una vista materializzata, oppure creare un indice basato su una
funzione quando questa vista materializzata o questo indice fanno riferimento a tabelle e viste
che si trovano nello schema del concessionario.
GLOBAL QUERY REWRITE Abilitare la riscrittura tramite una vista materializzata, oppure creare un indice basato su una
funzione quando questa vista materializzata o questo indice fanno riferimento a tabelle e viste
di qualsiasi schema.
ON COMMIT REFRESH Creare una vista materializzata di tipo ad “aggiornamento su commit” su qualsiasi tabella del
database. Modificare una vista materializzata di tipo ad “aggiornamento su richiesta” su qual-
siasi tabella nel database da aggiornare su commit.
OPERATOR
CREATE OPERATOR Creare un operatore e le relative associazioni nello schema del concessionario.
OUTLINE
CREATE ANY OUTLINE Creare strutture pubbliche che possono essere utilizzate in qualsiasi schema si serva di strut-
ture.
SELECT ANY OUTLINE Creare una struttura privata che sia il clone di una struttura pubblica.
PROCEDURE
CREATE PROCEDURE Creare stored procedure, funzioni e package nello schema del concessionario.
CREATE ANY PROCEDURE Creare stored procedure, funzioni e package in qualunque schema.
ALTER ANY PROCEDURE Modificare stored procedure, funzioni o package in qualsiasi schema.
DROP ANY PROCEDURE Eliminare stored procedure, funzioni o package in qualunque schema.
EXECUTE ANY PROCEDURE Eseguire procedure o funzioni (indipendenti o raccolte in package). Fare riferimento a variabili
di package pubblici in qualunque schema.
PROFILE
CREATE PROFILE Creare profili.
(segue)
1208 CAPITOLO 48
(continua)
ROLE
CREATE ROLE Creare ruoli.
ROLLBACK SEGMENT
CREATE ROLLBACK SEGMENT Creare segmenti di rollback.
SEQUENCES
CREATE SEQUENCE Creare sequenze nello schema del concessionario.
SESSION
CREATE SESSION Connettersi al database.
RESTRICTED SESSION Collegarsi dopo l’avvio dell’istanza con l’istruzione STARTUP RESTRICT di SQL*Plus.
SYNONYM
CREATE SYNONYM Creare sinonimi nello schema del concessionario.
TABLE
CREATE TABLE Creare tabelle nello schema del concessionario.
(segue)
GUIDA DI RIFERIMENTO ALFABETICA 1209
(continua)
BACKUP ANY TABLE Usare l’utility Export per esportare in maniera incrementale gli oggetti dallo schema di altri
utenti.
DELETE ANY TABLE Cancellare righe da tabelle, partizioni di tabelle o viste in qualunque schema.
DROP ANY TABLE Cancellare o troncare tabelle o partizioni di tabelle in qualsiasi schema.
SELECT ANY TABLE Eseguire query su tabelle, viste o viste materializzate in qualunque schema.
FLASHBACK ANY TABLE Eseguire una query flashback su qualunque tabella, vista, o vista materializzata in qualunque
schema.
TABLESPACE
CREATE TABLESPACE Creare tablespace.
MANAGE TABLESPACE Mantenere le tablespace in linea e fuori linea, iniziare e terminare backup di tablespace.
UNLIMITED TABLESPACE Usare una quantità illimitata di qualunque tablespace. Questo privilegio sostituisce qualsiasi
quota specifica assegnata. Se si revoca questo privilegio a un utente, gli oggetti rimarranno
nello schema dell’utente ma non sarà possibile allocare altre tablespace a meno che non si sia
autorizzati da quote di tablespace specifiche. Non è possibile concedere questo privilegio di
sistema ai ruoli.
TRIGGER
CREATE TRIGGER Creare un trigger di database nello schema del concessionario.
ALTER ANY TRIGGER Attivare, disattivare, o compilare trigger di database in qualsiasi schema.
ADMINISTER DATABASE TRIGGER Creare un trigger su DATABASE (si deve disporre anche dei privilegi CREATE TRIGGER o CRE-
ATE ANY TRIGGER).
TYPE
CREATE TYPE Creare tipi di oggetti e corpi dei tipi di oggetti nello schema del concessionario.
(segue)
1210 CAPITOLO 48
(continua)
DROP ANY TYPE Eliminare tipi di oggetti e corpi dei tipi di oggetti in qualsiasi schema.
EXECUTE ANY TYPE Usare e fare riferimento a tipi di oggetti e tipi di collection in qualsiasi schema, e invocare
metodi di un tipo di oggetto in qualunque schema se si fa la concessione a un utente specifico.
Se si concede EXECUTE ANY TYPE a un ruolo, gli utenti in possesso del ruolo abilitato non
saranno in grado di invocare i metodi di un tipo di oggetto in qualsiasi schema.
UNDER ANY TYPE Creare sottotipi in qualsiasi tipo di oggetto non finale.
USER
CREATE USER Creare utenti. Questo privilegio consente al creatore anche di: assegnare quote su qualsiasi
tablespace, impostare tablespace predefinite e temporanee, assegnare un profilo come parte
di un’istruzione CREATE USER.
ALTER USER Modificare qualsiasi utente. Questo privilegio autorizza il concessionario a: modificare la
password o il metodo di autenticazione di un altro utente, assegnare quote su qualsiasi
tablespace, impostare tablespace predefinite e temporanee e assegnare un profilo e ruoli
predefiniti.
BECOME USER Diventare un altro utente. (Richiesto da qualunque utente esegua un’importazione di database
completa).
VIEW
CREATE VIEW Creare viste nello schema del concessionario.
VARI
ANALYZE ANY Analizzare qualsiasi tabella, cluster o indice in qualsiasi schema.
AUDIT ANY Porre sotto controllo qualsiasi oggetto in qualunque schema con le istruzioni oggetti_schema
di AUDIT.
COMMENT ANY TABLE Commentare qualunque tabella, vista o colonna in qualsiasi schema.
EXEMPT ACCESS POLICY Ignorare i controlli di accesso dinamico. Si tratta di un privilegio di sistema molto potente
poiché consente al concessionario di ignorare i criteri di sicurezza basati sulle applicazioni. Gli
amministratori di database dovrebbero prestare molta attenzione quando concedono questo
privilegio.
FORCE ANY TRANSACTION Indurre il commit o il rollback di qualsiasi transazione distribuita sconosciuta nel database
locale. Indurre il fallimento di una transazione distribuita.
(segue)
GUIDA DI RIFERIMENTO ALFABETICA 1211
(continua)
SELECT ANY DICTIONARY Eseguire una query su qualsiasi oggetto del dizionario dati nello schema SYS. Questo privile-
gio consente di sostituire in modo selettivo l’impostazione predefinita FALSE del parametro di
inizializzazione O7_DICTIONARY_ACCESSIBILITY. Questo privilegio dev’essere concesso in-
dividualmente. Non è incluso in GRANT ALL PRIVILEGES, e non può essere concesso nean-
che mediante un ruolo.
DELETE_CATALOG_ROLE, Questi ruoli vengono forniti per l’accesso alle viste e ai package del dizionario dati.
EXECUTE_CATALOG_ROLE,
SELECT_CATALOG_ROLE
EXP_FULL_DATABASE, Questi ruoli vengono forniti per praticità nell’uso delle utility Import ed Export.
IMP_FULL_DATABASE
RECOVERY_CATALOG_OWNER Questo ruolo è necessario per la creazione del proprietario dello schema di un Recovery Catalog.
SCHEDULER_ADMIN Questo ruolo consente al beneficiario di eseguire le procedure del package DBMS_SCHEDULER.
NOTA Per le tabelle esterne, gli unici privilegi validi sono CREATE ANY TABLE,
ALTER ANY TABLE, DROP ANY TABLE e SELECT ANY TABLE.
1212 CAPITOLO 48
I privilegi di oggetto possono essere applicati solo ad alcuni tipi di oggetti. La tabella se-
guente mostra le relazioni e i privilegi di oggetti che si possono concedere.
PRIVILEGIO TABELLA VISTA SEQUENZA PROCEDURE, VISTA DIRECTORY LIBRERIA TIPO OPERATORE TIPO
OGGETTO FUNZIONI, MATERIALIZZATA DEFINITO DI INDICE
PACKAGEa DALL’UTENTE
ALTER X X
DELETE X X Xb
EXECUTE Xc Xc Xc Xc Xc
INDEX X
INSERT X X Xb
ON COMMIT X
REFRESH
QUERY X
REWRITE
READ X
REFERENCES X X
SELECT X X X X
UNDER X X
UPDATE X X Xb
WRITE X
a Oracle tratta una classe, un’origine o una risorsa Java come se fosse una procedura per concedere privilegi sugli oggetti.
bIprivilegi DELETE, INSERT e UPDATE possono essere concessi solo a viste materializzate aggiornabili.
cGli oggetti job scheduler vengono creati con il package DBMS_SCHEDULER. Una volta creati questi oggetti, è possibile assegnare il privilegio di oggetto EXECUTE
sulle classi e i programmi di pianificazione processi. È possibile concedere il privilegio ALTER su processi, programmi e pianificazioni di tipo job scheduler.
PRO*C
Il PRO*C è un’estensione del C che permette di sviluppare user exit e altri programmi di accesso
al database Oracle. Un precompilatore converte il codice PRO*C in codice C normale, pronto
per essere compilato. Vedere Pro*C/C++ Precompiler Programmers’s Guide.
PROCEDURA
Una procedura è un insieme di istruzioni (solitamente combinazioni di comandi SQL e PL/SQL)
salvate per esecuzioni ripetute e esecuzioni di chiamata. Vedere CREATE PROCEDURE.
PROCESSO PMON
Il Process MONitor è un processo in background utilizzato per recuperare le situazioni in cui un
processo si interrompe durante l’accesso al database. Vedere BACKGROUND, PROCESSO.
PRODUCT_USER_PROFILE
PRODUCT_USER_PROFILE è una tabella SYSTEM di Oracle utilizzata per limitare l’uso di
singoli prodotti Oracle o per disattivare uno o più comandi disponibili nel prodotto. Vedere
SQL*Plus User’s Guide and Reference.
GUIDA DI RIFERIMENTO ALFABETICA 1213
PROFILO
Un profilo è una collezione di impostazioni Oracle che limitano le risorse del database. Vedere
CREATE PROFILE e il Capitolo 18.
PROMPT (SQL*Plus)
VEDERE ANCHE ACCEPT.
SINTASSI
PROMPT [testo]
DESCRIZIONE Visualizza il testo sullo schermo dell’utente. Se non si specifica alcun testo,
viene visualizzata una linea vuota. Per visualizzare una variabile, vedere PRINT.
PSEUDOCOLONNE
Una pseudocolonna è una “colonna” che produce un valore quando selezionata ma non è una
vera colonna della tabella. Esempi tipici sono RowID e SysDate. Ecco le pseudocolonne supportate
attualmente da Oracle.
CONNECT_BY_ISLEAF Uguale a 1 se la riga corrente è una foglia della struttura ad albero definita dalla condizione CONNECT
BY,, altrimenti 0.
Level Pari a 1 per un nodo principale, a 2 per un figlio di un nodo e così via. Indica quanti livelli dell’albero sono
stati analizzati.
VERSIONS_STARTTIME Per le query di versione flashback, restituisce l’indicatore orario della prima versione delle righe restituite
dalla query.
VERSIONS_STARTSCN Per le query di versione flashback, restituisce il valore SCN della prima versione delle righe restituite
dalla query.
VERSIONS_ENDTIME Per le query di versione flashback, restituisce l’indicatore orario dell’ultima versione delle righe restituite
dalla query.
VERSIONS_ENDSCN Per le query di versione flashback, restituisce il valore SCN dell’ultima versione delle righe restituite dalla
query.
VERSIONS_XID Per le query di versione flashback, per ciascuna versione di ogni riga, restituisce l’ID della transazione
che ha creato quella versione della riga.
VERSIONS_OPERATION Per le query di versione flashback, per ciascuna versione di ogni riga, restituisce un singolo carattere per
l’operazione che ha causato quella versione della riga. I (insert), U (update) o D (delete).
OBJECT_ID Restituisce l’identificatore di oggetto di una colonna di una tabella o vista di oggetti.
(segue)
1214 CAPITOLO 48
(continua)
OBJECT_VALUE Restituisce i nomi generati dal sistema per le colonne di una tabella di oggetti, una tabella XMLType, una
vista di oggetti o una vista XMLType.
ORA_ROWSCN Restituisce il SCN di limite superiore conservativo della modifica più recente apportata alla riga, mo-
strando all’incirca quando la riga è stata aggiornata l’ultima volta (per un audit più capillare dovrebbero
essere create delle dipendenze a livello di riga).
ROWID Restituisce il numero dell’identificativo di una riga. RowID viene utilizzato in UPDATE ... WHERE e SELECT
... FOR UPDATE. In questo modo, si garantisce che vengano aggiornate solo le righe indicate.
ROWNUM Restituisce il numero di sequenza in cui è stata restituita una riga quando selezionata da una tabella. Il
RowNum della prima riga è 1, quello della seconda è 2 e così via.
XMLDATA Consente di accedere ai dati LOB XMLType sottostanti o alla colonna relazionale a oggetti.
PUBLIC
Public può avere queste due definizioni:
■ Qualcosa che sia stato reso pubblico è visibile o disponibile per tutti gli utenti. Possono
essere pubblici i sinonimi e i database link. In Oracle, per rendere pubblico qualcosa un utente
deve possedere i privilegi CREATE PUBLIC SYNONYM o CREATE PUBLIC DATABASE
LINK. Gli utenti possono inoltre concedere l’accesso ai propri oggetti agli altri utenti.
■ Un gruppo cui appartiene qualsiasi utente di un dato database, il nome di tale gruppo.
PUBLIC SYNONYM
Un sinonimo pubblico è un sinonimo di un oggetto di database che un utente ha creato, tramite
il privilegio CREATE PUBLIC SYNONYM, per essere utilizzato da tutti gli utenti di Oracle.
PURGE
VEDERE ANCHECapitolo 46, RECYCLE BIN.
SINTASSI
purge::=
TABLE table
INDEX index
RECYCLEBIN
PURGE ;
DBA_RECYCLEBIN
USER user
TABLESPACE tablespace
DESCRIZIONE PURGE rimuove una tabella o un indice dal cestino e rilascia tutto lo spazio
associato con l’oggetto, o rimuove l’intero cestino oppure ancora rimuove parte o tutta una
tablespace eliminata dal cestino.
GUIDA DI RIFERIMENTO ALFABETICA 1215
NOTA Non è possibile eseguire il rollback di comando PURGE. Una volta eliminato
con PURGE, un oggetto non è più recuperabile.
Per vedere il contenuto del cestino è possibile interrogare la vista del dizionario dati
RECYCLEBIN.
È possibile utilizzare le parole chiave TABLE o INDEX per specificare il nome dell’oggetto
che si desidera eliminare. Specificando RECYCLEBIN vengono eliminati tutti gli oggetti presenti
nel proprio cestino. DBA_RECYCLEBIN ripulisce i cestini di tutti gli utenti. TABLESPACE elimina
dal cestino tutti gli oggetti situati nella tablespace specificata. USER utente elimina lo spazio
interno a una tablespace per un utente particolare.
ESEMPIO
Per eliminare una singola tabella:
PURGE RECYCLEBIN;
QUERY
Una query è un’istruzione SQL usata per recuperare dati da una o più tabelle (o viste). Le query
iniziano con la parola chiave SQL select.
QUERY AD ALBERO
Una query ad albero è una query il cui risultato evidenzia relazioni gerarchiche tra le righe di una
tabella. Vedere CONNECT BY.
QUERY CORRELATA
Una query correlata è una subquery che viene eseguita ripetutamente, una volta per ciascun
valore di una riga candidata selezionata dalla query principale. L’esito di ogni esecuzione della
subquery dipende dai valori di uno o più campi all’interno della riga candidata; in altre parole, la
subquery è correlata alla query principale. Vedere il Capitolo 13.
QUERY DISTRIBUITA
Una query distribuita è una query che seleziona dati da più database, solitamente residenti su più
nodi di una rete.
QUERY FLASHBACK
Una query flashback mostra i dati così come erano prima di un commit. Non è possibile eseguire
DML quando ci si trova nella modalità di query flashback. Per esempi e restrizioni applicate alle
query flashback si rimanda al Capitolo 27.
1216 CAPITOLO 48
QUERY PADRE
La query padre è la query più esterna (quella che visualizza il risultato) in una query principale
che contiene una subquery. Vedere QUERY PRINCIPALE.
QUERY PRINCIPALE
Una query principale è la query più esterna o iniziale di una query contenente una subquery. È la
query le cui colonne producono il risultato finale.
QUIT
VEDERE ANCHE COMMIT, DISCONNECT, EXIT, SET AUTOCOMMIT, START.
SINTASSI
QUIT
DESCRIZIONE QUIT termina una sessione SQL*PLUS e riporta l’utente al sistema operativo,
al programma chiamante o al menu precedente.
QUOTA
Una quota è un limite imposto a una risorsa. Le quote possono limitare la quantità di memoria
utilizzata da ciascun utente del database. Vedere CREATE USER e ALTER USER.
RAISE
VEDERE ANCHE DECLARE EXCEPTION, EXCEPTION, EXCEPTION_INIT.
SINTASSI
RAISE [exception]
DESCRIZIONE RAISE assegna un nome al flag dell’eccezione che si intende sollevare, in base
a una condizione verificata. L’eccezione deve essere stata dichiarata esplicitamente o appartene-
re alle eccezioni di sistema come DIVIDE_BY_ZERO (per un elenco completo, vedere
EXCEPTION).
L’istruzione RAISE sposta il controllo alla sezione EXCEPTION del blocco corrente nella
quale si dovrà eseguire un controllo per verificare quale eccezione è stata sollevata. Se non è
presente alcuna sezione EXCEPTION, il controllo salta alla sezione EXCEPTION più vicina di
un blocco di inclusione (praticamente, ripercorrendo al contrario l’annidamento dei blocchi). Se
non viene trovata alcuna logica per la gestione delle eccezioni, il controllo passa da PL/SQL al
programma o all’ambiente chiamante fornendo un errore di eccezione non gestibile. Questo può
essere evitato utilizzando OTHERS. Vedere EXCEPTION.
RAISE può essere utilizzato senza parametri in un solo caso: all’interno di una sezione
EXCEPTION per fare in modo che l’eccezione corrente venga gestita dalla sezione EXCEPTION
del blocco più esterno, invece che dal blocco corrente. Se per esempio si fosse verificato un
errore NOT_LOGGED_ON e la sezione EXCEPTION locale contenesse le righe seguenti:
GUIDA DI RIFERIMENTO ALFABETICA 1217
when not_logged_on
then raise;
il controllo passerebbe alla sezione EXCEPTION del blocco immediatamente più esterno, oppu-
re al programma se non esistesse un blocco simile. Questo blocco EXCEPTION potrebbe essere
verificato per controllare la presenza di eventuali errori NOT_LOGGED_ON. Il vantaggio con-
siste nel fatto che per una certa classe di errori, soprattutto quelli in cui le fasi di recupero, traccia
e registrazione degli errori che si desiderano eseguire possono essere ampie, è possibile imposta-
re la sezione EXCEPTION di ogni blocco annidato per demandare semplicemente l’eccezione a
un unico blocco EXCEPTION.
RAMI
I rami rappresentano una serie di nodi interconnessi di un albero logico. Vedere CONNECT BY.
RANK
VEDERE ANCHE FUNZIONI ANALITICHE.
SINTASSI
rank_aggregate::=
DESC FIRST
NULLS
ASC LAST
( ORDER BY expr )
rank_analytic::=
query_partition_clause
RANK ( ) OVER ( order_by_clause )
RATIO_TO_REPORT
VEDERE ANCHE FUNZIONI DI AGGREGAZIONE.
SINTASSI
RAWTOHEX
VEDERE ANCHE HEXTORAW.
SINTASSI
RAWTOHEX(stringa_binaria)
DESCRIZIONE RAWTOHEX converte una stringa di numeri binari in una stringa di caratteri di
cifre esadecimali.
RAWTONHEX
VEDERE ANCHE RAWTOHEX.
SINTASSI
RAWTONHEX( raw )
RECORD (PL/SQL)
VEDERE ANCHE TABELLA (PL/SQL); DATI, TIPI.
SINTASSI
DESCRIZIONE La dichiarazione di un RECORD produce un nuovo tipo di dati che può essere
utilizzato per dichiarare le nuove variabili. I singoli componenti di un record si dicono campi e
ciascuno di essi è di un tipo di dati opportuno. Questi tipi di dati possono essere tipi standard di
PL/SQL (compresi altri RECORD ma escludendo le tabelle), o un riferimento al tipo di una
particolare colonna di una data tabella. Ogni campo può possedere anche l’attributo NOT NULL
secondo cui il campo deve sempre avere un valore significativo.
Si può fare riferimento ai singoli campi di un record con la classica notazione separata da punti.
RECOVER
RECOVER è una clausola del comando ALTER DATABASE.
VEDERE ANCHE ALTER DATABASE, Capitolo 46.
GUIDA DI RIFERIMENTO ALFABETICA 1219
SINTASSI
[STANDBY] DATABASE
[ {UNTIL {CANCEL | TIME data | CHANGE intero} | USING BACKUP CONTROLFILE}
[UNTIL {CANCEL | TIME data | CHANGE intero} | USING BACKUP CONTROLFILE]...]
RECSEP (SQL*PLUS)
Vedere SET.
RECSEPCHAR (SQL*PLUS)
Vedere SET.
RECUPERO DI DISCHI
Si tratta dell’operazione di recupero di guasti hardware che possono pregiudicare lettura, scrittu-
ra dei dati e operazioni simili nel database. Vedere anche RECUPERO DI ISTANZA.
RECUPERO DI ISTANZA
Il recupero di un’istanza è il processo di recupero del guasto (hardware o software) subito dal-
l’istanza stessa. Si ha quando il software ha terminato la propria esecuzione in maniera drastica
a causa di un errore, di un guasto o di un’interazione distruttiva tra programmi. Vedere anche
RECUPERO DI DISCHI.
RECYCLE BIN
A partire da Oracle Database 10g, gli oggetti eliminati per default finiscono in un cestino invece
di essere eliminati immediatamente. Il cestino consente di ripristinare gli oggetti eliminati senza
dover ricorrere a un ripristino completo del database. È poi possibile eliminare definitivamente
degli oggetti specifici dal cestino tramite il comando PURGE. Vedere PURGE.
Per vedere gli oggetti attualmente contenuti nel cestino è possibile interrogare la vista del
dizionario dati RECYCLEBIN o utilizzare il comando SHOW RECYCLEBIN.
GUIDA DI RIFERIMENTO ALFABETICA 1221
REDO LOG
Un redo log è un log sequenziale di azioni eseguite nel database. Il log è costituito sempre
almeno da due file; uno può essere facoltativamente archiviato mentre l’altro viene scritto. Quando
il file in cui si scrive è pieno, si comincia a riutilizzare l’altro.
REF
Un tipo di dati di riferimento utilizzato con tabelle oggetto. Vedere il Capitolo 36.
REFTOHEX
VEDERE ANCHE Capitolo 36.
SINTASSI
REFTOHEX ( espr )
REGEXP_INSTR
VEDERE ANCHEINSTR, Capitolo 8.
SINTASSI
regexp_instr::=
, match_parameter
, return_option
, occurrence
, position
)
1222 CAPITOLO 48
REGEXP_LIKE
LVEDERE ANCHEIKE, Capitolo 8.
SINTASSI
REGEXP_REPLACE
VEDERE ANCHEREPLACE, Capitolo 8.
SINTASSI
regexp_replace::=
, match_parameter
, occurrence
, position
, replace_string
)
REGEXP_SUBSTR
VEDERE ANCHESUBSTR, Capitolo 8.
SINTASSI
GUIDA DI RIFERIMENTO ALFABETICA 1223
regexp_substr::=
, match_parameter
, occurrence
, position
)
REGR_SLOPE
REGR_INTERCEPT
REGR_COUNT
REGR_R2
OVER ( analytic_clause )
REGR_AVGX ( expr1 , expr2 )
REGR_AVGY
REGR_SXX
REGR_SYY
REGR_SXY
DESCRIZIONE Le funzioni di regressione lineare adattano una retta di regressione normale per
quadrati minori a un gruppo di numeri pari. È possibile utilizzarle come funzioni di aggregazione
o come funzioni analitiche. REGR_SLOPE restituisce l’inclinazione della retta.
REGR_INTERCEPT restituisce l’intersezione sull’asse y della retta di regressione. REGR_COUNT
restituisce un intero che è il numero dei numeri pari non NULL utilizzati per la retta di regressione.
REGR_R2 restituisce il coefficiente di determinazione per la regressione. REGR_AVGX valuta
la media della variabile indipendente (espr2) della retta di regressione. REGR_AVGY valuta la
media della variabile dipendente (espr2) della retta di regressione. REGR_SXY, REGR_SXX e
REGR_SYY sono funzioni ausiliarie utilizzate per calcolare varie statistiche di diagnostica.
1224 CAPITOLO 48
REMAINDER
VEDERE ANCHE FUNZIONI NUMERICHE.
SINTASSI
REMAINDER (m, n)
REMARK
VEDERE ANCHE /* */, - -, Capitolo 6.
SINTASSI
REM[ARK] testo
REM Riduce la larghezza predefinita delle colonne per questo campo di dati:
column ActionDate format a6 trunc
RENAME
VEDERE ANCHE COPY, CREATE SEQUENCE, CREATE SYNONYM, CREATE TABLE,
CREATE VIEW.
SINTASSI
DESCRIZIONE RENAME cambia il nome di una tabella, vista, sequenza o sinonimo assegnando
loro un nome nuovo. Non sono necessari apici attorno ai nomi. Il nuovo nome non dev’essere né
una parola riservata né il nome di un oggetto già esistente di proprietà dell’utente stesso.
ESEMPIO
La riga seguente cambia il nome della tabella BIBLIOTECA in LIBRO:
REPFOOTER
VEDERE ANCHE ACCEPT, BTITLE, DEFINE, PARAMETRI, REPHEADER.
SINTASSI
DESCRIZIONE REPFOOTER (REPort FOOTER) inserisce un piè di pagina (magari a più linee)
nell’ultima pagina di un rapporto. OFF e ON rispettivamente sopprimono e ripristinano la
visualizzazione del testo senza modificarne i contenuti. REPFOOTER da solo mostra le opzioni
correnti e il valore di testo o variabile. PAGE inizia una nuova pagina prima di visualizzare il piè
di pagina del report specificato.
testo è il piè di pagina che si desidera assegnare a questo report, e variabile è il nome di una
variabile definita dall’utente o gestita dal sistema come SQL.LNO, il numero di linea corrente;
SQL.PNO, il numero di pagina corrente; SQL.RELEASE, il numero della release corrente di
Oracle; SQL.SQLCODE, il codice di errore corrente e SQL.USER, il nome utente.
Le opzioni possibili sono elencate di seguito.
■ COL n salta direttamente alla posizione n (dal margine sinistro) della linea corrente.
■ S[KIP] n visualizza n linee vuote. Se non viene specificato alcun numero, viene stampata una
sola linea vuota. Se n vale 0, non viene visualizzata alcuna linea vuota e la posizione di stampa
corrente diventa la prima della linea corrente (all’estremità sinistra della pagina).
■ TAB n salta di n tabulazioni verso destra (verso sinistra se n è negativo).
■ LE[FT], CE[NTER] e R[IGHT] giustificano a sinistra, centrano e giustificano a destra i dati
della linea corrente. Eventuali stringhe di testo e variabili che seguissero questi comandi verreb-
bero giustificate anch’esse, fino alla fine del comando. CENTER e RIGHT utilizzano il valore
impostato da SET LINESIZE per determinare dove disporre il testo e le variabili.
■ BOLD visualizza i dati in grassetto. SQL*PLUS rappresenta il grassetto sul terminale ripe-
tendo i dati su tre linee consecutive.
■ FORMAT stringa specifica il modello del formato per la visualizzazione del testo o delle
variabili seguenti e segue la stessa sintassi dell’opzione FORMAT del comando COLUMN; per
esempio, FORMAT A12 o FORMAT $999,990.99. Ogni volta che compare FORMAT, esso scaval-
ca il precedente formato attivo fino a quel momento. Se non si specifica alcun modello per
FORMAT, viene utilizzato quello impostato da SET NUMFORMAT. Se NUMFORMAT non è stato
definito, viene utilizzato il modello predefinito per SQL*PLUS.
Le date vengono visualizzate in base al formato predefinito a meno che la data di una varia-
bile non sia stata convertita mediante la funzione TO_CHAR.
1226 CAPITOLO 48
REPHEADER
VEDERE ANCHE ACCEPT, BTITLE, DEFINE, PARAMETRI, REPFOOTER.
SINTASSI
REPLACE
VEDERE ANCHE CARATTERI, FUNZIONI, TRANSLATE, Capitolo 7.
SINTASSI
REPLACE(stringa,if,then)
DESCRIZIONE REPLACE sostituisce uno o più caratteri di una stringa con 0 o più caratteri. if
è una stringa di uno o più caratteri. Ogni volta che compare all’interno di stringa, viene sostitui-
to dal contenuto di then.
GUIDA DI RIFERIMENTO ALFABETICA 1227
ESEMPIO
REPLACE('GEORGE','GE',null) = OR
REPLACE('BOB','BO','TA') = TAB
REPLICA
La replica è quel processo che prevede la copia dei dati da un database in un altro. La destinazio-
ne in cui vengono copiati i dati replicati prende il nome di replica. Per gestire il processo di
replica, si dovrà stabilire:
■ la collocazione, la struttura e la proprietà dei dati di origine;
■ la frequenza degli aggiornamenti per i dati di origine;
■ i requisiti di opportunità per i dati delle replica;
■ la volatilità dei dati di origine;
■ i vari impieghi della replica.
Se la replica è anche in grado di apportare delle modifiche e queste ultime devono essere
riportate al database originale, allora si avrà una configurazione con più siti principali e si dovrà
gestire la risoluzione dei conflitti e gli errori per questo ambiente. In generale, la proprietà a
singolo sito dei dati con più repliche di sola lettura è più semplice da gestire di una configurazio-
ne con più siti principali.
Vedere CREATE MATERIALIZED VIEW, CREATE DATABASE LINK
RESOURCE (RISORSA)
Risorsa è il termine generale che denota un oggetto logico o una struttura fisica di un database.
Le risorse possono essere bloccate. Quelle che gli utenti possono bloccare direttamente sono le
tabelle e le righe. Le risorse bloccabili dall’RDBMS sono molteplici e comprendono tabelle del
dizionari dati, cache e file.
RESOURCE è anche il nome di un ruolo standard di Oracle. Vedere RUOLO.
REVOKE
VEDERE ANCHE DISABLE, ENABLE, GRANT, PRIVILEGI, Capitolo 18.
SINTASSI
revoke::=
revoke_system_privilege
REVOKE ;
revoke_object_privileges
revoke_system_privileges::=
system_privilege
ALL PRIVILEGES
1228 CAPITOLO 48
revoke_object_privileges::=
object_privilege
PRIVILEGES on_object_clause
ALL
CASCADE CONSTRAINTS
FORCE
FROM grantee_clause
grantee_clause::=
user
role
PUBLIC
on_object_clause::=
schema . object
ON DIRECTORY directory_name
SOURCE schema .
JAVA object
RESOURCE
può eseguire le operazioni consentite dal privilegio su quel determinato oggetto. Se vengono
revocati i privilegi di un ruolo, nessun utente con quel ruolo potrà eseguire le operazioni relative
a quei privilegi, a meno che questi non vengano concessi tramite un altro ruolo oppure diretta-
mente all’utente. Se si revocano i privilegi di PUBLIC, nessun utente cui è stato concesso il
privilegio tramite PUBLIC potrà eseguire le operazioni ad esso associate.
La clausola CASCADE CONSTRAINTS elimina qualsiasi vincolo di integrità referenziale
definito da uno o più utenti in possesso del ruolo. Questo vale per il privilegio REFERENCES.
RIGA
Riga può avere due definizioni:
■ Un insieme di campi di una tabella; per esempio i campi che rappresentano un impiegato
nella tabella LAVORATORE.
■ Un insieme di campi prodotti da una query. In questo caso RECORD è un sinonimo.
ROLL FORWARD
Si tratta di un meccanismo per applicare nuovamente le modifiche apportate al database. Talvol-
ta serve per il recupero dei dischi e talvolta per il recupero dell’istanza. Il redo log contiene le
voci redo utilizzate per il roll forward.
ROLLBACK
Il rollback annulla una parte o l’intero lavoro effettuato nel corso della transazione corrente (fino
all’ultimo COMMIT o SAVEPOINT).
DESCRIZIONE ROLLBACK annulla tutti i cambiamenti apportati alle tabelle del database dal-
l’ultimo salvataggio e toglie qualsiasi blocco applicato alle tabelle. Ogni volta che si interrompe
una transazione, a causa di un errore di esecuzione o di un problema all’alimentazione viene
generato un rollback automatico. ROLLBACK non influisce solo sull’ultima istruzione insert,
update o delete, ma su tutte quelle occorse dall’ultimo COMMIT. Questo permette di trattare i
vari spezzoni di lavoro come una singola unità e salvare solo quando tutte le modifiche sono
state effettuate.
Se si specifica un SAVEPOINT, ROLLBACK salta a un punto specifico (etichettato) della
sequenza di transazioni elaborate, il SAVEPOINT. Cancella qualsiasi SAVEPOINT temporaneo e
annulla ogni blocco di tabella o riga occorso dopo la creazione del SAVEPOINT.
Se si specifica FORCE, ROLLBACK effettua un rollback automatico di una transazione sco-
nosciuta identificata dal testo che corrisponde a un ID di transazione locale o globale dalla vista
del dizionario dati DBA_2PC_PENDING.
1230 CAPITOLO 48
ROLLUP
VEDERE ANCHE GROUPING, CUBE, Capitolo 12.
SINTASSI
DESCRIZIONE ROLLUP genera totali parziali per gruppi di righe all’interno di una query.
Vedere il Capitolo 13.
SINTASSI
DESCRIZIONE ROUND arrotonda una data in base al formato specificato. Senza un formato, la
data viene arrotondata al giorno successivo se l’orario coincide con 12:00:00 P.M. (mezzogiorno
esatto) o più tardi, oppure alla data odierna se è prima di mezzogiorno; in altre parole, viene
arrotondata al giorno più vicino. L’ora della data così ottenuta viene impostata a 12 A.M., l’ini-
zio di una giornata.
Formati disponibili per gli arrotondamenti
FORMATO SIGNIFICATO
CC,SCC Secolo (arrotonda al primo gennaio del secolo successivo, a partire dalla mezzanotte esatta del primo
gennaio del 1950, 2050 e così via).
SYEAR,SYYY,Y,YY,YYY,YYYY Anno (arrotonda al primo gennaio dell’anno successivo, a partire dalla mezzanotte esatta del primo
and YEAR luglio).
Q Trimestre (arrotonda a partire dalla mezzanotte esatta del 16 del secondo mese del trimestre, indipen-
dentemente dal numero di giorni del mese).
MONTH,MON,MM,RM Mese (arrotonda a partire dalla mezzanotte esatta del 16 del mese, a prescindere dal numero di giorni
del mese).
IW Giorno della settimana che coincide con il primo giorno dell’anno ISO.
W Arrotonda al giorno più vicino a quello che coincide con il primo giorno del mese.
DDD,DD,J Arrotonda a mezzogiorno esatto del giorno successivo. È il formato predefinito se non ne viene specifi-
cato un altro.
DAY,DY,D Arrotonda alla domenica successiva (primo giorno della settimana) a partire da mezzogiorno esatto di
mercoledì.
HH,HH12,HH24 Arrotonda all’ora intera successiva, a partire da 30 minuti e 30 secondi dopo l’ora.
ROUND(valore,precisione)
sinistra del punto decimale. Un numero intero positivo arrotonda il valore al numero di cifre
indicato a destra del punto decimale.
ESEMPIO
ROUND(123.456,0) = 123
ROUND(123.456,-2) = 100
ROUND(-123.456,2) = -123.46
ROW_NUMBER
VEDERE ANCHE ROWNUM.
SINTASSI
ROWID
ROWID è l’indirizzo logico di una riga, pertanto è unico all’interno del database.
ROWID può essere selezionato o impiegato in una clausola where ma non può essere modi-
ficato da inserimenti, aggiornamenti o cancellazioni. Non si tratta di una vera colonna di dati; è
semplicemente un indirizzo logico creato sulla base di informazioni interne al database. ROWID
è utile all’interno di clausole where per aggiornare o cancellare rapidamente delle righe. ROWID
può variare se la tabella che lo contiene viene esportata e importata.
Il tipo di dati ROWID è una stringa esadecimale che rappresenta l’indirizzo univoco di una
riga di una tabella. Questo tipo di dati è utilizzato soprattutto per i valori restituiti dalla
pseudocolonna ROWID.
ROWIDTOCHAR
VEDERE ANCHE CHARTOROWID, CONVERSIONE, FUNZIONI.
SINTASSI
ROWIDTOCHAR(RowId)
ROWIDTONCHAR
VEDERE ANCHE CHARTOROWID, ROWIDTOCHAR, CONVERSIONE, FUNZIONI.
SINTASSI
ROWIDTONCHAR(RowId)
GUIDA DI RIFERIMENTO ALFABETICA 1233
ROWNUM
VEDERE ANCHE PSEUDOCOLONNE.
SINTASSI
ROWNUM
DESCRIZIONE ROWNUM restituisce il numero di sequenza con cui è stata restituita una riga la
prima volta che è stata selezionata da una tabella. La prima riga ha un valore di ROWNUM pari
a 1, la seconda 2 e così via. Si noti che anche un semplice order by in un’istruzione select può
mettere in disordine i ROWNUM, che sono assegnati alle righe prima di qualsiasi operazione di
ordinamento.
RPAD
VEDERE ANCHE CARATTERI, FUNZIONI; LPAD; LTRIM; RTRIM; TRIM; Capitolo 7.
SINTASSI
RPAD(stringa,lunghezza [ ,'set'])
DESCRIZIONE RPAD fa in modo che una stringa raggiunga una certa lunghezza, aggiungendo
alla sua destra un determinato set di caratteri. Se non si specifica set, il carattere di riempimento
predefinito è uno spazio.
ESEMPIO
produce:
HELLO WORLDWORLDWORLDWOR
RTRIM
VEDERE ANCHE CARATTERI, FUNZIONI; LPAD; LTRIM; RPAD; TRIM; Capitolo 7.
SINTASSI
RTRIM(stringa [,'set'])
DESCRIZIONE RTRIM elimina tutte le occorrenze di un set di caratteri a partire dal lato destro
di una stringa.
ESEMPIO
RTRIM('GEORGE','OGRE')
RTRIM('EDYTHE','HET')
produce:
EDY
RUN
VEDERE ANCHE /, @, @@, EDIT, START.
SINTASSI
R[UN]
DESCRIZIONE RUN visualizza il comando SQL nel buffer SQL e successivamente lo esegue.
RUN è simile al comando /, l’unica differenza è che / non visualizza per primo il comando SQL.
RUOLO
Un ruolo è un insieme di privilegi che un utente può concedere ad altri utenti. Oracle dispone di
diversi ruoli forniti dal sistema, tra cui CONNECT, RESOURCE e DBA. È possibile verificare
i privilegi assegnati ai ruoli tramite le viste del dizionario dati ROLE_SYS_PRIVS e
DBA_SYS_PRIVS. Durante lo sviluppo di un’applicazione, non si dovrebbe fare affidamento
sui ruoli definiti dal sistema, poiché i nomi e i privilegi di questi ruoli potrebbero cambiare nelle
future versioni di Oracle. Per la sintassi utilizzata nella creazione di un ruolo si consulti CREATE
ROLE.
Per esempi riguardanti la creazione e l’uso dei ruoli, si consulti il Capitolo 19.
SAVE
VEDERE ANCHE EDIT, GET, Capitolo 6.
SINTASSI
DESCRIZIONE SAVE salva il contenuto del buffer corrente in un file host di nome file. Se non
si specifica alcuna estensione, viene utilizzata l’estensione SQL. Questa estensione predefinita
può essere modificata con SET SUFFIX. SAVE salva eventuali modifiche ancora pendenti nel
database.
Se il file esiste già, l’opzione CREATE causerà l’annullamento dell’operazione di salvatag-
gio e produrrà un messaggio d’errore. L’opzione REPLACE sostituisce qualsiasi file preesistente
e ne crea di nuovi all’occorrenza.
L’opzione APPEND aggiunge questo file alla fine di qualunque file già esistente o ne crea
uno nuovo se non esiste nessuno.
ESEMPIO
La riga seguente salva il contenuto del buffer corrente in un file di nome lowcost.sql:
save lowcost
GUIDA DI RIFERIMENTO ALFABETICA 1235
SAVEPOINT
VEDERE ANCHE COMMIT, ROLLBACK, SET TRANSACTION.
SINTASSI
SAVEPOINT savepoint;
savepoint A;
savepoint B;
rollback to savepoint B;
Questo mostra come gruppi di istruzioni SQL possano essere raggruppati e annullati insie-
me o singolarmente. In un programma host, oppure con PL/SQL o SQL*PLUS, è possibile
configurare dei SAVEPOINT da cui eseguire il ROLLBACK, in base ai risultati dell’ultima istru-
zione SQL o dell’ultima condizione controllata. ROLLBACK permette di ritornare a un passag-
gio specifico in cui è stato nominato un SAVEPOINT.
Se una funzione, un controllo logico o un’istruzione SQL ha dei problemi, si possono ripri-
stinare i dati del database allo stato precedente. Quindi si può tentare nuovamente.
I nomi dei SAVEPOINT devono essere unici all’interno di una transazione (che termina
dopo un COMMIT o un ROLLBACK incondizionato) ma non necessariamente in tutto il database.
Per esempio, si può assegnare a un SAVEPOINT lo stesso nome di una tabella (operazione che
potrebbe rendere il codice più comprensibile se al SAVEPOINT si assegnasse lo stesso nome
della tabella aggiornata). I nomi dei SAVEPOINT seguono le solite regole di denominazione
degli oggetti.
Se a un nuovo SAVEPOINT si assegna un nome già utilizzato, quello nuovo sostituisce quel-
lo vecchio. Il vecchio nome viene perso definitivamente e non c’è alcun modo di effettuare un
rollback da quel punto.
1236 CAPITOLO 48
SCAN (SQL*PLUS)
Vedere SET.
SCN_TO_TIMESTAMP
VEDERE ANCHE ORA_ROWSCN, FLASHBACK QUERY.
SINTASSI
SCN_TO_TIMESTAMP ( numero )
SCORE
La funzione SCORE viene utilizzata dagli indici CONTEXT in Oracle Text per valutare in che
misura una stringa di testo rispetti i criteri di ricerca specificati. È possibile visualizzare il “pun-
teggio” di una ricerca individuale; più spesso il punteggio viene confrontato con un valore di
soglia. Vedere il Capitolo 25.
SEGMENTO
Un segmento è la memoria fisica dello spazio allocato in una tabella, indice o cluster. Una tabella
possiede un segmento costituito da tutti i suoi extent. Per ogni indice viene definito un segmento
analogo. Un cluster ha almeno due segmenti, uno per i dati e uno per l’indice della chiave di
clusterizzazione.
SEGMENTO DI ROLLBACK
Un segmento di rollback è un’area di memoria di una tablespace che contiene le informazioni
relative alle transazioni utilizzate per garantire l’integrità dei dati durante un rollback e per for-
nire coerenza di lettura in più transazioni. Vedere il Capitolo 40.
SEGMENTO DI UNDO
A partire da Oracle9i, si potrà ricorrere alla gestione automatica degli undo per fornire coerenza
di lettura al posto dei segmenti di rollback. Se si utilizza questa opzione, Oracle gestirà i seg-
GUIDA DI RIFERIMENTO ALFABETICA 1237
menti di undo per tenere traccia delle modifiche e fornire le capacità di rollback. Vedere SEG-
MENTI DI ROLLBACK e il Capitolo 40.
SEGMENTO TEMPORANEO
Si dice segmento temporaneo l’area di memoria all’interno di una tablespace utilizzata per con-
tenere i risultati intermedi di un’istruzione SQL. Per esempio, i segmenti temporanei vengono
utilizzati nel riordino di tabelle molto estese. Solitamente, i segmenti temporanei sono memoriz-
zati in tablespace a essi dedicate; vedere CREATE TABLESPACE.
for_update_clause
subquery ;
subquery::=
DISTINCT
UNIQUE
,
where_clause hierarchical_query_clause group_by_clause
FROM table_reference
ALL
UNION
INTERSECT ( subquery )
MINUS order_by_clause
subquery_factoring_clause::=
select_list::=
query_name
table .*
schema .
view
materialized view
AS
c_alias
expr
table_reference::=
flashback_query_clause t_alias
ONLY ( query_table_expression )
flashback_query_clause t_alias
query_table_expression
( join_clause )
join_clause
flashback_query_clause::=
SCN
AS OF expr
TIMESTAMP
GUIDA DI RIFERIMENTO ALFABETICA 1239
query_table_expression::=
query_name
SUBPARTITION ( subpartition )
sample_clause
@ dblink
schema . table
view @ dblink
materialized view
subquery_restriction_clause
( subquery )
table_collection_expression
sample_clause::=
subquery_restriction_clause::=
READ ONLY
WITH CONSTRAINT constraint
CHECK OPTION
table_collection_expression::=
( + )
TABLE ( collection_expression )
join_clause::=
inner_cross_join_clause
outer_join_clause
1240 CAPITOLO 48
inner_cross_join_clause::=
ON condition
INNER
JOIN table_reference ,
USING ( column )
table_reference
CROSS
outer_join_clause::=
query_partition_clause
table_reference
ON condition
USING ( column )
query_partition_clause::=
expr
PARTITION BY ,
( expr )
outer_join_type::=
FULL
OUTER
LEFT
RIGHT
GUIDA DI RIFERIMENTO ALFABETICA 1241
where_clause::=
WHERE condition
hierarchical_query_clause::=
group_by_clause::=
expr
HAVING condition
GROUP BY rollup_cube_clause
grouping_sets_clause
rollup_cube_clause::=
ROLLUP
( grouping_expression_list )
CUBE
grouping_sets_clause::=
rollup_cube_clause
GROUPING SETS ( )
grouping_expression_list
grouping_expression_list::=
expression_list
expression_list::=
expr
( expr )
1242 CAPITOLO 48
model_clause::=
cell_reference_options return_rows_clause
MODEL
reference_model
main_model
cell_reference_options::=
IGNORE DIMENSION
NAV UNIQUE
KEEP SINGLE REFERENCE
returns_rows_clause::=
UPDATED
RETURN ROWS
ALL
reference_model::=
cell_reference_options
model_column_clauses
main_model::=
MAIN main_model_name
cell_reference_options
model_column_clauses model_rules_clause
model_column_clauses::=
c_alias
query_partition_clause
, ,
model_column::=
AS
c_alias
expr
model_rules_clause::=
UPSERT AUTOMATIC
ORDER
UPDATE SEQUENTIAL
RULES
UNTIL ( condition )
ITERATE ( number )
UPDATE
UPSERT order_by_clause
( cell_assignment = expr )
cell_assignment::=
condition
expr
measure_column [ single_column_for_loop ]
multi_column_for_loop
single_column_for_loop::=
literal
IN ( )
subquery
FOR dimension_column
LIKE pattern INCREMENT
FROM literal TO literal literal
DECREMENT
1244 CAPITOLO 48
multi_column_for_loop::=
,
,
( literal )
FOR ( dimension_column ) IN ( )
subquery
order_by_clause::=
c_alias
for_update_clause::=
schema . table
.
view
OF column
FOR UPDATE
NOWAIT
WAIT integer
DESCRIZIONE SELECT recupera delle righe da una o più tabelle o viste, come comando a sé
stante o come subquery all’interno di altri comandi SQL (con limitazioni) compresi SELECT,
INSERT, UPDATE e DELETE. ALL impone che vengano restituite tutte le righe che soddisfano le
condizioni specificate (ed è l’impostazione predefinita). DISTINCT impone che vengano restitu-
ite solo le righe uniche, gli eventuali doppioni vengono ignorati.
Un * (asterisco) da solo comporta la visualizzazione di tutte le colonne prese da tutte le
tabelle della clausola from. tabella.* significa che verranno visualizzate tutte le colonne di que-
sta tabella. Un asterisco da solo non può essere combinato con qualsiasi altra colonna, mentre
tabella.* può essere seguita da nomi di colonna e espressioni, tra cui ROWID.
select_list può includere qualsiasi tipo di colonna. Può trattarsi del nome di una colonna, di
un letterale, di un calcolo matematico, di una funzione o di una combinazione di funzioni. La
versione più comune è un semplice nome di colonna, eventualmente preceduto dal nome di una
tabella o da un suo alias. alias_colonna è l’alias di una colonna o di un’espressione. L’alias di
colonna può essere preceduto dalla parola AS. L’alias diviene l’intestazione di colonna nella
visualizzazione e può essere indicato mediante i comandi SQL*PLUS COLUMN, TTITLE e
GUIDA DI RIFERIMENTO ALFABETICA 1245
BTITLE. Può inoltre essere utilizzato nella clausola ORDER BY. Se è composto da più di una
parola oppure contiene caratteri che non sono né numeri né lettere, deve essere racchiuso tra
virgolette.
schema, tabella e dblink denotano la tabella o la vista da cui prelevare le righe; schema e
dblink sono facoltativi, la loro assenza fa in modo che Oracle supponga si tratti dell’utente cor-
rente. Specificando il nome utente in una query si può ridurre il carico di lavoro di Oracle e
eseguire la query più velocemente. Nella clausola FROM, si può specificare una subquery. Oracle
esegue la subquery e le righe risultanti vengono trattate come se provenissero da una vista.
alias_tabella in questo caso rinomina la tabella solo per la query corrente. A differenza degli
alias delle espressioni, a questo alias si può fare riferimento da qualsiasi altro punto dell’istru-
zione SELECT, per esempio come prefisso nei nomi di colonne provenienti da questa tabella. Se
una tabella dispone di un alias, questo deve essere utilizzato in ogni prefisso di colonna che lo
richiede. Alle tabelle vengono associati degli alias generalmente quando due tabelle con nomi
lunghi vengono unite tramite join in una query, e quando molte delle loro colonne hanno nomi
identici, rendendo necessaria una denominazione chiara nella clausola SELECT. Inoltre, gli alias
vengono utilizzati spesso in subquery correlate e quando una tabella viene unita tramite join a se
stessa.
condizione può essere qualsiasi espressione valida che vale vero o falso. Può contenere fun-
zioni, colonne (prese da queste tabelle) e letterali. posizione consente alla clausola ORDER BY
di identificare le espressioni in base alla loro posizione relativa nella clausola SELECT piuttosto
che ai loro nomi. Ciò si rivela particolarmente utile nelle espressioni complesse. Si dovrebbe
alternare l’uso delle posizioni ordinali nelle clausole order by; gli alias di colonna possono esse-
re impiegati in terza battuta. Lo standard SQL attuale non prevede alcun supporto per l’uso di
posizioni ordinali nelle clausole ORDER BY e quindi Oracle potrebbe non supportare tale uso in
futuro. ASC e DESC specificano rispettivamente se per ogni espressione nella clausola ORDER
BY si tratta di una sequenza crescente o decrescente. Per un’analisi di queste sequenze, si consul-
ti COLLATION.
colonna è una colonna di una tabella elencata nella clausola from. Non può essere un’espres-
sione, ma deve essere un nome vero di colonna. NOWAIT significa che ogni eventuale select for
update che incontra una riga bloccata viene arrestato e il controllo torna immediatamente al-
l’utente invece di aspettare lo sblocco della risorsa e cercare di aggiornare ancora la riga in breve
tempo.
La clausola for update of inserisce dei blocchi sulle righe selezionate. SELECT . . . FOR
UPDATE OF dovrebbe essere seguita subito da un comando UPDATE...WHERE, oppure da un
COMMIT o ROLLBACK se si decide di non eseguire alcun aggiornamento. FOR UPDATE OF
include anche le operazioni di inserimento e cancellazione. Una volta bloccata una riga, gli altri
utenti non potranno aggiornarla fino a quando non la si libererà con un comando COMMIT (o
AUTOCOMMIT) o ROLLBACK. SELECT... FOR UPDATE OF non può includere DISTINCT,
GROUP BY, UNION, INTERSECT, MINUS, o alcuna funzione di gruppo, come MIN, MAX, AVG,
o COUNT. Le colonne indicate a questo punto non hanno alcun effetto e sono presenti per mera
compatibilità con altri dialetti SQL. Oracle blocca solo le tabelle che appaiono all’interno della
clausola for update. Se non si dispone di una clausola of in cui elencare le tabelle, Oracle blocca
tutte le tabelle della clausola from per aggiornarle. Tutte le tabelle devono trovarsi nello stesso
database e, se sono presenti dei riferimenti a una colonna di tipo LONG o a una sequenza nel-
l’istruzione select, le tabelle devono trovarsi nello stesso database della colonna LONG o della
sequenza.
Se si esegue una query da una tabella partizionata è possibile indicare il nome della partizione
su cui si esegue la query all’interno della clausola from della query. Vedere il Capitolo 17.
1246 CAPITOLO 48
Le altre singole clausole dell’istruzione select sono descritte sotto il loro nome in questo
stesso capitolo. La clausola AS OF {TIMESTAMP|SCN} per le query flashback è stata introdotta
in Oracle9i, Release 2. La clausola VERSIONS BETWEEN per le query di versione flashback è
disponibile a partire da Oracle9 Database 10g.
Altre note
Le clausole devono essere disposte nell’ordine indicato, fatta eccezione per quelle che seguono:
■ CONNECT BY, START WITH, GROUP BY e HAVING, che possono essere inserite in qualsi-
asi ordine relativo le une alle altre;
■ ORDER BY e FOR UPDATE OF, che possono essere inserite in qualsiasi ordine l’una rispetto
all’altra.
DESCRIZIONE Vedere la descrizione delle varie clausole nella forma 1 di SELECT. Di seguito
sono elencati gli elementi caratteristici di Embedded SQL:
■ AT database, che assegna facoltativamente un nome a un database da una istruzione CONNECT
precedente, per un nome di database da una precedente istruzione DECLARE DATABASE.
■ INTO :variabile_host [, variabile_host] è l’elenco di variabili host in cui dovranno essere
scritti i risultati dell’istruzione SELECT. Se una variabile di questa lista è un array, devono
esserlo anche tutte le altre anche se non è necessario che siano della stessa dimensione.
GUIDA DI RIFERIMENTO ALFABETICA 1247
SELECT...INTO
VEDERE ANCHE %ROWTYPE, %TYPE, DECLARE VARIABLE, FETCH.
SINTASSI
SEQUENZA
Una sequenza è un oggetto di database utilizzato per generare numeri interi unici da impiegare
come chiavi primarie. Vedere CREATE SEQUENCE.
1248 CAPITOLO 48
SERVER CONDIVISO
Il server condiviso di Oracle, noto in precedenza come Multi-Threaded Server (MTS), supporta
connessioni a Oracle tramite dispatcher process e processi a server condiviso. I dispatcher process
accettano richieste di connessione da parte degli utenti e i processi a server condiviso comunica-
no con il database. Il server condiviso permette a molti utenti di condividere un piccolo numero
di processi a server condiviso, riducendo così la quantità di memoria richiesta per supportare gli
utenti del database. Il server condiviso è particolarmente efficiente quando ci sono più utenti che
avviano connessioni e quando gli utenti delle applicazioni interrompono spesso le proprie attivi-
tà di inserimento dei dati.
SERVER MULTITHREAD
Vedere SERVER CONDIVISO.
SESSIONTIMEZONE
DESCRIZIONE SESSIONTIMEZONE restituisce il valore del fuso orario della sessione corrente.
ESEMPIO
select SESSIONTIMEZONE from DUAL;
SET
dove caratteristica e valore appartengono all’elenco seguente. I valori predefiniti sono sottolineati.
■ APPI[NFO] {ON|OFF|testo} abilita la registrazione di file dei comandi attraverso il package
DBMS_APPLICATION_INFO. Il nome registrato compare nella colonna Module della tabella
di prestazioni dinamiche V$SESSION.
■ ARRAY[SIZE] {15|n} imposta la dimensione del batch di righe che SQL*PLUS recupera a
ogni prelievo. L’intervallo spazia da 1 a 5000. Valori più grandi migliorano l’efficienza delle
query e delle subquery in cui ha senso recuperare molte righe ma viene utilizzata molta memo-
ria. Valori superiori a 100 raramente producono miglioramenti sensibili a livello di prestazioni.
ARRAYSIZE non ha alcun altro effetto su SQL*PLUS.
■ AUTO[COMMIT] {ON|OFF|IMM[EDIATE]|n} fa in modo che SQL salvi immediatamente qual-
siasi modifica al database non appena ogni comando SQL viene completato. n consente di impo-
stare il numero di comandi dopo cui effettuare il salvataggio. OFF interrompe il salvataggio
automatico obbligando, di fatto, a indicare esplicitamente le richieste di salvataggio tramite il
comando COMMIT. Molti comandi, come QUIT, EXIT, CONNECT e tutti i comandi DDL ese-
guono essi stessi un COMMIT di qualsiasi modifica ancora pendente.
GUIDA DI RIFERIMENTO ALFABETICA 1249
SET (funzione)
VEDERE ANCHE IS A SET, Capitolo 34.
SINTASSI
SET (tabelle_nidificata)
GUIDA DI RIFERIMENTO ALFABETICA 1253
SET CONDITION
La condizione di impostazione (set condition) è un’espressione logica contenente una query, per
esempio “Nome IN (select...)”. Il suo nome deriva dal fatto che la condizione di query produrrà
un gruppo di record.
SET CONSTRAINTS
VEDERE ANCHE VINCOLO DI INTEGRITÀ.
SINTASSI
SET ROLE
VEDERE ANCHE ALTER USER, CREATE ROLE, Capitolo 18.
SINTASSI
DESCRIZIONE SET ROLE abilita o disabilita i ruoli concessi a un utente nella sessione SQL
corrente. La prima opzione consente di specificare dei ruoli fornendo facoltativamente una
password, se il ruolo lo richiede, (vedere CREATE ROLE). La seconda opzione permette di
abilitare tutti (ALL) i ruoli a eccezione (EXCEPT) di quelli indicati, che dovranno essere conces-
si direttamente all’utente, e non tramite altri utenti. L’opzione ALL non abilita i ruoli protetti da
password. La terza opzione, NONE, disabilita tutti i ruoli della sessione corrente.
SET TRANSACTION
VEDERE ANCHE COMMIT, ROLLBACK, SAVEPOINT, TRANSACTION, Capitolo 46.
SINTASSI
SET TRANSACTION
{ { READ { ONLY | WRITE }
| ISOLATION LEVEL { SERIALIZABLE | READ COMMITTED }
| USE ROLLBACK SEGMENT segmento_rollback }
1254 CAPITOLO 48
[NAME 'test']
| NAME 'test' } ;
DESCRIZIONE SET TRANSACTION avvia una transazione. La transazione SQL standard ga-
rantisce la coerenza di lettura a livello di istruzione, assicurando così che i dati di una query
siano coerenti durante l’esecuzione dell’istruzione stessa. Tuttavia, alcune transazioni richiedo-
no garanzie maggiori dato che una serie di istruzioni select, ciascuna all’opera su una o più
tabelle, dovranno visualizzare dati coerenti gli uni con gli altri (ovvero dati che si riferiscono a
uno stesso istante di tempo). SET TRANSACTION READ ONLY specifica questa coerenza di
lettura più forte. Nessuna delle modifiche che altri utenti potrebbero apportare ai dati su cui sono
state eseguite query influirà sulla vista che la transazione ha dei dati stessi. In una transazione di
sola lettura è possibile impiegare solo i comandi select, lock table, set role, alter session e alter
system.
Alle transazioni che contengono i comandi insert, update o delete, Oracle assegna un seg-
mento di rollback. SET TRANSACTION USE ROLLBACK SEGMENT specifica che la transazio-
ne corrente utilizzerà un segmento di rollback specifico.
SET TRANSACTION dev’essere la prima istruzione SQL di una transazione. L’inserimento
di un COMMIT subito prima di SET TRANSACTION assicura la veridicità di questa impostazione.
Il COMMIT alla fine rilascia la vista materializzata dei dati. Questo è importante perché Oracle
ha bisogno di rilasciare le risorse che ha messo da parte per mantenere la coerenza.
SGA
Vedere System Global Area.
SHARED POOL
Un’area nella SGA di Oracle che contiene sia la cache del dizionario dati sia un’area condivisa
per le versioni analizzate di tutti i comandi SQL del database. La sua dimensione è stabilita dal
parametro SHARED_POOL_SIZE che si trova nel file dei parametri di inizializzazione del
database.
SHOW
VEDERE ANCHE SET.
SINTASSI
SHO[W] { opzione }
opzione può essere qualsiasi parametro impostato tramite il comando SET o la sintassi seguente:
variabile_sistema
ALL
BTI[TLE]
ERR[ORS] [ { FUNCTION | PROCEDURE | PACKAGE | PACKAGE BODY |
TRIGGER| VIEW | TYPE | TYPE BODY | DIMENSION | JAVA CLASS } [schema.]nome]
LNO
PARAMETERS [nome_parametro]
PNO
GUIDA DI RIFERIMENTO ALFABETICA 1255
REL[EASE]
REPF[OOTER]
REPH[EADER]
SGA
SPOO[L]
SQLCODE
TTI[TLE]
USER
DESCRIZIONE SHOW visualizza il valore di una (o di tutte) caratteristica di SET o degli altri
oggetti SQL*PLUS. Più di un oggetto (quindi, più di una caratteristica di SET) può seguire la
parola SHOW, e ciascuno viene visualizzato su una linea diversa. Le righe restituite vengono
ordinate alfabeticamente.
variabile_sistema può essere qualsiasi variabile impostata con il comando SET.
BTI[TLE] visualizza la definizione corrente di btitle.
ERR[ORS] mostra gli ultimi errori incontrati durante la compilazione di un oggetto memorizzato.
LNO mostra il numero di linea corrente (la linea della pagina attualmente visualizzata).
PARAMETERS mostra l’impostazione di un parametro specifico, o di tutti se non si specifica un
parametro in particolare.
PNO visualizza il numero della pagina corrente.
REL[EASE] fornisce il numero della release di questa versione di Oracle.
REPF[OOTER] mostra il piè di pagina del report.
REPH[EADER] mostra l’intestazione del report.
SGA mostra le allocazioni di memoria correnti per la SGA.
SPOO[L] mostra la situazione di reindirizzamento dell’output su file (se è attivo o no). Vedere
SPOOL.
SQLCODE mostra il numero del messaggio dell’errore Oracle più recente.
TTI[TLE] visualizza la definizione corrente di ttitle.
USER mostra l’ID dell’utente.
SHOWMODE (SQL*PLUS)
Vedere SET.
SHUTDOWN
VEDERE ANCHE STARTUP, RECOVER, Capitolo 46.
SINTASSI
SIGN
VEDERE ANCHE +, PRECEDENZE, Capitolo 9.
SINTASSI
SIGN(valore)
SIGN(33) = 1
SIGN(-.6) = -1
SIGN(0) = 0
SIN
VEDERE ANCHE ACOS; ASIN; ATAN; ATAN2; COS; COSH; NUMERI, FUNZIONI; SINH;
TAN; Capitolo 9.
SINTASSI
SIN(valore)
SINH
VEDERE ANCHE ACOS; ASIN; ATAN; ATAN2; COS; NUMERI, FUNZIONI; SIN; TAN;
Capitolo 9.
SINTASSI
SINH(valore)
SINTASSI
La sintassi è un insieme di regole che determinano le modalità di scrittura di un’istruzione valida
per un particolare linguaggio di programmazione, come SQL.
GUIDA DI RIFERIMENTO ALFABETICA 1257
SMON
Il System Monitor è uno dei processi in background di Oracle, utilizzato per eseguire il recupero
e il cleanup dei segmenti temporanei inutilizzati. Vedere BACKGROUND, PROCESSO.
SOSTITUZIONE
Vedere &, &&, ACCEPT, DEFINE.
SOUNDEX
VEDERE ANCHE LIKE, Capitolo 7 e Capitolo 25.
SINTASSI
SOUNDEX(stringa)
DESCRIZIONE SOUNDEX trova tutte le parole che hanno un suono simile a una stringa di
esempio. SOUNDEX fa alcune assunzioni sulla pronuncia comune di lettere e combinazioni di
lettere. Le due parole da confrontare devono cominciare con la stessa lettera. Si possono esegui-
re ricerche di tipo SOUNDEX di singole parole all’interno di stringhe testuali negli indici
CONTEXT. Vale solo per la lingua inglese.
ESEMPIO
SOUNDEX('SEPP');
COGNOME NOME TELEFONO
------------------------- ------------------------- ------------
SZEP FELICIA 214-522-8383
SEP FELICIA 214-522-8383
SPACE (SQL*PLUS)
Vedere SET.
SPOOL
VEDERE ANCHE SET, Capitolo 6.
SINTASSI
SPO[OL] [file|OFF|OUT];
avvio che precede l’istruzione SQL, ma prima del comando SPOOL. SPOOL senza parametri
mostra il nome del file di spool corrente (o del più recente).
SQL
SQL (Structured Query Language) è il linguaggio ANSI standard utilizzato per manipolare le
informazioni di un database relazionale, e impiegato dai sistemi di gestione dei database relazionali
Oracle e IBM DB2. SQL si pronuncia “siquel”, anche se è ormai accettata la pronuncia “S.Q.L.”.
SQL*LOADER
SQL*LOADER è un’utility impiegata per il caricamento dei dati in un database Oracle. Vedere
SQLLDR e il Capitolo 21.
SQL*Plus
Vedere SQLPLUS.
SQLCASE (SQL*Plus)
Vedere SET.
SQLCODE
VEDERE ANCHE ECCEZIONI, SQLERRM.
SINTASSI
variabile := SQLCODE
DESCRIZIONE SQLCODE è una funzione di errore che restituisce il numero dell’ultimo erro-
re, ma al di fuori di una sezione di gestione delle eccezioni (vedere ECCEZIONI e WHEN)
restituisce sempre 0. Questo dipende dal fatto che l’occorrenza di un’eccezione (ovvero, quando
SQLCODE è diversa da zero) dovrebbe trasferire immediatamente il controllo alla sezione di
gestione delle eccezioni del blocco PL/SQL Una volta in questa sezione, è possibile verificare il
valore di SQLCODE o utilizzarlo per assegnare un valore a una variabile.
SQLCODE non può essere usato in un’istruzione SQL (per esempio, per inserire il valore
del codice di errore in una tabella di errori). Tuttavia, è possibile impostare una variabile a
SQLCODE e utilizzare quest’ultima in un’istruzione SQL:
sql_error := sqlcode;
insert into PROBLEMLOG values (sql_error);
SQLCONTINUE (SQL*Plus)
Vedere SET.
GUIDA DI RIFERIMENTO ALFABETICA 1259
SQLERRM
VEDERE ANCHE ECCEZIONI, EXCEPTION_INIT, PRAGMA, SQLCODE.
SINTASSI
SQLERRM[(intero)]
error_message := sqlerrm;
error_message := sqlerrm(1403);
Al di fuori di una sezione di gestione delle eccezioni (vedere SQLCODE), questa funzione
senza un argomento intero restituisce sempre “normal, successful completion”. In una sezione di
gestione delle eccezioni, si ottiene uno dei messaggi seguenti.
■ Il messaggio associato a un errore di Oracle.
■ Le parole “User-defined exception” per un’eccezione sollevata esplicitamente dall’utente
quando non è stato assegnato un messaggio.
■ Un messaggio definito dall’utente caricato con PRAGMA EXCEPTION_INIT.
SQLLDR
VEDERE ANCHE Capitolo 21.
SINTASSI
Parametri per il comando SQLLDR:
Discardmax Numero massimo di righe da scartare prima di interrompere il caricamento. L’impostazione predefinita
consente tutte le eliminazioni.
Skip Numero di righe logiche nel file di input da scartare prima di avviare il caricamento dei dati. Solitamente
viene utilizzato durante i nuovi caricamenti dallo stesso file di input, che seguono un caricamento parzia-
le. Il valore predefinito è 0.
(segue)
1260 CAPITOLO 48
(continua)
Rows Numero di righe su cui eseguire contemporaneamente il commit. Questo parametro serve per suddivide-
re la dimensione della transazione durante il caricamento L’impostazione predefinita per i caricamenti a
percorso convenzionale è 64, per i caricamenti a percorso diretto è tutte le righe.
Bindsize Dimensione dell’array di bind a percorso convenzionale espressa in byte. L’impostazione predefinita
dipende dal sistema operativo.
Parfile Nome del file di parametri che contiene altre specifiche dei parametri di caricamento.
Skip_Unusable_Indexes Consente di eseguire caricamenti in tabelle che hanno indici in stati inutilizzabili. L’impostazione predefinita
è FALSE.
Skip_Index_Maintenance Interrompe la gestione degli indici per i caricamenti a percorso diretto, lasciandoli in uno stato inutilizzabile.
L’impostazione predefinita è FALSE.
Readsize Dimensione del buffer di lettura espressa in byte; il valore predefinito è 1048576.
External_Table Usa la tabella esterna per il caricamento. L’impostazione predefinita è NOT_USED, gli altri valori sono
GENERATE_ONLY ed EXECUTE.
ColumnArrayRows Numero di righe per array di colonna a percorso diretto. Il valore predefinito è 5000.
StreamSize Dimensione del buffer di flusso a percorso diretto espressa in byte. Il valore predefinito è 256000.
Resumable Attiva o disattiva la possibilità del riutilizzo nella sessione corrente; l’impostazione predefinita è FALSE.
Resumable_Timeout Tempo di attesa, in secondi per il parametro Resumable. Il valore predefinito è 7200.
Date_Cache Dimensioni (in voci) della cache di conversione dei dati. La dimensione predefinita è 1000.
DESCRIZIONE SQL*LOADER carica i dati dai file esterni in tabelle del database Oracle. Per
esempi, si rimanda al Capitolo 21. La sintassi del control file è:
Options clause
OPTIONS ( options )
GUIDA DI RIFERIMENTO ALFABETICA 1261
Load statement
UNRECOVERABLE
CONTINUE_LOAD
BYTE
SEMANTICS
LENGTH CHAR BIG ENDIAN
BYTEORDER
CHARACTER LITTLE
CHECK
BYTEORDERMARK
NOCHECK
INSERT
APPEND
, REPLACE
,
concatenate_clause PRESERVE BLANKS BEGINDATA
into_table_clause
infile_clause
DISCARDS
integer
DISCARDFILE filename DISCARDMAX
var
fix
’string’
" "
X’hex_string
str
integer
1262 CAPITOLO 48
concatenate_clause
integer
CONCATENATE
( integer )
THIS
NEXT PRESERVE (
pos_spec )
str
CONTINUEIF PRESERVE ( operator
X’hex_str’
LAST
into_table_clause
PARTITION name INSERT
( )
SUBPARTITION name REPLACE
INTO TABLE name
TRUNCATE
APPEND
INSERT
REPLACE
TRUNCATE
INDEXES
SORTED ( name ) SINGLEROW APPEND
OPTIONS ( FILE=database_filename )
OID_spec
delim_spec NULLCOLS
SID_spec FIELDS TRAILING
TREAT AS typename
SKIP n
field_list
GUIDA DI RIFERIMENTO ALFABETICA 1263
field_condition
enclosure_spec
FIELDS OPTIONALLY
enclosure_spec
termination_spec
delim_spec
enclosure_spec
OPTIONALLY
enclosure_spec
termination_spec
full_fieldname
full_fieldname
termination_spec
WHITESPACE
BY X’hexstr’
TERMINATED
’string’
EOF
enclosure_spec
’string’ ’string’
AND
BY X’hexstr’ X’hexstr’
ENCLOSED
oid_spec
OID ( fieldname )
sid_spec
fieldname
SID ( )
CONSTANT SID_val
1264 CAPITOLO 48
field_list
dgen_fld_spec
scalar_fld_spec
( column_name col_obj_fld_spec )
collection_fld_spec
filler_fld_spec
dgen_fld_spec
RECNUM
SYSDATE
CONSTANT val
COUNT
, incr
SEQUENCE ( MAX )
integer
REF_spec
SID_spec init_spec
BFILE_spec
ref_spec
,
fieldname
REF ( )
CONSTANT val
init_spec
AND
NULLIF
field_condition
DEFAULTIF
GUIDA DI RIFERIMENTO ALFABETICA 1265
bfile_spec
fieldname fieldname
BFILE ( , )
CONSTANT val CONSTANT val
filler_fld_spec
FILLER pos_spec datatype_spec PIECED
BOUNDFILLER
scalar_fld_spec
LOBFILE_spec
datatype_spec PIECED
POSITION pos_spec
lobfile_spec
fieldname CHARACTERSET name
LOBFILE (
CONSTANT filename
BYTE
SEMANTICS
LENGTH CHAR BIG ENDIAN
BYTEORDER
CHARACTER LITTLE
CHECK
BYTEORDERMARK
NOCHECK
)
pos_spec
:
end
start –
( +integer )
*
1266 CAPITOLO 48
datatype_spec
delim_spec
SIGNED
( length ) UNSIGNED
( length ) delim_spec
INTEGER
EXTERNAL
( length ) delim_spec
EXTERNAL
FLOAT
( length ) delim_spec
EXTERNAL
DECIMAL
, scale
ZONED ( precision )
DOUBLE
BYTEINT
SIGNED
UNSIGNED
SMALLINT
( length )
RAW
EXTERNAL ( graphic_char_length )
GRAPHIC
VARGRAPHIC ( max_length )
VARCHAR
datatype_spec_cont
datatype_spec_cont
( length ) delim_spec
CHAR
, max_size_bytes
VARCHARC ( length_of_length )
, max_size_bytes
VARRAWC ( length_of_length )
LONG ( max_bytes )
VARRAW
LOCAL
TIME fractional_second_precision WITH TIME ZONE "mask"
TIMESTAMP
year_precision
YEAR TO MONTH
day_precision fractional_second_precision
DAY TO SECOND
INTERVAL
GUIDA DI RIFERIMENTO ALFABETICA 1267
col_obj_fld_spec
TREAT AS typename init_spec sql_string_spec
COLUMN OBJECT field_list
collection_fld_spec
nested_table_spec
BOUNDFILLER
varray_spec
nested_table_spec
SDF_spec count_spec init_spec
NESTED TABLE field_list
delim_spec
varray_spec
SDF_spec count_spec init_spec
VARRAY field_list
delim_spec
sdf_spec
field_name
BYTE
SEMANTICS
LENGTH CHAR
count_spec
fieldname
COUNT ( )
CONSTANT positive_integer
1268 CAPITOLO 48
SQLNUMBER (SQL*PLUS)
Vedere SET.
SQLPLUS
VEDERE ANCHE Capitolo 6.
SINTASSI
DESCRIZIONE SQLPLUS avvia SQL*PLUS. Se si inseriscono sia il nome utente sia la password,
SQL*PLUS si collega al database predefinito. Se si specifica solo il proprio nome utente,
SQL*PLUS richiede anche la password, che non viene mai visualizzata mentre la si inserisce. Se
si specifica @database si ottiene la connessione al database specificato, invece che a quello
predefinito. @database può essere ovunque, purché il computer cui si è collegati sia connesso a
questo database tramite Oracle Net. Non devono esserci spazi tra password e @database. Per
ulteriori informazioni su Oracle Net, si rimanda al Capitolo 22. @file eseguirà il file di avvio non
appena SQL*PLUS è stato caricato. Prima di @file deve esserci uno spazio. Se il nome utente e
la password non vengono digitati sulla linea di comando con SQLPLUS, devono trovarsi sulla
prima linea del file. Se sono presenti nel file, e li si inserisce nella linea di comando si ottiene un
messaggio di errore che non influirà sulla corretta esecuzione del file di avvio. Per inserire il
nome utente e la password all’inizio del file, li si separi tramite una barra obliqua (/):
GEORGE/MISTY
/NOLOG avvia SQL*PLUS, ma non connette l’utente al database Oracle. Per collegarsi a
Oracle, si dovrà ricorrere a CONNECT. (Vedere CONNECT).
-SILENT elimina tutte le visualizzazioni delle schermate di SQL*PLUS, compresi i prompt
dei comandi e persino le informazioni sul collegamento a SQL*PLUS e sul copyright. In questo
modo, è possibile che altri programmi usino SQL*PLUS in maniera trasparente.
-? visualizza la versione corrente e il numero del livello di SQL*PLUS senza avviarlo.
ESEMPIO
Ecco un avvio classico di SQL*PLUS:
sqlplus george/misty
sqlplus george/misty@EDMESTON
Per avviare il file di report REPORT6 che contiene nome utente e password sulla prima linea
si utilizzi:
sqlplus @report6
Per avviare il file di report REPORT6 che include il nome utente e la password nella prima
linea sul database EDMESTON si utilizzi:
SQLPREFIX (SQL*PLUS)
Vedere SET.
SQLPROMPT (SQL*PLUS)
Vedere SET.
SQLTERMINATOR (SQL*PLUS)
Vedere SET.
SQRT
VEDERE ANCHE POWER.
SINTASSI
SQRT(valore)
SQRT(64) = 8
START
VEDERE ANCHE @, @@, ACCEPT, DEFINE, SPOOL, Capitolo 6.
SINTASSI
DESCRIZIONE START esegue il contenuto del file di avvio specificato (che prende questo
nome poiché è avviato proprio da questo comando). Il file può contenere qualsiasi comando di
SQL*PLUS. Se non si specifica alcun tipo di file, START suppone si tratti di .sql. Gli eventuali
parametri che seguono il nome del file vengono sostituiti in variabili contenute nel file di avvio;
le variabili devono avere come nomi &1, &2, &3 e così via e ricevono i parametri in ordine da
sinistra a destra. Ogni occorrenza di &1 nel file di avvio ottiene il primo parametro. I parametri
costituiti da più di una parola possono essere racchiusi tra apici (''); altrimenti, saranno limitati a
una singola parola o a un singolo numero.
ESEMPIO
in cui il file checkout.sql contiene una variabile di nome &1, in cui verrà sostituita la stringa
‘INNUMERACY’.
1270 CAPITOLO 48
STARTUP
VEDERE ANCHE
SHUTDOWN, RECOVER, Capitolo 46.
SINTASSI
[FORCE][RESTRICT][PFILE=nomefile][QUIET][MOUNT[nomedb]|
[OPEN [opzioni_apertura][nomedb]]|NOMOUNT]
[PFILE=nomefile]{UPGRADE|DOWNGRADE} [QUIET]
DESCRIZIONE
STARTUP avvia un’istanza. FORCE arresta un’istanza in esecuzione con SHUTDOWN ABORT
prima di avviarla. RESTRICT consente la connessione solo agli utenti con i privilegi richiesti.
L’opzione PFILE consente di specificare un file init.ora da usare durante l’avvio (al posto dello
spfile standard). STARTUP RECOVER ha lo stesso effetto dell’esecuzione di RECOVER
DATABASE e dell’avvio di un’istanza. UPGRADE avvia il database in modalità OPEN UPGRADE
e dovrebbe essere usata solo quando un database viene avviato per la prima volta con una nuova
versione del software Oracle.
STATS_BINOMIAL_TEST
SINTASSI
stats_binomial_test::=
TWO_SIDED_PROB
EXACT_PROB
,
ONE_SIDED_PROB_OR_MORE
ONE_SIDED_PROB_OR_LESS
STATS_BINOMIAL_TEST ( expr1 , expr2 , p )
DESCRIZIONE
STATS_BINOMIAL_TEST è un test di probabilità esatto utilizzato per le variabili dicotome, dove
esistono solo due valori possibili. Viene verificata la differenza tra una proporzione di esempio e
una proporzione data.
GUIDA DI RIFERIMENTO ALFABETICA 1271
STATS_CROSSTAB
SINTASSI
stats_crosstab::=
CHISQ_OBS
CHISQ_SIG
CHISQ_DF
, PHI_COEFFICIENT
CRAMERS_V
CONT_COEFFICIENT
COHENS_K
STATS_CROSSTAB ( expr1 , expr2 )
DESCRIZIONE
STATS_CROSSTAB prende tre argomenti: due espressioni e un valore di restituzione del tipo
VARCHAR2. expr1 ed expr2 sono le due variabili nominali analizzate. La funzione restituisce
un numero, determinato dal valore del terzo argomento. I valori per il terzo argomento sono
CHISQ_OBS, CHISQ_SIG, CHISQ_DF, PHI_COEFFICIENT, CRAMERS_V, CONT_
COEFFICIENT e COHENS_K.
STATS_F_TEST
SINTASSI
stats_f_test::=
STATISTIC
DF_NUM
, DF_DEN
ONE_SIDED_SIG
TWO_SIDED_SIG
STATS_F_TEST ( expr1 , expr2 )
DESCRIZIONE
STATS_F_TEST verifica se due varianze sono diverse in modo significativo. Il valore osservato
di f è il rapporto di una varianza con l’altra, pertanto i valori molto diversi da 1 in genere indicano
differenze significative.
1272 CAPITOLO 48
STATS_KS_TEST
SINTASSI
stats_ks_test::=
STATISTIC
,
SIG
STATS_KS_TEST ( expr1 , expr2 )
DESCRIZIONE
STATS_KS_TEST è una funzione Kolmogorov-Smirnov che confronta due campioni
per veder se provengono dalla stessa popolazione o da popolazioni che hanno la medesima
distribuzione. Non presuppone che la popolazione di provenienza dei campioni sia distribuita
normalmente.
STATS_MODE
SINTASSI
STATS_MODE (espr)
DESCRIZIONE
STATS_MODE prende come proprio argomento un gruppo di valori e restituisce il valore che
compare con maggiore frequenza. Se esiste più di una modalità, Oracle ne sceglie una e restituisce
solo quel valore.
STATS_MW_TEST
SINTASSI
stats_mw_test::=
STATISTIC
U_STATISTIC
,
ONE_SIDED_SIG
TWO_SIDED_SIG
STATS_MW_TEST ( expr1 , expr2 )
DESCRIZIONE
Un test Mann-Whitney che confronta due campioni indipendenti per verificare l’ipotesi nulla
che le due the popolazioni hanno la stessa funzione di distribuzione a scapito dell’ipotesi alternativa
che le due funzioni di distribuzione siano diverse.
GUIDA DI RIFERIMENTO ALFABETICA 1273
STATS_ONE_WAY_ANOVA
SINTASSI
stats_one_way_anova::=
SUM_SQUARES_BETWEEN
SUM_SQUARES_WITHIN
DF_BETWEEN
DF_WITHIN
,
MEAN_SQUARES_BETWEEN
MEAN_SQUARES_WITHIN
F_RATIO
SIG
STATS_ONE_WAY_ANOVA ( expr1 , expr2 )
DESCRIZIONE
STATS_ONE_WAY_ANOVA è un’analisi a senso unico della funzione di varianza. Verifica le
differenze nelle medie per la portata statistica confrontando due stime diverse di varianza (errore
quadratico medio e quadrati medi intermedi). La funzione restituisce un numero, determinato
dal valore del terzo argomento (per default è SIG, abbreviazione di “significance”).
STATS_T_TEST_*, FUNZIONI
SINTASSI
stats_t_test::=
STATISTIC
DF
,
STATS_T_TEST_INDEP ONE_SIDED_SIG
STATS_T_TEST_INDEPU TWO_SIDED_SIG
( expr1 , expr2 )
STATS_T_TEST_ONE
STATS_T_TEST_PAIRED
DESCRIZIONE
Il t-test misura la portata di una differenza di medie. La si può utilizzare per confrontare le medie
di due gruppi o le medie di un gruppo con una costante. Le funzioni STATS_T_TEST_* prendono
tre argomenti: due espressioni e un valore di restituzione di tipo VARCHAR2. Le funzioni
restituiscono un numero, determinato dal valore del terzo argomento (per default è
TWO_SIDED_SIG).
1274 CAPITOLO 48
STATS_WSR_TEST
SINTASSI
stats_wsr_test::=
STATISTIC
, ONE_SIDED_SIG
TWO_SIDED_SIG
STATS_WSR_TEST ( expr1 , expr2 )
DESCRIZIONE
STATS_WSR_TEST è un test Wilcoxon Signed Ranks di campioni accoppiati per determinare se
la mediana delle differenze tra i due campioni è molto diversa da zero. Se non si specifica il terzo
argomento, per default è TWO_SIDED_SIG.
STDDEV
VEDERE ANCHE FUNZIONI DI GRUPPO, VARIANCE, Capitolo 9.
SINTASSI
STDDEV_POP
VEDERE ANCHE FUNZIONI DI GRUPPO, STTDEV, STDDEV_SAMP.
SINTASSI
STDDEV_SAMP
VEDERE ANCHE FUNZIONI DI GRUPPO, STTDEV, STDDEV_POP.
SINTASSI
STORAGE
VEDERE ANCHE BLOCK, CREATE CLUSTER, CREATE INDEX, CREATE ROLLBACK
SEGMENT, CREATE MATERIALIZED VIEW, CREATE MATERIALIZED VIEW LOG,
CREATE TABLE, CREATE TABLESPACE e le analoghe istruzioni ALTER.
SINTASSI
storage_clause::=
M
INITIAL integer
M
NEXT integer
MINEXTENTS integer
integer
MAXEXTENTS
UNLIMITED
PCTINCREASE integer
STORAGE ( FREELISTS integer )
M
integer
NULL
OPTIMAL
KEEP
BUFFER_POOL RECYCLE
DEFAULT
1276 CAPITOLO 48
DESCRIZIONE La clausola STORAGE può essere utilizzata in qualsiasi delle istruzioni CREA-
TE e ALTER riportate nella sezione “Vedere anche”. Non essendo un’istruzione SQL, non può
rimanere da sola. Nei paragrafi seguenti, un blocco sarà un blocco di database (vedere BLOCK)
con una dimensione che varia in base al sistema operativo in uso e ai parametri di inizializzazione
del database.
INITIAL alloca il primo extent di spazio in un oggetto. Se non si specifica questa opzione, per
default si usano cinque blocchi di dati. L’extent iniziale più piccolo che si possa allocare è di due
blocchi di dati, mentre il più grande dipende dal sistema operativo. È possibile esprimere queste
dimensioni sotto forma di numeri interi semplici o di interi seguiti da K o M per indicare rispet-
tivamente kilobyte o megabyte.
NEXT rappresenta la dimensione dell’extent allocato una volta riempito l’extent iniziale. Se
non viene specificato altro, l’impostazione predefinita è di cinque blocchi di dati. L’extent suc-
cessivo più piccolo che si possa allocare è di un blocco di dati, mentre il più grande dipende dal
sistema operativo. Si possono utilizzare K e M per i kilobyte e i megabyte.
PCTINCREASE controlla il tasso di crescita degli extent che seguono il secondo. Se viene
impostato a 0, ogni extent aggiuntivo avrà la stessa dimensione del secondo, specificato da NEXT.
Se PCTINCREASE è un numero intero positivo, ogni extent successivo sarà più grande di quello
precedente della percentuale specificata. Per esempio, se PCTINCREASE vale 50 (l’impostazione
predefinita), ogni extent aggiuntivo sarà del 50 per cento più grande del precedente. PCTINCREASE
non può essere negativo. Il valore minimo è zero mentre il massimo dipende dal sistema opera-
tivo. Oracle arrotonda la dimensione degli extent al multiplo intero successivo della dimensione
di blocco impostata dal sistema operativo.
Per default, MINEXTENTS vale 1 (o 2 per i segmenti di rollback) se non viene specificato, e
ciò significa che quando si crea l’oggetto, viene allocato solo l’extent iniziale. Un numero mag-
giore di 1 crea diversi extent (che non devono necessariamente essere attigui su disco, come fa
ogni extent) e la dimensione di ogni extent viene determinata dai valori impostati con INITIAL,
NEXT e PCTINCREASE. Tutti questi extent verranno allocati quando si crea l’oggetto.
MAXEXTENTS imposta il numero massimo di extent allocabili. Il numero minimo è 1, il
massimo dipende dal sistema operativo. Si può specificare un valore MAXEXTENTS come
UNLIMITED.
OPTIMAL imposta la dimensione ottimale, espressa in byte, di un segmento di rollback. Si
possono utilizzare K e M per i kilobyte e i megabyte. Oracle annulla dinamicamente l’allocazione
degli extent nel segmento di rollback per mantenere la dimensione ottimale. NULL significa che
Oracle non annulla mai l’allocazione degli extent nei segmenti di rollback e questo è il compor-
tamento predefinito. Si deve fornire una dimensione maggiore o uguale allo spazio iniziale allo-
cato per il segmento di rollback dai parametri MINEXTENTS, INITIAL, NEXT e PCTINCREASE.
FREELIST GROUPS fornisce il numero di gruppi di free list, con un valore predefinito pari
a 1. Questa impostazione si applica all’opzione Real Application Clusters di Oracle per le tabel-
le, i cluster e gli indici.
FREELISTS imposta il numero di free list in ogni gruppo.
BUFFER_POOL imposta il buffer pool in cui verranno letti i blocchi della tabella. Per default,
tutti i blocchi vengono letti nel pool DEFAULT. Si possono creare pool separati per i blocchi che
si desidera mantenere in memoria più a lungo (il pool di conservazione) oppure per quelli che si
desidera rimuovere rapidamente dalla memoria (il pool di riciclo).
Per la maggior parte delle applicazioni, si consiglia di utilizzare le funzioni di automazione
della gestione dello spazio di Oracle, comprese le tablespace gestite localmente, nelle quali si
definiscono i parametri di memorizzazione una volta in modo che sia Oracle a gestire lo spazio
per gli oggetti creati nella tablespace.
GUIDA DI RIFERIMENTO ALFABETICA 1277
STORE
VEDERE ANCHE SAVE, START, Capitolo 6.
SINTASSI
store settings.sql
SUBQUERY
Una query (ovvero, un’istruzione select) può essere utilizzata all’interno di altre istruzioni SQL
(dette istruzioni padre o esterne), tra cui CREATE TABLE, delete, insert, select, update e la
versione SQL*PLUS del comando COPY, per definire le righe e le colonne che il padre utilizze-
rà nella propria esecuzione. I risultati della query figlia (definita anche subquery) non vengono
visualizzati ma vengono passati all’istruzione SQL esterna. Questo costrutto deve rispettare le
regole seguenti.
■ Nei comandi update e CREATE TABLE, la subquery deve restituire un valore per ogni colon-
na da inserire o aggiornare. I valori vengono quindi utilizzati dall’istruzione SQL esterna per
inserire o aggiornare le righe.
■ Una subquery non può contenere le clausole order by e for update of.
■ Nella clausola where di un’istruzione select viene utilizzata una subquery “correlata” che si
riferisce all’alias della tabella utilizzata dal comando di selezione esterno. Questa subquery vie-
ne verificata una volta per ogni riga valutata per la selezione dall’istruzione select esterna (una
subquery standard valutata una sola volta per la query padre). Per ulteriori dettagli, si rimanda al
Capitolo 13.
A parte le restrizioni appena citate, una subquery obbedisce alle stesse leggi che governano
le normali istruzioni select.
SUBSTR
VEDERE ANCHE ||; CARATTERI, FUNZIONI; INSTR; Capitolo 7.
SINTASSI
substr::=
SUBSTR
SUBSTRB
, substring_length
SUBSTRC ( string , position )
SUBSTR2
SUBSTR4
1278 CAPITOLO 48
DESCRIZIONE SUBSTR taglia una parte di una stringa partendo dal carattere la cui posizione
è inizio e terminando dopo un numero di caratteri definito da conta. Se non si specifica quest’ul-
timo parametro, la stringa viene tagliata a partire da inizio fino alla fine.
ESEMPIO
SUBSTR('RIVISTA',5)
produce:
STA
SUFFIX (SQL*PLUS)
Vedere SET.
SUGGERIMENTI
All’interno di una query, è possibile specificare dei suggerimenti che dirigono l’ottimizzatore
basato sui costi durante l’elaborazione della query stessa. Per specificare un suggerimento, si
utilizza la sintassi seguente. Si digiti la stringa che segue subito dopo la parola chiave select:
/*+
FULL(biblioteca)
*/
Per una descrizione di tutti i suggerimenti disponibili e dell’impatto che esercitano sull’ela-
borazione delle query, si rimanda al Capitolo 38.
SUM
VEDERE ANCHE COMPUTE, FUNZIONI DI AGGREGAZIONE, Capitolo 9.
SINTASSI
DESCRIZIONE SUM è la somma di tutti i valori di un gruppo di righe. DISTINCT fa sì che SUM
sommi ogni valore unico al totale una sola volta; opzione generalmente poco utile.
SYNONYM
Un sinonimo è un nome assegnato a una tabella, a una vista o a una sequenza per semplificare i
successivi riferimenti a quella stessa risorsa. Se si ha la possibilità di accedere a una tabella di un
altro utente, è possibile crearne un sinonimo e impiegare quest’ultimo per riferirsi alla tabella
senza introdurre il nome dell’altro utente come qualificatore. Vedere i Capitoli 23 e 42.
GUIDA DI RIFERIMENTO ALFABETICA 1279
SYSAUX
A partire da Oracle Database 10g la tablespace SYSAUX viene creata con il comando CREATE
DATABASE. SYSAUX contiene tabelle relative al sistema (come il repository delle statistiche)
che non fanno parte del nucleo centrale del dizionario dati.
SYS_CONNECT_BY_PATH
VEDERE ANCHE CONNECT BY, Capitolo 14.
SINTASSI
SYS_CONTEXT
VEDERE ANCHE CREATE CONTEXT.
SINTASSI
SYS_DBURIGEN
VEDERE ANCHE Capitolo 47.
SINTASSI
SYS_DBURIGEN
( { colonna | attributo } [rowid]
[, { colonna | attributo } [rowid]]...
[, 'text ( )'] )
DESCRIZIONE SYS_DBURIGEN accetta una o più colonne oppure uno o più attributi come
propri argomenti, e facoltativamente un RowID, generando l’URL di un tipo di dati DBUriType
per una colonna o un oggetto riga particolari. Quindi, si potrà utilizzare questo URL per recupe-
rare un documento XML dal database.
1280 CAPITOLO 48
Tutte le colonne o gli attributi indicati devono risiedere nella stessa tabella. Inoltre, devono
eseguire la funzione di una chiave primaria. In altre parole, non devono effettivamente corri-
spondere alle chiavi primarie della tabella, ma devono fare riferimento a un valore unico. Se si
specificano più colonne, tutte tranne quella finale identificano le righe del database mentre l’ul-
tima colonna specificata identifica la colonna all’interno delle righe.
Per default, l’URL punta a un documento XML formattato. Se si desidera che l’URL punti
solo al testo del documento, si specifichi l’opzione facoltativa ‘text()'. (In questo contesto XML,
la parola “text” scritta in minuscolo è una parola chiave e non un segnaposto sintattico).
SYS_EXTRACT_UTC
VEDERE ANCHE Capitolo 10.
SINTASSI
SYS_EXTRACT_UTC ( data/ora_con_fuso_orario )
SYS_GUID
SINTASSI
SYS_GUID ( )
DESCRIZIONE SYS_GUID genera e restituisce un identificativo unico (un valore di tipo RAW)
costituito da 16 byte. Sulla maggior parte delle piattaforme, l’identificativo creato è costituito da
un identificatore host e da un processo o un da un identificatore di thread del processo oppure da
un thread che invoca la funzione, e da un valore non ripetuto (sequenza di byte) per quel proces-
so o thread.
SYS_TYPEID
VEDERE ANCHE Capitolo 36.
SINTASSI
SYS_TYPEID ( valore_tipo_oggetto )
DESCRIZIONE SYS_TYPEID restituisce l’ID del tipo più specifico dell’operando. Questo valo-
re viene utilizzato principalmente per identificare la colonna discriminante del tipo che funge da
base per una colonna sostituibile. Per esempio, si può utilizzare il valore restituito da
SYS_TYPEID per costruire un indice sulla colonna discriminante del tipo.
SYS_XMLAGG
VEDERE ANCHE SYS_XMLGEN, Capitolo 47.
SINTASSI
SYS_XMLGEN
VEDERE ANCHE SYS_XMLAGG, Capitolo 47.
SINTASSI
DESCRIZIONE SYS_XMLGEN accetta un’espressione che viene valutata a una particolare riga
e colonna del database, restituendo un’istanza del tipo SYS.XMLType che contiene un docu-
mento XML. espr può essere un valore scalare, un tipo definito dall’utente oppure un’istanza
XMLType.
Se espr è un valore scalare, la funzione restituisce un elemento XML che contiene il valore
scalare. Se espr è un tipo, la funzione associa gli attributi del tipo definito dall’utente agli ele-
menti XML. Se espr è un’istanza XMLType, la funzione include il documento in un elemento
XML; il nome di tag predefinito di questo elemento è ROW.
Per default, gli elementi del documento XML corrispondono agli elementi di espr. Per esem-
pio, se espr si risolve in un nome di colonna, l’elemento XML di inclusione avrebbe lo stesso
nome di colonna. Se si desidera formattare il documento XML in modo differente, si specifichi
fmt, che è un’istanza dell’oggetto SYS.XMLGenFormatType.
SYSDATE
VEDERE ANCHE Capitolo 10.
SINTASSI
SYSDATE
SYSTIMESTAMP
VEDERE ANCHE Capitolo 10.
SINTASSI
SYSTIMESTAMP
TABELLA
Una tabella è la struttura di memorizzazione dei dati fondamentali per i sistemi di gestione dei
database relazionali. Una tabella è costituita da una o più unità d’informazione (righe), ciascuna
contenente gli stessi tipi di valori (colonne). Vedere CREATE TABLE.
Per creare STRANO come tabella di solo indice, occorre creare su di essa un vincolo
PRIMARY KEY.
In generale, le tabelle di solo indice sono adatte per le tabelle associative in relazioni di tipo
molti a molti. Idealmente, una tabella di solo indice avrà poche colonne (o nessuna) che non
fanno parte della sua chiave primaria.
Vedere il Capitolo 17 e CREATE TABLE.
GUIDA DI RIFERIMENTO ALFABETICA 1283
TABELLA ESTERNA
Una tabella esterna è un file che è esterno al database cui si può accedere tramite i comandi SQL.
Per i dettagli sulla creazione e l’uso delle tabelle esterne, si rimanda al Capitolo 26.
TABELLA NIDIFICATA
Una tabella annidata è, come suggerisce il nome stesso, una tabella contenuta all’interno di
un’altra. In questo caso, si tratta di una tabella rappresentata sotto forma di una colonna all’inter-
no di un’altra tabella. È possibile avere diverse righe della tabella annidata associate a ciascuna
riga della tabella principale. Non c’è alcun limite al numero di voci per riga. Per dettagli relativi
alla creazione, uso e query di tabelle annidate, si consulti il Capitolo 34.
TABELLA OGGETTO
Una tabella oggetto è una tabella in cui ogni riga è un oggetto riga. Vedere il Capitolo 36 e la
parte relativa al comando CREATE TABLE.
TABELLA PARTIZIONATA
Una tabella partizionata è una tabella le cui righe siano state partizionate su diverse tabelle più
piccole.
TABLE, PL/SQL
VEDERE ANCHE DATI, TIPI; RECORD (PL/SQL).
SINTASSI
DESCRIZIONE Una dichiarazione TABLE crea un nuovo tipo che potrà essere utilizzato nella
dichiarazione di variabili di quel tipo. Una tabella PL/SQL ha un’unica colonna e una chiave
intera e può avere un numero qualsiasi di righe. Il tipo di dati della colonna può essere un tipo
standard PL/SQL (compresi i RECORD ma escluse altre tabelle), o può essere un riferimento a
un tipo di una colonna particolare già utilizzato in un’altra tabella del database. I campi possono
anche avere un qualificatore NOT NULL, che specifica che il campo deve sempre avere un valore
definito.
La clausola index by binary integer è indispensabile e ricorda che l’indice è necessariamente
intero. Si può fare riferimento a qualsiasi riga della tabella menzionando il suo indice tra parentesi.
Se si fa riferimento a un indice cui non è stato ancora assegnato alcun dato, PL/SQL solleva
l’eccezione NO_DATA_FOUND.
TABLESPACE
Una tablespace è un file o un insieme di file utilizzato per memorizzare dati di Oracle. Un
database Oracle è costituito dalla tablespace SYSTEM e molto probabilmente da altre tablespace.
Vedere i Capitoli 20 e 46.
1284 CAPITOLO 48
TABLESPACE TRASPORTABILE
Una tablespace trasportabile è una tablespace che può essere “scollegata” da un database e “col-
legata” in un altro. Per essere trasportabile, una tablespace, o un insieme di tablespace, deve
essere autonoma. Il gruppo di tablespace non può contenere oggetti che fanno riferimento a
oggetti contenuti in altre tablespace. Pertanto, se si trasporta una tablespace contenente indici, si
dovrà spostare la tablespace che contiene le tabelle base degli indici come parte del medesimo
insieme di tablespace trasportabili. Migliore è l’organizzazione e la distribuzione degli oggetti
tra le tablespace, più semplice sarà la creazione di un gruppo autonomo di tablespace da traspor-
tare.
Per trasportare le tablespace, è necessario creare un insieme di tablespace, copiarlo o spo-
starlo nel nuovo database quindi collegare il gruppo al nuovo database. I database devono risie-
dere sul medesimo sistema operativo, con la stessa versione di Oracle e del set di caratteri.
Fare riferimento al Capitolo 46 per ulteriori dettagli.
TAN
VEDERE ANCHE ACOS; ASIN; ATAN; ATAN2; COS; COSH; NUMERI, FUNZIONI; SIN;
TANH; Capitolo 9.
SINTASSI
TAN(valore)
TANH
VEDERE ANCHE ACOS; ASIN; ATAN; ATAN2; COS; COSH; NUMERI, FUNZIONI; SIN;
TAN; Capitolo 9.
SINTASSI
TANH(valore)
TEMA
Un tema è una particolare tipologia di documento di testo. Le voci di testo possono contenere
temi che non compaiono come parole nel documento stesso. Per esempio, un documento riguar-
GUIDA DI RIFERIMENTO ALFABETICA 1285
dante un mutuo può avere come tema la parola “banca” anche se questa non appare nel docu-
mento. Vedere il Capitolo 24.
TERMOUT (SQL*PLUS)
Vedere SET.
TIME (SQL*PLUS)
Vedere SET.
TIMESTAMP
Il tipo di dati TIMESTAMP (precisione_secondo_frazionario) registra i valori anno, mese e
giorno delle date, così come i valori ora, minuto e secondi degli orari, in cui precisio-
ne_secondo_frazionario è il numero di cifre contenute nella parte frazionaria del campo dei
secondi della data/ora. I valori validi per precisione_secondo_frazionario sono compresi tra 0 e
9. Il valore predefinito è 6. vedere DATI, TIPI e il Capitolo 9.
TIMING (SQL*Plus)
VEDERE ANCHE CLEAR, SET.
SINTASSI
DESCRIZIONE TIMING tiene traccia del tempo trascorso da START a STOP tramite un nome di
area. START apre un’area di temporizzazione e le assegna come titolo area. Il titolo deve essere
di un’unica parola. Possono esistere contemporaneamente più aree: quella creata più di recente
rimane l’area di temporizzazione corrente finché non viene cancellata. In quel momento, l’area
immediatamente precedente diventa quella corrente. Questo significa che le aree di temporiz-
zazione sono annidate. L’area più recente mostrerà sempre il valore di tempo minimo, perché il
1286 CAPITOLO 48
tempo trascorso delle aree precedenti sarà, per definizione, più lungo. Il tempo totale di qualun-
que area di temporizzazione è il suo tempo di rete più quelli di tutte le aree create dopo di lei.
SHOW fornisce il nome dell’area di temporizzazione corrente e il tempo trascorso.
STOP fornisce il nome dell’area di temporizzazione corrente e il tempo trascorso, cancella
l’area e rende corrente l’area immediatamente precedente (se esiste). Per dettagli sul significato
preciso del tempo nel proprio computer, si consulti SQL*Plus User’s Guide and Reference del
proprio sistema operativo.
ESEMPIO
Per creare un’area di temporizzazione di nome 1 si digiti:
timing start 1
timing show
timing stop
TO_BINARY_DOUBLE
VEDERE ANCHE TO_BINARY_FLOAT.
SINTASSI
TO_BINARY_FLOAT
VEDERE ANCHE TO_BINARY_DOUBLE.
SINTASSI
SINTASSI
TO_CHAR(data,'formato')
TO_CHAR(numero,'formato')
DESCRIZIONE TO_CHAR riformatta un numero o una data in base a formato. data dev’essere
una colonna definita come il tipo di dati DATE di Oracle. Non può essere una stringa, neppure se
è nel formato standard (DD-MON-YY). L’unico modo di utilizzare una stringa in cui data com-
paia nella funzione TO_CHAR consiste nel racchiuderla in una funzione TO_DATE. I formati
disponibili per questa funzione sono numerosi. Sono elencati alle voci NUMERICI, FORMATI;
e DATE, FORMATI.
ESEMPIO
Si osservi il formato dell’esempio seguente. È necessario operare in questo modo per evitare che
SQL*PLUS utilizzi il formato di data predefinito di TO_CHAR che è lungo circa 100 caratteri:
DATANASCITA Formattata
--------- ------------------------------
20-MAY-49 20/05/49
TO_CLOB
VEDERE ANCHE Capitolo 35.
SINTASSI
DESCRIZIONE TO_CLOB converte i valori NCLOB in una colonna di tipo LOB o altre stringhe
di caratteri in valori CLOB. car può essere uno qualsiasi tra i tipi di dati CHAR, VARCHAR2,
NCHAR, NVARCHAR2, CLOB o NCLOB. Oracle esegue questa funzione convertendo i dati
del LOB di base dal set di caratteri nazionali al set di caratteri del database. Si osservi che i valori
1288 CAPITOLO 48
LONG possono essere convertiti direttamente in colonne di tipo CLOB tramite il comando ALTER
TABLE.
TO_DATE
VEDERE ANCHE DATE,FORMATI; DATE, FUNZIONI; TO_CHAR; Capitolo 10.
SINTASSI
TO_DATE(stringa,'formato')
DESCRIZIONE TO_DATE converte una stringa il cui formato è quello specificato in una data
Oracle. Questa funzione accetta anche un numero al posto della stringa, ma con alcune limita-
zioni. stringa è una stringa letterale, un numero letterale o una colonna di database che contiene
un numero o una stringa. In tutti i casi, tranne uno, il formato deve corrispondere a quello de-
scritto da formato. Solo se la stringa è nel formato ‘DD-MON-YY’ si può omettere il formato. Si
osservi che formato è limitato. Per un elenco di formati accettabili per TO_DATE, si consulti
DATE, FORMATI.
ESEMPIO
TO_DATE('
---------
22.02.02
TO_DSINTERVAL
VEDERE ANCHE DATI, TIPI.
SINTASSI
DESCRIZIONE TO_DSINTERVAL converte una stringa del tipo di dati CHAR, VARCHAR2,
NCHAR o NVARCHAR2 in un tipo INTERVAL DAY TO SECOND. car è la stringa di caratteri
da convertire L’unico parametro NLS valido che si può specificare in questa funzione è NLS_NU-
MERIC_CHARACTERS. Questo argomento può avere come forma: NLS_NUMERIC_CHA-
RACTERS = “dg” dove d e g rappresentano rispettivamente il carattere decimale e il separatore
di gruppo.
TO_LOB
VEDERE ANCHE INSERT, Capitolo 35.
SINTASSI
TO_LOB(colonna_long)
DESCRIZIONE TO_LOB converte i valori LONG nella colonna_long in valori LOB. Questa
funzione può essere applicata solo a una colonna di tipo LONG, e solo nel select list di una
subquery in un comando insert.
GUIDA DI RIFERIMENTO ALFABETICA 1289
TO_MULTI_BYTE
VEDERE ANCHE CONVERSIONE, FUNZIONI; Capitolo 10.
SINTASSI
TO_MULTI_BYTE(stringa)
TO_NCHAR (carattere)
VEDERE ANCHE CONVERSIONE, FUNZIONI; TRANSLATE …USING.
SINTASSI
DESCRIZIONE TO_NCHAR (carattere) converte una stringa di caratteri, CLOB o NCLOB dal
set di caratteri del database nel set di caratteri nazionali. Questa funzione equivale alla funzione
TRANSLATE ... USING con una clausola USING nel set di caratteri nazionali.
TO_NCHAR(data/ora)
VEDERE ANCHE CONVERSIONE, FUNZIONI.
SINTASSI
DESCRIZIONE TO_NCHAR (data/ora) converte una stringa di caratteri del tipo di dati DATE,
TIMESTAMP, TIMESTAMP WITH TIME ZONE, TIMESTAMP WITH LOCAL TIME ZONE,
INTERVAL MONTH TO YEAR o INTERVAL DAY TO SECOND dal set di caratteri del database
nel set di caratteri nazionali.
TO_NCHAR(numero)
VEDERE ANCHE CONVERSIONE, FUNZIONI.
SINTASSI
DESCRIZIONE TO_NCHAR (numero) converte un numero in una stringa nel set di caratteri del
tipo di dati NVARCHAR2. Le opzioni facoltative fmt e param_nls corrispondenti a n possono
essere del tipo di dati DATE, TIMESTAMP, TIMESTAMP WITH TIME ZONE, TIMESTAMP
WITH LOCAL TIME ZONE, INTERVAL MONTH TO YEAR o INTERVAL DAY TO SECOND.
TO_NCLOB
VEDERE ANCHE CONVERSIONE, FUNZIONI; Capitolo 35.
1290 CAPITOLO 48
SINTASSI
DESCRIZIONE TO_NCLOB converte i valori CLOB in una colonna di tipo LOB o altre stringhe
di caratteri in valori NCLOB. car può essere un qualsiasi tipo di dati CHAR, VARCHAR2,
NCHAR, NVARCHAR2, CLOB o NCLOB. Oracle implementa questa funzione convertendo il
set di caratteri della colonna di tipo LOB dal set di caratteri del database nel set di caratteri
nazionali.
TO_NUMBER
VEDERE ANCHE CONVERSIONE, FUNZIONI; Capitolo 9.
SINTASSI
TO_NUMBER('333.46')
TO_SINGLE_BYTE
VEDERE ANCHE CONVERSIONE, FUNZIONI; Capitolo 11.
SINTASSI
TO_SINGLE_BYTE(stringa)
DESCRIZIONE TO_SINGLE_BYTE converte i caratteri a più byte di una stringa di caratteri nei
relativi equivalenti a byte singoli. Se un carattere multibyte non ha un equivalente monobyte, la
funzione lo restituisce senza modificarlo.
TO_TIMESTAMP
VEDERE ANCHE CONVERSIONE, FUNZIONI; TO_CHAR; TIMESTAMP;
TO_TIMESTAMP_TZ.
SINTASSI
DESCRIZIONE TO_TIMESTAMP converte car del tipo di dati CHAR, VARCHAR2, NCHAR o
NVARCHAR2 in un valore del tipo di dati TIMESTAMP con un formato fmt se car non è nel
formato predefinito del tipo di dati TIMESTAMP. In questa funzione, l’opzione facoltativa
param_nls ha lo stesso scopo che aveva nella funzione TO_CHAR per la conversione delle date.
GUIDA DI RIFERIMENTO ALFABETICA 1291
TO_TIMESTAMP_TZ
VEDERE ANCHE CONVERSIONE, FUNZIONI; TO_TIMESTAMP; TIMESTAMP WITH
TIME ZONE.
SINTASSI
DESCRIZIONE TO_TIMESTAMP_TZ converte car del tipo di dati CHAR, VARCHAR2, NCHAR
o NVARCHAR2 in un valore del tipo di dati TIMESTAMP WITH TIMEZONE.
TO_YMINTERVAL
VEDERE ANCHE CONVERSIONE, FUNZIONI; INTERVAL YEAR TO MONTH.
SINTASSI
TO_YMINTERVAL ( car )
DESCRIZIONE TO_YMINTERVAL converte una stringa di caratteri del tipo di dati CHAR,
VARCHAR2, NCHAR o NVARCHAR2 in un tipo INTERVAL YEAR TO MONTH, in cui car
è la stringa di caratteri da convertire.
TRANSAZIONE
Una transazione è una sequenza di istruzioni SQL che Oracle trattaTA come un’unica entità.
L’insieme di modifiche viene reso permanente tramite l’istruzione COMMIT. Gli effetti di una
transazione possono essere annullati in toto o in parte attraverso l’istruzione ROLLBACK.
Oracle gestisce le transazioni sia con meccanismi di blocco (vedere LOCK) sia con un mo-
dello di coerenza multiversione, che in sostanza si comporta come se ogni transazione dispones-
se di una propria copia del database, ossia crea più versioni concorrenti dello stesso database.
Una transazione inizia con l’esecuzione della prima istruzione SQL che la riguarda e termina
con le istruzioni COMMIT o ROLLBACK. Per default, Oracle garantisce che le transazioni di-
spongano di una coerenza di lettura a livello di istruzione, ovvero quando si esegue una query i
dati rimangono congelati mentre Oracle li raccoglie e li restituisce al programma. Se però una
transazione ha più query, ciascuna è coerente con se stessa ma non è detto che lo sia con le altre.
Se si desidera mantenere una visuale coerente dei dati durante un’intera transazione, questa deve
utilizzare un meccanismo di coerenza di lettura a livello di transazione che garantisce che una
transazione non risentirà degli effetti del salvataggio di altre transazioni concorrenti. Queste
transazioni di sola lettura, riconoscibili perché iniziano con l’istruzione SET TRANSACTION
READ ONLY , possono eseguire solo query e alcuni comandi di controllo (vedere SET
TRANSACTION).
TRANSLATE
VEDERE ANCHE REPLACE, Capitolo 11.
SINTASSI
TRANSLATE(stringa,da,a)
1292 CAPITOLO 48
DESCRIZIONE TRANSLATE esamina ogni carattere in stringa, poi controlla da per vedere se il
carattere è presente nella stringa. In caso affermativo, TRANSLATE annota la posizione in cui è
stato trovato il carattere in da e guarda nella stessa posizione di a. Qualsiasi carattere trovi in
questa posizione, viene sostituito a quello di stringa.
ESEMPIO
TRANSLATE … USING
VEDERE ANCHE CONVERSIONE, FUNZIONI, CONVERT, TO_NCHAR, UNISTR.
SINTASSI
DESCRIZIONE TRANSLATE… USING converte testo nel set di caratteri specificato per le con-
versioni tra il set di caratteri del database e quello di caratteri nazionali. L’argomento testo è
l’espressione da convertire.
Se si specifica l’argomento USING CHAR_CS, testo viene convertito nel set di caratteri del
database. Il tipo di dati dell’output è VARCHAR2.
Se invece si specifica l’argomento USING NCHAR_CS, testo viene convertito nel set di
caratteri nazionali. Il tipo di dati dell’output è NVARCHAR2.
Questa funzione è simile alla funzione CONVERT di Oracle, ma dev’essere impiegata al
posto di CONVERT se il tipo di dati dell’input o dell’output utilizzato è CHAR o NVARCHAR2.
Se l’input contiene codepoint UCS2 o caratteri come la barra contraria (\), è necessario utilizzare
la funzione UNISTR.
TREAT
VEDERE ANCHE DEREF, REF, Capitolo 36.
SINTASSI
TRIGGER
Un trigger di database è una stored procedure associata a una tabella che Oracle esegue automa-
ticamente al verificarsi di uno o più eventi (prima, dopo o al posto di un inserimento, un aggior-
namento o una cancellazione) che la riguardano. I trigger possono essere eseguiti sull’intera
tabella o singolarmente su ciascuna riga della tabella. Per una discussione completa sui trigger e
relativi esempi, si rimanda al Capitolo 28, mentre per la sintassi si consulti la voce CREATE
TRIGGER in questo capitolo.
TRIM
VEDERE ANCHE LTRIM, RTRIM, Capitolo 7.
SINTASSI
TRIM
( [{ { LEADING | TRAILING | BOTH } [caratteri_da_tagliare])
| caratteri_da_tagliare
} FROM ] origine_da_tagliare )
DESCRIZIONE TRIM consente di tagliare i caratteri iniziali o finali (oppure entrambi) da una
stringa di caratteri. Se caratteri_da_tagliare o origine_da_tagliare è un letterale, lo si deve
racchiudere tra apici.
Se si specifica LEADING, Oracle rimuove qualsiasi carattere iniziale uguale a caratte-
ri_da_tagliare. Se invece si specifica TRAILING, Oracle rimuove qualsiasi carattere finale ugua-
le a caratteri_da_tagliare. Se si specifica BOTH o nessuna delle tre opzioni, Oracle rimuove i
caratteri iniziali e finali uguali a caratteri_da_tagliare.
Se si specifica solo sorgente_da_tagliare, Oracle rimuove gli spazi vuoti iniziali e finali Se
origine_da_tagliare o caratteri_da_tagliare è un valore NULL, la funzione TRIM restituisce un
valore NULL.
ESEMPIO
TRIMOUT (SQL*PLUS)
Vedere SET.
TRUNC(data,'formato')
Il risultato di TRUNC è sempre una data con l’ora impostata a mezzanotte, l’inizio di una
giornata.
TRUNC(valore,precisione)
TRUNC(123.45,0) = 123
TRUNC(123.45,-1) = 120
TRUNC(123.45,-2) = 100
TRUNCATE
VEDERE ANCHE CREATE CLUSTER, DELETE, DROP TABLE, TRIGGER, Capitolo 17.
SINTASSI
TRUNCATE
{ TABLE [schema .] tabella [{ PRESERVE | PURGE } MATERIALIZED VIEW LOG]
| CLUSTER [schema .] cluster }
[{ DROP | REUSE } STORAGE];
TTITLE (SQL*Plus)
VEDERE ANCHE ACCEPT, BTITLE, DEFINE, PARAMETRI, REPFOOTER, REPHEADER,
Capitolo 14.
SINTASSI
DESCRIZIONE TTITLE inserisce un titolo (che può anche occupare più di una linea) all’inizio
di ogni pagina di un report. OFF e ON rispettivamente eliminano e ripristinano la visualizzazione
GUIDA DI RIFERIMENTO ALFABETICA 1295
del testo senza modificarne i contenuti. TTITLE da solo visualizza le opzioni correnti e testo o
variabile.
testo è il titolo che si desidera assegnare a questo report, mentre variabile è una variabile
definita dall’utente o una gestita a livello di sistema come SQL.LNO (numero di linea corrente),
SQL.PNO (numero di pagina corrente), SQL.RELEASE (numero della release corrente di Oracle),
SQL.SQLCODE (codice di errore corrente) e SQL.USER (nome utente).
SQL*PLUS utilizza ttitle nella sua nuova forma se riconosce nella prima parola dopo ttitle
un’opzione valida. Le opzioni valide sono:
■ COL n salta direttamente alla posizione n (dal margine sinistro) della linea corrente.
■ S[KIP] n visualizza n linee vuote. Se non viene specificato alcun numero, viene stampata una
sola linea vuota. Se n vale 0, non viene visualizzata alcuna linea vuota e la posizione di stampa
corrente diventa la prima della linea corrente (all’estremità sinistra della pagina).
■ TAB n salta di n tabulazioni verso destra (verso sinistra se n è negativo).
■ BOLD stampa i dati dell’output in grassetto.
■ LE[FT], CE[NTER] e R[IGHT] giustificano a sinistra, centrano o giustificano a destra i dati
della linea corrente. Eventuali stringhe di testo e variabili che seguissero questi comandi verreb-
bero giustificate anch’esse, fino alla fine del comando. CENTER e RIGHT utilizzano il valore
impostato da SET LINESIZE per determinare dove disporre il testo e le variabili.
■ FORMAT stringa specifica il modello del formato che controlla la visualizzazione del testo o
delle variabili seguenti e segue la stessa sintassi di FORMAT in un comando COLUMN; per
esempio, FORMAT A12 o FORMAT $999,990.99. Ogni volta che compare FORMAT, esso scaval-
ca il precedente formato attivo fino a quel momento. Se non si specifica alcun modello per
FORMAT, viene utilizzato quello impostato da SET NUMFORMAT. Se NUMFORMAT non è stato
definito, viene utilizzato il modello predefinito per SQL*PLUS.
Le date vengono visualizzate in base al formato predefinito, a meno che la data di una
variabile non sia stata convertita mediante la funzione TO_CHAR.
In un comando ttitle può essere utilizzato un numero qualsiasi di opzioni, blocchi di testo e
variabili. Ognuno viene stampato nell’ordine specificato e viene formattato in base alle clausole
che lo precedono.
TUPLA
È un sinonimo di riga.
TYPE
Vedere TIPO DI DATI ASTRATTO e CREATE TYPE.
DESCRIZIONE PL/SQL consente di assegnare un tipo di dati esterno di Oracle a un tipo di dati
definito dall’utente. Questo può contenere una lunghezza, una precisione o una scala. Questo
1296 CAPITOLO 48
tipo di dati esterno viene reso equivalente a quello definito dall’utente e viene assegnato a tutte
le variabili host di quel tipo. Per un elenco dei tipi di dati esterni, si consulti la guida di program-
mazione del precompilatore.
TYPE BODY
Vedere TIPO DI DATI ASTRATTO, CREATE TYPE, e METODO.
TZ_OFFSET
VEDERE ANCHE SESSIONTIMEZONE, DBTIMEZONE.
SINTASSI
TZ_OFFSET
( { ' nome_fuso_orario'
| '{ + | - } hh : mi'
| SESSIONTIMEZONE
| DBTMEZONE
})
UID
VEDERE ANCHE SESSION.
SINTASSI
UID
DESCRIZIONE UID restituisce un valore intero che identifica in modo univoco l’utente della
sessione (l’utente connesso).
UNDEFINE
VEDERE ANCHE ACCEPT, DEFINE, PARAMETRI, Capitolo 15.
SINTASSI
UNDEF[INE] variabile
GUIDA DI RIFERIMENTO ALFABETICA 1297
ESEMPIO
Per eliminare la definizione della variabile di nome Total, si digiti:
undefine Total
UNDERLINE (SQL*PLUS)
Vedere SET.
UNION
VEDERE ANCHE INTERSECT, MINUS, OPERATORI DI QUERY, Capitolo 13.
SINTASSI
select...
UNION [ALL]
select...
DESCRIZIONE UNION combina due query. Restituisce tutte le righe distinte di entrambe le
istruzioni select oppure, qualora sia indicata l’opzione ALL, tutte le righe senza controllarne
l’unicità (e quindi comprendendo eventuali doppioni). Il numero di colonne e i tipi di dati devo-
no essere identici tra le due istruzioni select, condizione non richiesta per i nomi delle colonne.
Per una discussione riguardante le differenze importanti e gli effetti di INTERSECT, UNION e
MINUS, e il ruolo che la precedenza ha nei risultati, si rimanda Capitolo 12.
UNISTR
VEDERE ANCHE CONVERSIONE, FUNZIONI, CONVERT, TRANSLATE…USING.
SINTASSI
UNISTR ( "stringa" )
DESCRIZIONE UNISTR accetta come proprio argomento una stringa in un qualsiasi set di
caratteri e la restituisce nel formato UNICODE del set di caratteri UNICODE del database. Per
includere nella stringa i caratteri codepoint UCS2, si utilizzi la barra contraria di escape (\)
seguita dal numero successivo. Per includere la stessa barra contraria, la si faccia precedere da
un’altra barra rovesciata (\\).
Questa funzione assomiglia alla funzione TRANSLATE ... USING, con l’unica differenza che
UNISTR offre il carattere di escape per i codepoint UCS2 e per le barre contrarie.
1298 CAPITOLO 48
UNITÀ DI LAVORO
In Oracle, una transazione equivale a un’unità di lavoro logica e comprende tutte le istruzioni
SQL da quando ci si è collegati, si è salvato per l’ultima volta o si sono annullati i cambiamenti.
Per questo motivo, una transazione può racchiudere una o più istruzioni SQL.
DESCRIZIONE Vedere la descrizione delle varie clausole in UPDATE (Forma 3). Gli elementi
tipici di Embedded SQL sono i seguenti:
■ AT dbnome, che facoltativamente assegna a un database aperto precedentemente da un’istru-
zione CONNECT il nome di un database preso da una precedente istruzione DECLARE DATABASE.
■ FOR :intero_host, che imposta il numero massimo di righe da recuperare. intero è il nome di
una variabile host.
■ espr può comprendere una variabile host :variabile[:indicatore].
■ La clausola where può contenere variabili o array host.
■ CURRENT OF aggiorna l’ultima riga recuperata del cursore specificato. Tuttavia, il cursore
dev’essere aperto e posizionato sulla riga. In caso contrario, CURRENT OF, che fa parte della
clausola where, fa sì che quest’ultima non trovi alcuna riga da poter aggiornare. Il cursore de-
v’essere stato dichiarato precedentemente in un’istruzione DECLARE CURSOR mediante
select...for update of.
Se una variabile host di set o where è un array, allora tutte le variabili host di set e where
devono essere array, anche se non necessariamente della stessa dimensione. Se si tratta di array,
update viene eseguito una volta per ciascun gruppo di componenti dell’array, e può aggiornare
zero o più righe. Il numero massimo dipende dalla dimensione dell’array più piccolo o dal valore
intero della clausola for, se ne è stato specificato uno. Per ulteriori dettagli si consulti FOR.
GUIDA DI RIFERIMENTO ALFABETICA 1299
UPDATE [utente.]tabella[@dblink]
SET { colonna = espressione | colonna = (select espressione...)
[ [,colonna = espressione]... |
[,colonna = (select espressione...)]... ] |
(colonna [,colonna]...) = (subquery)}
[WHERE {condizione | CURRENT OF cursor}];
where_clause returning_clause
update_set_clause ;
1300 CAPITOLO 48
DML_table_expression_clause::=
PARTITION ( partition )
SUBPARTITION ( subpartition )
@ dblink
schema . table
view @ dblink
materialized view
subquery_restriction_clause
( subquery )
table_collection_expression
subquery_restriction_clause::=
READ ONLY
WITH CONSTRAINT constraint
CHECK OPTION
table_collection_expression::=
( + )
TABLE ( collection_expression )
update_set_clause::=
( column ) = ( subquery )
expr
column = ( subquery )
SET
DEFAULT
expr
VALUE ( t_alias ) =
( subquery )
GUIDA DI RIFERIMENTO ALFABETICA 1301
where_clause::=
WHERE condition
returning_clause::=
, ,
DESCRIZIONE UPDATE aggiorna (modifica) i valori delle colonne elencate nella tabella speci-
ficata. La clausola where può contenere una subquery correlata. Una subquery può eseguire
selezioni dalla tabella aggiornata, anche se deve restituire solo una riga. Senza alcuna opzione
where, vengono aggiornate tutte le righe. Con una clausola where, vengono aggiornate solo le
righe selezionate. Le espressioni vengono valutate all’esecuzione del comando e i loro risultati
sostituiscono i valori correnti delle colonne nelle righe.
L’eventuale subquery deve selezionare lo stesso numero di colonne (con tipi di dati compa-
tibili) di quelle racchiuse tra parentesi sul lato sinistro dell’opzione set. Le colonne impostate
uguali a una certa espressione possono precedere le colonne tra parentesi impostate uguali a una
certa subquery, tutte all’interno di un’unica istruzione update.
ESEMPIO
Per impostare a NULL tutti i valori di Editore:
update BIBLIOTECA set Editore = NULL ;
Il codice seguente aggiorna la città di Walpole nella tabella COMFORT impostando a NULL
tutti i valori Precipitazione, la temperatura massima uguale a quella di Manchester e quella
minima pari alla massima meno 10 gradi.
update COMFORT set Precipitazione = NULL,
(Mezzogiorno, Mezzanotte) =
(select Temperatura, Temperatura - 10
from CLIMA
where Citta = 'MANCHESTER')
where Citta = 'WALPOLE';
UPDATEXML
VEDERE ANCHE Capitolo 47.
SINTASSI
UPDATEXML (istanza_XMLType_,
[stringa_Xpath, espr_valore [,stringa_Xpath, espr_valore …]
[, stringa_spazionomi ] )
UPPER
VEDERE ANCHE LOWER, Capitolo 7.
SINTASSI
UPPER(stringa)
produce:
GUARDA CHE HAI FATTO!
UROWID
UROWID è il tipo di dati utilizzato per le chiavi primarie delle tabelle di solo indice, conosciuto
anche come Universal RowID. La dimensione massima e quella predefinita sono di 4.000 byte.
Vedere DATI, TIPI e CREATE TABLE.
USER
VEDERE ANCHE UID.
SINTASSI
USER
DESCRIZIONE User è il nome attraverso cui l’utente corrente è riconosciuto da Oracle. User è
una funzione, e come tale può essere sottoposta a query in qualsiasi istruzione SELECT.
ESEMPIO
USERENV
VEDERE ANCHE CARATTERI, FUNZIONI.
SINTASSI
USERENV(opzione)
DESCRIZIONE USERENV è una funzione tradizionale, sostituita dallo spazio di nomi UserEnv
di SYS_CONTEXT. Le opzioni e i relativi valori di restituzione sono i seguenti.
GUIDA DI RIFERIMENTO ALFABETICA 1303
'CLIENT_INFO' CLIENT_INFO restituisce fino a 64 byte di informazioni sulla sessione dell’utente che possono essere
memorizzati da un’applicazione che usa il package DBMS_APPLICATION_INFO.
'ENTRYID' ENTRYID restituisce l’identificativo della voce di audit disponibile. Questo attributo non può essere utiliz-
zato in istruzioni SQL distribuite. Per usare questa parola chiave in USERENV, è necessario impostare a
TRUE il parametro di inizializzazione AUDIT_TRAIL.
'ISDBA' ISDBA restituisce ‘TRUE' se l’utente è stato autenticato con privilegi DBA, tramite il sistema operativo
oppure tramite un password file.
'LANG' LANG restituisce l’abbreviazione ISO per il nome della lingua, una forma più breve rispetto al parametro
‘LANGUAGE'.
'LANGUAGE' LANGUAGE restituisce la lingua e il territorio utilizzati attualmente dalla sessione insieme al set di carat-
teri del database in questa forma:
language_territory.characterset
'SESSIONID' SESSIONID restituisce l’identificativo di sessione di audit. Questo attributo non può essere utilizzato in
istruzioni SQL distribuite.
'TERMINAL' TERMINAL restituisce l’identificativo del sistema operativo per il terminale della sessione corrente. Nelle
istruzioni SQL distribuite, questo attributo restituisce l’identificativo della sessione locale. In un ambiente
distribuito, questo attributo è supportato solo per le istruzioni SELECT remote, e non per le operazioni
remote di inserimento, aggiornamento o cancellazione.
USERNAME
username è una parola che identifica un utente autorizzato del sistema operativo installato nel
computer host o di Oracle. A ciascun username è sempre associata una password.
VALORE PREDEFINITO
Il valore predefinito è un valore che viene utilizzato se non ne viene specificato o inserito espli-
citamente un altro.
VALUE
VEDERE ANCHE DEREF, REF, Capitolo 36.
SINTASSI
VALUE ( variabile_correlazione )
DESCRIZIONE In un’istruzione SQL, VALUE accetta come proprio argomento una variabile di
correlazione (alias di tabella) associata a una riga di una tabella oggetto e restituisce le istanze
dell’oggetto memorizzate in questa tabella oggetto. Il tipo delle istanze dell’oggetto è il medesi-
mo di quello della tabella oggetto. Vedere il Capitolo 33.
SINTASSI
VAR_POP
VEDERE ANCHE FUNZIONI DI GRUPPO, VAR_SAMP, VARIANCE.
SINTASSI
VAR_SAMP
VEDERE ANCHE FUNZIONI DI GRUPPO, VAR_POP, VARIANCE.
SINTASSI
VARCHAR2
Vedere DATI, TIPI.
VARIABILE INDICATORE
VEDERE ANCHE : (due punti, prefisso della variabile host), guida di programmazione del
precompilatore.
SINTASSI
DESCRIZIONE Una variabile indicatore, utilizzata quando sia il nome sia l’indicatore sono
nomi di variabili del linguaggio di host, è un campo di dati il cui valore indica se una variabile
host dev’essere o meno considerata come NULL (la parola chiave INDICATOR è inserita solo
per semplificare la lettura e non ha alcun effetto).
nome può essere qualsiasi nome dei dati di una variabile host, utilizzata nel programma di
host e contenuta nella sezione delle dichiarazioni del precompilatore. indicatore è definito an-
ch’esso nella sezione delle dichiarazioni del precompilatore ed equivale a un intero di due byte.
Pochi linguaggi procedurali consentono l’uso diretto di una variabile contenente un valore
NULL o indefinito. Oracle e SQL richiedono invece alcune modifiche minime. Per far sì che i
linguaggi per i quali Oracle ha sviluppato precompilatori supportino le variabili NULL, una va-
riabile indicatore viene associata alla variabile host in modo che si comporti come un flag, indi-
cando cioè se la variabile è pari a NULL oppure no. La variabile host e la sua indicatrice possono
essere utilizzate e impostate separatamente nel linguaggio host ma risultano sempre concatenate
sia in SQL che in PL/SQL.
ESEMPIO
BEGIN
select Titolo, NomeAutore into :Titolo, :NomeAutore:IndNomeAutore
from BIBLIOTECA_AUTORE;
IF :NomeAutore:IndNomeAutore IS NULL
THEN :NomeAutore:IndNomeAutore := 'Nessun Autore'
END IF;
END;
VARIABILI UTENTE
Vedere ACCEPT, DEFINE, PARAMETRI.
SINTASSI
variabile [CONSTANT]
{tipo | identificativo%TYPE | [utente.]tabella%ROWTYPE}
[NOT NULL]
[{DEFAULT | :=} espressione];
VARIABLE
VEDERE ANCHE PRINT.
SINTASSI
DESCRIZIONE VARIABLE dichiara una bind variable cui si può fare riferimento in PL/SQL. A
ogni variabile viene assegnato un nome e un tipo (NUMBER o CHAR). Per le variabili di tipo
CHAR è possibile specificare una lunghezza massima (n).
ESEMPI
Nell’esempio seguente, viene creata una variabile di nome bal il cui valore viene impostato al
risultato di una funzione.
variable bal NUMBER
begin
:bal := CONTROLLO_SALDO('DORAH TALBOT');
end;
GUIDA DI RIFERIMENTO ALFABETICA 1307
VARIANCE
VEDERE ANCHE ACCEPT, COMPUTE, DEFINE, FUNZIONI DI GRUPPO, PARAMETERS,
STDDEV, VAR_POP, VAR_SAMP, Capitolo 9.
SINTASSI
VARRAY
VARRAY è la clausola del comando CREATE TYPE che indica al database il limite di voci dell’array
variabile. Per esempi dettagliati riguardanti gli array variabili, si rimanda al Capitolo 31. Per
informazioni di carattere sintattico, si consulti CREATE TYPE.
VERIFY (SQL*PLUS)
Vedere SET.
VERSIONE DI REVISIONE
La versione di revisione è il secondo numero nella numerazione delle versioni del software
Oracle. Per esempio, in Oracle versione 9.0.1, la versione di revisione è 0.
VINCOLO DI INTEGRITÀ
Un vincolo di integrità è una regola che limita l’intervallo di valori consentiti per una colonna.
Viene applicato su una colonna quando si crea la tabella. Per la sintassi, si rimanda alla voce
VINCOLI di questo capitolo.
Se non si assegna un nome al vincolo, Oracle assegnerà un nome scritto nella forma SYS_Cn,
in cui n è un valore intero. Solitamente, i nomi assegnati da Oracle cambiano durante le impor-
tazioni, cosa che non accade con i nomi assegnati dall’utente.
NULL permette la presenza di valori NULL. NOT NULL specifica che ogni riga deve contene-
re su questa colonna un valore non nullo.
UNIQUE impone che i valori della colonna siano unici. Una tabella può possedere solo un
vincolo di tipo PRIMARY KEY. Se una colonna è UNIQUE non può essere dichiarata come
PRIMARY KEY (dato che anche PRIMARY KEY impone l’univocità). Un indice impone il
vincolo unico o di chiave primaria, mentre la clausola USING INDEX con le sue opzioni speci-
fica le caratteristiche di memorizzazione di questo indice. Per ulteriori informazioni sulle opzio-
ni, si consulti CREATE INDEX.
REFERENCES identifica la colonna corrente come chiave esterna da [utente.]tabella [(co-
lonna)]. Se si omette colonna, Oracle suppone che il nome di utente.tabella sia lo stesso di
quello della tabella corrente. Si osservi che quando REFERENCES viene utilizzato in un
vincolo_tabella (esaminato tra breve), questo deve essere preceduto da FOREIGN KEY. In que-
sto caso, non è stato necessario utilizzarlo dato che si fa riferimento a una sola colonna;
vincolo_tabella può indicare diverse colonne FOREIGN KEY. ON DELETE CASCADE fa sì che
Oracle gestisca automaticamente l’integrità referenziale rimuovendo le righe contenenti chiavi
1308 CAPITOLO 48
esterne nelle tabelle dipendenti quando si rimuove la riga delle chiavi primarie nella tabella
principale.
CHECK assicura che il valore della colonna superi una condizione come quella che segue:
condizione può essere qualsiasi espressione valida (che valga TRUE o FALSE). Può conte-
nere funzioni, colonne appartenenti a tabelle e letterali.
La clausola EXCEPTIONS INTO specifica una tabella in cui Oracle inserisce le informazio-
ni relative alle righe che violano un determinato vincolo di integrità. Questa tabella deve essere
locale.
L’opzione DISABLE consente di disattivare il vincolo di integrità già all’atto della creazio-
ne. Quando il vincolo è disattivato, Oracle non lo impone automaticamente. In seguito sarà
possibile attivare il vincolo con la clausola ENABLE di ALTER TABLE.
Si possono creare vincoli anche a livello di tabella. I vincoli di tabella sono identici a quelli
di colonna, tranne per il fatto che un vincolo unico può fare riferimento a più colonne, per
esempio nella dichiarazione di un gruppo di tre colonne come chiave primaria o esterna.
VINCOLO DI TABELLA
Un vincolo di tabella è un vincolo di integrità che si applica a più colonne della stessa tabella.
Vedere VINCOLO DI INTEGRITÀ.
VIRTUALE, COLONNA
Una colonna virtuale è una colonna nel risultato di una query i cui valori vengono calcolati a
partire da quelli di altre colonne.
VISITA DI UN ALBERO
La visita di un albero è l’atto di elaborare uno per uno ogni nodo di un albero. Vedere CONNECT BY.
VISTA
Una vista (un oggetto di database) è una rappresentazione logica di una tabella. Deriva da una
tabella ma non dispone di un proprio spazio di memoria. Spesso può essere utilizzata allo stesso
modo delle tabelle. Vedere CREATE VIEW e il Capitolo 17.
VISTA MATERIALIZZATA
Le viste materializzate possono essere utilizzate per aggregare anticipatamente i dati e migliora-
re le prestazioni delle query. Quando si crea una vista materializzata, Oracle crea una tabella
fisica per contenere i dati che solitamente verrebbero letti tramite una vista. Quando si crea una
vista materializzata, si dovrà specificare la query base della vista, nonché un programma per gli
aggiornamenti dei suoi dati. Quindi si potrà indicizzare la vista materializzata per migliorare le
prestazioni delle query eseguite su di essa. Di conseguenza, si potranno fornire i dati agli utenti
GUIDA DI RIFERIMENTO ALFABETICA 1309
nel formato richiesto, indicizzati in modo corretto. Vedere CREATE MATERIALIZED VIEW e
il Capitolo 23.
VISTA OGGETTO
Una vista oggetto sovrappone tipi di dati astratti a tabelle relazionali già esistente. Le viste
oggetto consentono di accedere ai dati di una tabella relazionale tramite i normali comandi SQL
oppure tramite le strutture del suo tipo di dati astratto. Le viste oggetto mettono a disposizione
un ponte tecnologico tra i database relazionali e quelli relazionali ad oggetti. Per esempi relativi
alle viste oggetto, si rimanda ai Capitoli 30 e 33.
VSIZE
VEDERE ANCHE CARATTERI, FUNZIONI; LENGTH; NUMERI, FUNZIONI; Capitolo 9.
SINTASSI
VSIZE(valore)
VSIZE(12.345) = 4
WHENEVER
VEDERE ANCHE EXECUTE, FETCH.
SINTASSI
DESCRIZIONE WHENEVER non è un’istruzione SQL eseguibile, bensì una direttiva del
processore del linguaggio Oracle che di fatto aggiunge una condizione del tipo “IF condizione
THEN GOTO etichetta” al termine di ogni istruzione SQL che segue. Mentre viene eseguita, i
1310 CAPITOLO 48
risultati di ogni istruzione SQL vengono controllati per vedere se soddisfano la condizione. In
caso affermativo, il programma passa a etichetta.
WHENEVER può essere utilizzato con CONTINUE o con un’etichetta diversa per ciascuna
delle tre possibili condizioni. Ciascuna di queste si propagherà a tutte le successive istruzioni
SQL. Un nuovo comando WHENEVER con una di queste condizioni rimpiazza completamente
il suo predecessore per tutte le istruzioni SQL successive.
La condizione NOT FOUND viene sollevata quando SQLCODE vale 100; questo significa,
per esempio, che un FETCH non restituisce nessuna riga (ciò include anche le subquery delle
istruzioni insert).
SQLERROR è vera quando SQLCODE è minore di 0. Si tratta generalmente di errori
irreversibili che richiedono complesse routine di gestione.
SQLWARNING è vera quando si verifica un errore non irreversibile. In questa categoria
rientrano il troncamento di stringhe di caratteri caricate all’interno di variabili host, una select
list di colonne che non corrisponde all’elenco INTO delle variabili host, l’esecuzione di istruzio-
ni di cancellazione o aggiornamento prive di clausole where e così via.
In genere, la diramazione iniziale, la continuazione, l’interruzione o l’esecuzione di routine
vengono impostate all’inizio del programma, prima di qualsiasi istruzione SQL eseguibile. Co-
munque, all’interno di particolari blocchi logici del programma, esse possono essere sovrascritte
in base alle necessità locali. Si noti che WHENEVER non sa nulla riguardo le regole di ambito
dei linguaggi host, le chiamate o la diramazione. Dal momento in cui si impone un comando
WHENEVER, le sue regole rimangono attive finché un altro WHENEVER (con la stessa condi-
zione) non lo sostituisce. D’altra parte, il programma deve obbedire alle regole di ambito del
linguaggio per quanto riguarda GOTO e l’etichetta.
L’opzione STOP interrompe l’esecuzione del programma; l’opzione DO chiama una routine
di qualche tipo tra quelle del linguaggio host. La sintassi di questa routine dipende dal linguag-
gio host impiegato. DO BREAK interrompe un ciclo; DO CONTINUE esegue un’istruzione con-
tinua da un ciclo quando la condizione è soddisfatta.
Infine, all’interno di una routine di gestione degli errori, specie in una che può contenere
istruzioni SQL, WHENEVER SQLERROR dovrebbe contenere CONTINUE o STOP oppure do-
vrebbe chiamare una routine di uscita in modo da evitare cicli infiniti nella stessa routine di
gestione degli errori.
WHENEVER OSERROR
{EXIT [SUCCESS|FAILURE|n|variabile|:BindVariable] [COMMIT|ROLLBACK]
|CONTINUE [COMMIT|ROLLBACK|NONE]}
SINTASSI
WHENEVER SQLERROR
{EXIT [SUCCESS|FAILURE|WARNING|n|variabile|:BindVariable]
[COMMIT|ROLLBACK]|CONTINUE [COMMIT|ROLLBACK|NONE]}
WHERE
VEDERE ANCHE DELETE, OPERATORI LOGICI, PRECEDENZE, SELECT, OPERATORI
SINTATTICI, UPDATE.
SINTASSI
DESCRIZIONE WHERE definisce le condizioni logiche che vincolano la selezione delle righe
da restituire, cancellare o aggiornare.
Una condizione può essere definita in uno dei modi seguenti:
■ Un confronto tra espressioni (=, >, != e così via).
■ Un confronto tra un’espressione e una query.
■ Un confronto tra un elenco di espressioni e un elenco di espressioni derivanti da una query.
1312 CAPITOLO 48
■ Un confronto tra un’espressione e alcuni o tutti (ANY o ALL) i membri di un elenco o tra
un’espressione e i valori restituiti da una query.
■ Un controllo che un’espressione sia o non sia (IN o NOT IN) in un elenco o tra i risultati di
una query.
■ Una verifica che qualcosa sia contenuta o meno (BETWEEN o NOT BETWEEN) tra due
valori.
■ Una verifica che un’espressione sia NULL o meno (IS NULL o IS NOT NULL).
■ Una verifica di esistenza o meno (EXISTS o NOT EXISTS) dei risultati di una query.
■ Una combinazione delle condizioni precedenti correlate mediante gli operatori logici AND e OR.
ESEMPI
WHILE (PL/SQL)
Vedere LOOP, Capitolo 27.
WIDTH_BUCKET
VEDERE ANCHE NTILE.
SINTASSI
WRAP (SQL*PLUS)
Vedere SET.
GUIDA DI RIFERIMENTO ALFABETICA 1313
WRAPPING
Wrapping significa spezzare la parte finale di un’intestazione, di un titolo o di una colonna
portandola su un’altra linea quando viene superato il margine di visualizzazione. È l’effetto
opposto di TRUNCATE. Vedere COLUMN.
XML
XML (eXtensible Markup Language) è una sintassi standardizzata per descrivere dati gerarchi-
ci. XML fornisce un formato universale per documenti e dati strutturati. La sua sintassi basata su
tag gli consente di gestire con molta flessibilità dati complessi. HTML comunica a un browser
Web come presentare i dati, mentre XML indica alle applicazioni il significato dei dati. Per degli
esempi, si rimanda al Capitolo 41.
XMLAGG
VEDERE ANCHE SYS_XMLAGG.
SINTASSI
XMLCOLATTVAL
VEDERE ANCHE Capitolo 47.
SINTASSI
XMLCONCAT
VEDERE ANCHE XMLSEQUENCE.
SINTASSI
DESCRIZIONE XMLCONCAT prende come input una serie di istanze XMLType, concatena la
serie di elementi per ciascuna riga e restituisce la serie concatenata. XMLCONCAT è l’inverso di
XMLSEQUENCE.
XMLELEMENT
VEDERE ANCHE SYS_XMLGEN.
SINTASSI
XMLElement::=
XML_attributes_clause::=
AS c_alias
XMLATTRIBUTES ( value_expr )
XMLFOREST
VEDERE ANCHE XMLCONCAT.
SINTASSI
DESCRIZIONE XMLFOREST converte ciascuno dei suoi parametri argomento in XML, poi
restituisce un frammento XML che è la concatenazione di questi argomenti convertiti.
XMLSEQUENCE
VEDERE ANCHE XMLCONCAT.
SINTASSI
■ La prima forma prende come input un’istanza XMLType e restituisce un array variabile dei
nodi superiori in XMLType.
■ La seconda forma prende come input un’istanza REFCURSOR, con l’istanza opzionale
dell’oggetto XMLFORMAT, e restituisce come tipo XMLSEQUENCE un documento XML per
ciascuna riga del cursore.
XMLTRANSFORM
VEDERE ANCHE Capitolo 47.
SINTASSI
XMLType
XMLType è un tipo di dati disponibile a partire da Oracle9i che serve per memorizzare ed ese-
guire query sui dati XML nel database. In qualità di tipo, XMLType dispone di funzioni membro
per accedere, estrarre ed eseguire query sui dati XML con una classe di operazioni note con il
nome di espressioni XPath. I package SYS_XMLGEN, SYS_XMLAGG e DBMS_XMLGEN
creano valori XMLType a partire da dati relazionali a oggetti già esistenti. Quando si stabilisce
che una colonna utilizzerà il tipo di dati XMLType, Oracle memorizza internamente i dati in un
tipo di dati CLOB.
Il listato seguente mostra la creazione di una tabella che utilizza il tipo di dati XMLType:
datatype:
Per ulteriori dettagli su XMLType e i relativi metodi correlati, si rimanda al Capitolo 41.
○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○
Indice analitico
J stored procedure, N
chiamata diretta, 658–659
loadjava, 656
Java, 8 National Language Support, 144
LOB
alle classi, 655–658 NCHR, 1176
aggiornamento dei valori, 589
caricamento di classi, 655 NEAR, 1176
BLOB, 999
classi, 638–642 NEW_TIME, funzione, 189
cancellazione, 607
comandi eseguibili, 629–637 NEXT_DAY, funzione, 189
CLOB, 1013
dichiarazioni, 628–629 NLS_CHARSET_DECL_LEN,
dizionario dati, 717–718
e PL/SQL, 627–628 1177
funzione SUBSTR, 595
e XSU, 880–881 NLS_CHARSET_ID, 1177
funzioni di stringa, 589–590
gestione delle eccezioni, NLS_CHARSET_NAME, 1177
inizializzazione dei valori,
636–637 NLS_INITCAP, 1177
587–588
loadjava, 656 NLS_LOWER, 1178
inserimento con subquery,
logica condizionale, 631–634 NLS_UPPER, 1178
588–589
parole riservate, 637 NLSSORT, 1178
NCLOB, 1176
stored procedure, 653 NOAUDIT, 1178–1180
parametri di memorizzazione,
strumenti (OracleAS 10g), nodo
585–586
833–834 foglia, 256
tipi di dati disponibili,
tipi di dati, 629 principale, 256
583–584
JDBC, 8 NOLOGGING, 1180
locale, 1099
classi, 645–648 nomi
LOCALTIMESTAMP, 1169
e utenti Windows, 644 di servizio, 408
LOCK TABLE, 1169–1170
manipolazione dei dati, sinonimi, 67
LOG, funzione, 169–170
648–651 non-equi-join, 1182
logica e valore, 81–89
verifica della connessione, normalizzazione, 45
login.sql, 116
644–648 modello logico, 49
LOWER, funzione, 132–133,
join NOT, 1182
1171
colonne di, 1015 NOT EXISTS, 243–244, 1182
LPAD, funzione, 126–127, 1171
comando, 1163 notazione esadecimale, 1127
LTRIM, funzione, 127–128, 1171
di più di due tabelle, 777 NTILE, 1182–1183
equi-join, 1127 NULL, 1182–1183
FULL OUTER JOIN, 1144 valore, 85
interno, 1163 M NULLIF, 1183
naturale, 1164 NUMTODSINTERVAL, 1186
non-equi-join, 1182 maiuscole e minuscole, 55–56 NUMTODSINTERVAL,
outer join, 238 MAKE_REF, 1172 funzione, 189
MapViewer Toolkit, 821 NUMTOYMINTERVAL, 1186
marcatore di posizione, 84 NUMTOYMINTERVAL,
L MAX, funzione, 1172 funzione, 189
merge, 278–281 NUMWIDTH, 1186
MIN, funzione, 1174 NVL, funzione, 166–167,
LAG, 1164
MINUS 1186–1187
LAST, 1164
clausola, 245 NVL2, 1187
LAST_DAY, funzione, 189, 1165
funzione, 1174
LAST_VALUE, 1165
MOD, funzione, 168–169,
LEAD, 1165
1174–1175 O
LEAST, funzione, 180,
modello entità-relazioni, 1127
1165–1166
MONTHS_BETWEEN, 1175
LENGTH, funzione, 133, 1166 OCRCONFIG, 671
MONTHS_BETWEEN, funzione,
LEVEL, 1166 OID, 1187
189
LGWR, 1166 on commit preserve rows, 251
MOUNT, 839
LIKE, 1167 OPEN, 1187–1188
LIKE, operatore, 84 OPEN CURSOR, 1188
LIST, 1167 operatori
LN, funzione, 169–170, 1168 insiemistici, 1189
loadjava, 656, 1168 LIKE, 84
1324 INDICE ANALITICO
Finito di stampare
nel mese di febbraio 2005