Insieme di istruzioni per la modifica dei dati contenuti nei database. Per gli esempi verranno utilizzate le seguenti tabelle.
Per gli esempi verranno utilizzate le seguenti tabelle.
TB_CLIENTI |
CODICE |
NOME |
COGNOME |
TELEFONO |
1 |
MARIO |
ROSSI |
06.333444 |
2 |
LUIGI |
VERDI |
06.333555 |
3 |
FABIO |
BIANCHI |
- |
TB_SEDE |
CODICE |
CITTA |
INDIRIZZO |
PROVINCIA |
1 |
ROMA |
VIA FLAMINIA, 24 |
RM |
2 |
ROMA |
VIA LOMBARDI, 2 |
RM |
3 |
TORINO |
PZZ. AUGUSTO, 55 |
TO |
TB_FATTURA |
CODICE |
NUM_FATTURA |
COSTO |
SCONTO |
1 |
1 |
1000 |
5 |
2 |
2 |
100000 |
10 |
3 |
3 |
100000 |
10 |
2 |
4 |
50000 |
5 |
DELETE
Permette la cancellazioni di una o più righe di una tabella.
sintassi del comando
DELETE FROM nome_tabella
WHERE condizione di ricerca
Esempio : immaginiamo di voler cancellare il cliente con CODICE = 1
DELETE FROM tb_cliente
WHERE CODICE = 1
Nel caso in cui non venga specificata la Where verranno cancellate tutte le righe della tabella.
Se volessimo cancellare tutti i clienti che hanno la PROVINCIA = ‘RM’ si scriverà :
DELETE FROM tb_cliente
WHERE CODICE IN (SELECT CODICE FROM tb_sede WHERE PROVINCIA = ‘RM’)
L’uso delle sub-query risulta essere valido anche per l’istruzione di UPDATE.
Se dovessimo cancellare le righe lette da un cursore (vedi DECLARE) allora la WHERE sarà scritta nel seguente modo :
DELETE FROM nome_tabella
WHERE CURRENT OF nome cursore
Per poter utilizzare questo tipo di istruzione il cursore dovrà rispettare i seguenti punti :
- la clausola FROM deve far riferimento ad una sola tabella
- non deve essere presente una DISTINCT
- non deve essere presente una ORDER BY
- non deve essere presente una GROUP BY, HAVING
- non devono essere utilizzate colonne calcolate
- non devono essere utilizzate sottointerrogazioni
INSERT
permette l’inserimento di una o più righe in una tabella
sintassi del comando
INSERT INTO nome_tabella [(nomi_colonne)]
VALUES (:valori-colonne)
I nomi delle colonne sono opzionali e vanno elencati solamente se si vogliono inserire alcuni campi, gli altri verranno valorizzati dal DB2 con i valori di defaut (NULL o CURRENT TIME, ….) precedentemente spiegati.
Esempio : immaginiamo di voler inserire tutti i clienti di un’altra tabella
INSERT INTO tb_clienti
SELECT * FROM tb_clienti_2
Le colonne della prima e della seconda tabella dovranno essere uguali.
Esempio : nel caso in cui volessimo specificare i campi da inserire
INSERT INTO tb_clienti (nome campo 1, nome campo 2, ..., nome campo n )
SELECT nome campo 1, nome campo 2, ..., nome campo n FROM tb_clienti_2
Esempio : immaginiamo di voler inserire il cliente MARIO ROSSI
INSERT INTO tb_clienti (CODICE, NOME, COGNOME, TELEFONO)
VALUES (1,’MARIO’,’ROSSI’,’06/333444’)
Nel caso di FABIO BIANCHI avremo :
INSERT INTO tb_clienti (CODICE, NOME, COGNOME)
VALUES (3,’FABIO’,’BIANCHI’)
Come si può notare non e stata inserita la colonna TELEFONO in quanto questa può accogliere il valore NULL.
SELECT
permette la visualizzazione di uno o più righe da una o più tabelle
sintassi del comando
SELECT campi_tabella INTO :variabili :indicator
FROM nome_tabella
WHERE condizioni-di-ricerca (facoltativo)
ORDER BY {column-name | integer} (facoltativo) {ASC | DESC}[,...]}
Esempio : immaginiamo di vole selezionare tutti i clienti
SELECT * FROM tb_clienti
Il risultato sarà la visualizzazione di tutta la tabella tb_clienti. L’opzione ‘*’ dopo il comando SELECT sta a significare tutte le colonne della tabella.
Esempio : ora vogliamo elencare tutte le colonne della tabella ma con un prociso ordine
SELECT COGNOME, NOME, TELEFONO, CODICE
FROM tb_clienti
Atrimenti potremmo selezionare solamente le colonne desiderate
SELECT COGNOME, NOME
FROM tb_clienti
Includendo il modificatore WHERE (operatore relazionale di selezione) possiamo andare a scegliere i dati da visualizzare
SELECT COGNOME, NOME
FROM tb_clienti
WHERE CODICE = 1
I dati visualizzati saranno quindi relativi solamente al cliente MARIO ROSSI.
Le condizioni di selezioni utilizzabili nella WHERE saranno le seguenti :
=, <>, <, >, =<, >=.
Per specificare un intervallo di valori nella codizione WHERE si possono usare le parole chiave BETWEEN e IN.
SELECT COGNOME, NOME
FROM tb_clienti
WHERE CODICE IN (1,3)
SELECT COGNOME, NOME
FROM tb_clienti
WHERE CODICE BETWEEN 1 AND 3
Per ricercare invece una particolare sequenza di caratteri si userà l’opzione LIKE.
SELECT COGNOME, NOME
FROM tb_clienti
WHERE NOME LIKE '%IO%'
% indica un numero qualsiasi di caratteri
_ indica un solo carattere
La clausola ESCAPE nell’opzione LIKE starà a significare il fatto di ignorare, per esempio il carattere jolly ‘_’ associato al carattere che segue ’\’.
Per ricercare invece una particolare sequenza di caratteri si userà l’opzione LIKE.
SELECT COGNOME, NOME
FROM tb_clienti
WHERE NOME LIKE ‘\_IO%’ ESCAPE ‘\’
Per eliminare le righe duplicate useremo la parola chiave DISTINCT.
Supponiamo di voler sapere la lista delle citta nella tabella TB_SEDE, sensa usare la DISTINCT avremo 2 volte la città ROMA invece per visualizzarla una sola volta scriveremo :
SELECT DISTINCT(CITTA)
FROM tb_sede
Le selezioni si possono basare anche su selezioni multiple tramite l’utilizzo degli operatori booleani AND e OR.
Immaginiamo di voler visualizzare tutti i clienti che fanno di cognome ROSSI o di nome FABIO.
SELECT * FROM tb_clienti
WHERE COGNOME = ‘ROSSI’ OR NOME = ‘FABIO’
Se invece volessimo visualizzare tutti i clienti che hanno come telefono il valore NULL.
SELECT * FROM tb_clienti
WHERE TELEFONO IS NULL
Per visualizzare un valore di default al posto di un valore NULL utilizzeremo la funzione VALUE.
SELECT NOME, COGNOME, VALUE(TELEFONO, ‘NON PRESENTE’)
FROM tb_clienti
WHERE TELEFONO IS NULL
Per specificare l’opposto di una qualsiasi condizione si aggiungerà la parola chiave NOT.
SELECT * FROM tb_clienti
WHERE NOT COGNOME = ‘ROSSI’
La parola chiave NOT può essere utilizzata anche con IN (NOT IN), BETWEEN (NOT BETWEEN), LIKE (NOT LIKE) e IS NULL(IS NOT NULL).
Oltre a visualizzare le colonne appartenenti ad una tabella si possono anche creare delle colonne in base a dei calcoli matematici.
Per esempio per sapere qual è la cifra scontata pagata dai clienti scriverò :
SELECT CODICE, COSTO – ((COSTO * SCONTO) / 100)
FROM tb_fattura
Per avere una lista dei clienti ordinata per esempio per cognome in modo crescente e per nome in modo decrescente si userà il modificatore ORDER BY
SELECT * FROM tb_clienti
WHERE NOT COGNOME = ‘GIALLI’
ORDER BY COGNOME, 2 DESC
Fino ad ora abbiamo interrogato singole tabelle ora invece vedremo cosa vuol dire applicare l’opzione relazionale di giunzione(join) su più tabelle.
Facciamo finta di voler conoscere il NOME, il COGNOME e l’INIRIZZO di ogni cliente.
SELECT tb_clienti.CODICE, NOME, COGNOME, INDIRIZZO
FROM tb_clienti , tb_sede
WHERE tb_clienti.CODICE = tb_sede.CODICE
oppure
SELECT A.CODICE, A.NOME, A.COGNOME, B.INDIRIZZO
FROM tb_clienti A, tb_sede B
WHERE A.CODICE = B.CODICE
L’SQL mette a disposizione delle funzioni per eseguire operzioni con il comando SELECT e sono :
- SUM(nome_colonna) - Calcola il totale
- MIN(nome_colonna) - Calcola il valore minimo
- MAX(nome_colonna) - Calcola il valore massimo
- AVG(nome_colonna) - Calcola la media dei valori
- COUNT(*) - Conta il numero delle righe
- COUNT(DISTINCT nome_colonna) - Conta i valori unici delle righe
Per indicare la modalità di raggruppamento delle righe si utilizza il modificatore GROUP BY. Per esempio per sapere, nella tabella fattura, il costo totare per ogni codice si scriverà :
SELECT CODICE, SUM(COSTO)
FROM tb_fattura
GROUP BY CODICE
ORDER BY COSTO
Per aggiungere una espressione condizionale invece della WHERE si farà uso del modificatore HAVING (in quanto si riferisce ad un gruppo di dati).
SELECT CODICE, SUM(COSTO)
FROM tb_fattura
GROUP BY CODICE
HAVING SUM(COSTO) > 10000
ORDER BY COSTO
Per sapere se nella tabella esistono record duplicati con lo stesso NOME e COGNOME:
SELECT COUNT(NOME), NOME, COGNOME
FROM tb_clienti
GROUP BY NOME, COGNOME
HAVING COUNT(NOME) > 1
In un comando SELECT è anche possibile annidare le istruzioni si parla quindi di sottointerrogazioni.
Se volessimo conoscere, per esempio, i clienti con il COSTO in fattura più alto:
SELECT A.NOME, A.COGNOME, B.COSTO
FROM tb_clienti A, tb_fattura B
WHERE A.CODICE = B.CODICE
AND B.COSTO = (SELECT MAX(C.COSTO) FROM tb_fattura C)
Se la sottointerrogazione producesse più di una riga come risultato, allora bisognerà sostituire il segno ‘=’ con ‘IN’ altrimenti :
SELECT A.NOME, A.COGNOME, B.COSTO
FROM tb_clienti A, tb_fattura B
WHERE A.CODICE = B.CODICE
AND B.COSTO IN (SELECT MAX(C.COSTO) FROM tb_fattura C)
Le condizioni EXISTS e NOT EXISTS risultano utili per estrarre i dati di due tabelle messe in relazione tra di loro quando la relazione viene rispettata e quando non lo è.
SELECT * FROM TB_CLIENTI
WHERE EXISTS (SELECT * FROM TB_SEDE WHERE TB_CLIENTI.CODICE = TB_SEDE.CODICE)
oppure
SELECT * FROM TB_CLIENTI
WHERE NOT EXISTS (SELECT * FROM TB_SEDE WHERE TB_CLIENTI.CODICE = TB_SEDE.CODICE)
UPDATE
permette l’aggiornamento di una o più righe in una tabella
sintassi del comando
UPDATE nome_tabella
SET colonna = valore o :variabile
WHERE condizione di ricerca
Esempio : immaginiamo di voler modificare la CITTA con il valore ‘MILANO’ a tutti i clienti che hanno ‘ROMA’
UPDATE tb_sede
SET CITTA = ‘MILANO’, PROVINCIA = ‘MI’
WHERE CITTA = ‘ROMA’
Nel caso in cui non venga specificata la Where verranno modificate tutte le righe della tabella.
Se dovessimo invece modificare le righe lette da un cursore (vedi DECLARE) allora la WHERE sarà scritta nel seguente modo :
UPDATE nome_tabella
SET colonna = valore o :variabile
WHERE CURRENT OF nome cursore
Per poter utilizzare questo tipo di istruzione il cursore dovrà rispettare i seguenti punti :
- la clausola FROM deve far riferimento ad una sola tabella
- non deve essere presente una DISTINCT
- non deve essere presente una ORDER BY
- non deve essere presente una GROUP BY, HAVING
- non devono essere utilizzate colonne calcolate
- non devono essere utilizzate sottointerrogazioni
COMMIT
Questo comando da al sistema relazionale la conferma che l’unita di lavoro è andata a buon fine. L’unità di lavoro inizia con il primo comando SQL e finisce con un comando di Commit o Rollback. Le modifiche, dopo il comando di commit, saranno quindi disponibili a tutti gli a ltri utenti del sistema.
Una delle caratteristiche del comando COMMIT è che questo chiude tutti i cursori SQL ancora aperti.
In ambiente CICS non è possibile usare questo comando in quanto è il CICS stesso che si incarica di inviare il comando COMMIT in caso di unità di lavoro andata a buon fine. Esiste però un comando CICS alternativo che invia una COMMIT :
EXEC CICS SYNCPOINT END-EXEC
ROLLBACK
Questo comando invece, al contrario del comando di COMMIT, richiede al sistema l’annullamento di tutte le operazioni svolte durante l’unità di lavoro ritornando quindi alla situazione iniziale (dopo l’ultima commit).
Anche questo comando, come la COMMIT, provoca la chiusura di tutti i cursori SQL ancora aperti.
DECLARE
I programmi cobol, come altri linguaggi, possono trattare una riga dati alla volta. Ecco nascere l’esigenza quindi di gestire i dati prodotti da una istruzione SQL attraverso quello che viene chiamato CURSORE.
Quest’ultimo non è niente altro che un puntatore che si scorre sequenzialmente tutte le righe di una tabella dei risultati.
L’istruzione DECLARE non fa altro che associare un nome simbolico ad una interrogazione.
sintassi del comando
DECLARE nome_cursore CURSOR FOR interrogazione
OPEN
L’istruzione OPEN apre un cursore precedentemente dichiarato preparando la tabella dei risultati e si posiziona quindi prima della prima riga della tabella.
sintassi del comando
OPEN nome_cursore
FETCH
L’istruzione FETCH sposta il cursore sulla riga successiva della tabella dei risultati e muove i dati nelle variabili ospiti.
sintassi del comando
FETCH nome_cursore INTO :variabili :indicator
CLOSE
L’istruzione CLOSE cliude il cursore ed informa il sistema che non utilizzerà più la tabella dei risultati.
sintassi del comando
CLOSE nome_cursore