Linguaggio SQL [DB2]

[Lezione 1] - DML (Data Manipulation Language)

08/06/2020


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 



     lezione successiva >