A. Veneziani - Primi elementi di Linguaggio SQL
←
→
Trascrizione del contenuto della pagina
Se il tuo browser non visualizza correttamente la pagina, ti preghiamo di leggere il contenuto della pagina quaggiù
A. Veneziani – Primi elementi di Linguaggio SQL SQL SQL (Structured Query Language) E’ un linguaggio tipico dei DBMS (DataBase Managment System) di tipo relazionale, che sono stati fino ad ora una parte prevalente dei sistemi software per la gestione dei dati, talora abbreviati come RDBMS (Relational DataBase Managment System). Il linguaggio è stato più volte standardizzato per cui esso ha mantenuto una forte similitudine su tutti i DBMS, a vantaggio della portabilità di script e query. E’ un linguaggio che può essere usato in due modalità: Stand-alone – SQL viene utilizzato da solo, ossia dando direttamente comandi nel linguaggio stesso o utilizzando script che contengano serie di comandi che poi vengono eseguiti in sequenza. Embedded – SQL viene utilizzato abbinato ad un qualunque linguaggio di programmazione (C++, Object Pascal, C#, Java, PHP, ASP, ecc.) sia per applicazioni desktop che per applicazioni Web, interpretato o compilato. Il linguaggio di programmazione che ospita SQL controlla il flusso logico principale del programma, e quando necessario invia comandi SQL al DBMS per ricavarne dati o compiere altre operazioni (quali inserimenti, cancellazioni, aggiornamenti ecc.). In tal modo SQL ed il linguaggio che lo “ospita” collaborano per un efficiente interfacciamento della base di dati con la parte di presentazione / gestione degli stessi. In un comune DBMS tutte le operazioni sono effettuabili da console dando esclusivamente comandi SQL. Quindi in pratica si può dire che un DBMS relazionale può essere controllato completamente tramite linguaggio SQL. L’insieme dei comandi SQL, essendo particolarmente vasto e diversificato, può essere suddiviso in varie parti: Query Language – parte del linguaggio che permette l’estrazione selettiva di dati dal DBMS DML – Data Manipulation Language - Parte del linguaggio che permette le operazioni di modifica dei dati, quali cancellazioni, inserimenti, modifica degli stessi DDL – Data Definition Language – Parte del linguaggio che permette di definire ed eventualmente modificare la struttura interna logica di un DB, ossia le tabelle, il numero ed il tipo di campi, i vincoli a cui tali campi devono sottostare, ecc. DCL – Data Control Language – Parte del linguaggio preposta a regolare i permessi di accesso dei vari utenti, e/o creare opportunamente nuove utenze. Vediamo ora i vari comandi utilizzabili in console per effettuare diverse operazioni su un DB: Creazione di un database Il comando SQL per creare la creazione di un nuovo DB è: CREATE DATABASE ; ad esempio CREATE DATABASE prova; Cancellazione di un DB Il comando per eliminare (in modo definitivo un database e tutti i dati che contiene) è: DROP DATABASE ; ad esempio: DROP DATABASE prova; Pagina 1
Messa in uso di un DB Esistendo più DB sotto il controllo del DBMS, è necessario indicare su quale il DBMS debba operare in quel momento. Questo ovviamente non esclude che il DB in uso possa essere poi successivamente cambiato. Tale operazione può essere fatta con: USE ; ad esempio: USE prova; Creazione di tabelle in un DB Si effettua con il noto comando CREATE TABLE. Il comando ha la struttura generale: CREATE TABLE ( , , …. ); Il comando fa parte del DDL – in quanto definisce la struttura del DB. Per i numerosi dettagli sul comando vedi dispense sui vari database implementati. Modifica di una tabella Si effettua con il comando ALTER TABLE. Anche questo comando diverse varianti ed è piuttosto complesso, quindi indicherò qui solo le forme più usate ed elementari del comando stesso. Supponiamo di avere una tabella minima denominata Persone, di una sola colonna: CREATE TABLE Persone ( Id_Persona INT UNSIGNED ); e volerla modificare ed ampliare. Se ad esempio dovessimo rendere chiave primaria proprio il campo appena definito (CF – codice fiscale): ALTER TABLE persone ADD PRIMARY KEY(Id_Persona); e se dovessimo eventualmente togliere la chiave primaria appena definita dalla tabella potremo farlo con il comando: ALTER TABLE persone DROP PRIMARY KEY; (in questo caso non c’è bisogno di specificare il campo da cui eleminare il vincolo, perché esso è già noto al DBMS). Per aggiungere altre colone potremo procedere con degli ulteriori comandi ALTER TABLE: ALTER TABLE persone ADD Nome VARCHAR(40) NOT NULL; e così per la colonna Cognome: ALTER TABLE persone ADD Cognome VARCHAR(40) NOT NULL; Una variante della sintassi permette di effettuare le modifiche in modo cumulato fra loro, senza ripetere il comando, miscelando anche le varie modalità che sono stanzialmente ADD, DROP, MODIFY: ALTER TABLE persone MODIFY Nome VARCHAR(50) NOT NULL, ADD DataNascita DATE NOT NULL; in modo simile è possibile persino aggiungere vincoli di integrità o di integrità referenziale: Pagina 2
ALTER TABLE persone ADD CHECK(DataNascita
Esso può essere applicato ad uno o più campi. Se applicato a più campi Permette però a differenza della chiave primaria (PRIMARY KEY), il valore NULL, e comunque indica un campo vincolato dall’univocità non chiave primaria. Infine si possono considerare i cosiddetti vincoli di integrità referenziale in cui i valori che una chiave esterna può assumere sono legati a quelli della corrispondente chiave primaria, questo per mantenere una coerenza interna del DB, definiti da comandi del tipo: …FOREIGN KEY() REFERENCES ()… Campi AUTO_INCREMENT Molto spesso, quando la chiave primaria di una tabella sia intera, e si desideri che la generazione dei suoi valori sia prodotta automaticamente, è possibile utilizzare un sistema di generazione interna del DBMS della chiave, basato sull’autoincremento del valore precedentemente generato. In definitiva il sistema si basa su un contatore interno (uno per tabella), che ricorda l’ultimo valore intero generato per la chiave primaria e lo incrementa, così da essere certo che nessuna ripetizione possa verificarsi. Per avere una chiave primaria così regolata basta aggiungere la specifica AUTO_INCREMENT alla colonna definita come chiave primaria. Ad es: CREATE TABLE Persone ( Id_Persona INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, …. In tal modo il valore interno alla colonna Id_Persona non dovrà essere indicato, ma verrà generato automaticamente, via via sempre diverso, dal valore 1, a valori sempre più alti con passi unitari di incremento. Cancellazione di una tabella Per cancella una intera tabella basta utilizzare il comando: DROP TABLE ; Attenzione ! La cancellazione di una tabella potrebbe non essere possibile in presenza di dati sottoposti a vincolo di integrità referenziale. Cancellazione dei dati di una tabella Diverso concetto e diverso comando è quello con cui si cancellano i dati da una tabella (lasciando ovviamente invariata la tabella stessa). Per cancellare tutti i dati da una tabella si utilizzerà il comando: DELETE FROM ; (senza alcuna condizione). Se invece si volessero cancellare selettivamente solo alcuni dati della tabella, allora si deve inserire una condizione aggiuntiva: DELETE FROM WHERE ; ove è una condizione di selezione, semplice o composta (ossia combinata da operatori AND OR e NOT presenti anche nel linguaggio SQL. Possibili esempi di condizioni sono: Cognome = ‘Rossi’; DataNascita > ‘1970-01-01’; e simili. Quindi si potrebbe avere una cancellazione con condizione del tipo: DELETE FROM Persone WHERE DataNascita >= ‘1980-01-01’ AND DataNascita
Inserimento dati in una tabella Un altro comando per la manipolazione dei dati nei DB e quindi nelle loro tabelle è quello per l’inserimento dei dati. Per inserire dei dati in una tabella si utilizza il comando: INSERT INTO VALUES(, , …..); in questo caso devono essere indicati i valori di tutti i campi presenti nella tabella. Se un campo ammette il valore NULL, sarà ammesso indicarlo come valore inserito, scrivendolo senza apici o virgolette. Se il primo campo è chiave primaria AUTO_INCREMENT, il valore della relativa colonna, sarà indicato, nel comando INSERT precedente con un NULL: INSERT INTO Persone VALUES(NULL, 'Mario', 'Rossi', '1985-03-24'); ciò indica che il valore della colonna con autoincremento deve rimanere “libero” a seconda di quanto il DBMS lo abbia fissato. Una variante del comando è: INSERT INTO (, , ….) VALUES(, , …..); in tal caso si fissa di assegnare valori solo ad alcune colonne e lasciare altre libere. Le colonne il cui valore non è stato indicato, vengono valorizzate secondo i valori di default. Se non sono stati indicati valori di default specifici per una colonna, esistono valori di default convenzionali, che sono: Tipo Valore di default INT, SMALLINT; TINYINT 0 BIT 0 DATE 0000-00-00 TIME 00:00:00 CHAR(n) “” (stringa nulla) VARCHAR(n) “” (stringa nulla) ENUM(‘v1’,’v2’,’v3’,…) v1 Se la colonna della quale non sono specificati i valori ammette valore NULL, allora essa sarà valorizzata con NULL. Un esempio d’uso della seconda sintassi data la tabella Persone definita come: CREATE TABLE `persone` ( `Id_Persona` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `Nome` VARCHAR(50) NOT NULL, `Cognome` VARCHAR(40) NOT NULL, `DataNascita` DATE NOT NULL, PRIMARY KEY (`Id_Persona`) ) Può essere INSERT INTO Persone(Nome, Cognome) VALUES( 'Mario', 'Rossi'); Aggiornamento dei dati di una tabella L’operazione di modifica dei dati di alcune colonne di alcune tuple di una tabella viene effettuata con l’istruzione SQL: UPDATE SET = , = , … WHERE ; Usualmente la condizione indicata sebbene non obbligatoria, è presente, perché altrimenti il valore inserito viene esteso a tutte le tuple della tabella (cosa che di solito non si desidera accada). Pagina 5
Ad esempio per cambiare il nome della persona di id 1 a ‘Paolo’ effettuerò: UPDATE Persone SET Nome = 'Paolo' WHERE Id_Persona = 1; Operazioni di Query Query semplici In SQL si possono effettuare semplici operazioni di estrazione di dati. Tipicamente la forma più semplice dell’istruzione SELECT ha la forma: SELECT FROM WHERE ; Inizialmente consideriamo estrazioni da una sola tabella. Le operazioni più comuni sono quelle di: Proiezione – Ossia includere nel risultato della query solo i dati di alcune colonne desiderate ed escludere altri dati presenti nei risultati ma non di interesse. Ad es: SELECT Nome, Cognome FROM Persone Se si ritiene necessario visualizzare tutte le colonne rese disponibili dalla operazione di selezione allora si utilizzerà la dicitura *. Ad esempio: SELECT * FROM Persone Renderà disponibili tutte le colonne presenti nella tabella Persone. Selezione - Alla operazione si proiezione (recuperiamo solo i dati dei campi Nome e Cognome) si potrà combinare quella di selezione, ossia filtrare tuple che soddifino le condizioni poste: SELECT Nome, Cognome FROM Persone WHERE DataNascita '0000-00-00'; (in questo caso la ricerca delle persone con data di nascita valida). I due tipi di operazioni possono essere svolte singolarmente od in modo combinato. Come sempre la condizione potrà essere composita, vale a dire: SELECT Nome, Cognome FROM Persone WHERE Id_Persona > 3 AND Id_Persona < 6; In alcuni casi queste query potrebbero anche non rendere alcuna tupla, ossia l’insieme delle tuple che sottostanno alla condizione posta potrebbe essere vuoto. Prodotto cartesiano Si indica come prodotto cartesiano tra due insiemi, la combinazione di tutti gli elementi del primo insieme con tutti quelli del secondo insieme. Consideriamo due tabelle in associazione 1 a N tra Persone ed il /i loro cellulari personali. Il prodotto cartesiano viene considerato in SQL soprattutto per il fatto che nelle query viene assai spesso utilizzato un suo sottoinsieme derivante dall’operazione detta di inner join (o join naturale). Il prodotto cartesiano di Persone combinate con Cellulari potrà essere effettuato con l’istruzione SQL: SELECT * FROM Persone, Cellulari L’operazione porta ad una combinazione di tutte le tuple di Persone combinate con quelle di Cellulari, indipendentemente dal fatto che le tuple siano o meno associate tramite i valori dei campi Id_persona (chiave primaria / chiave esterna). Pagina 6
mysql> SELECT * FROM Persone; +------------+--------+---------+-------------+ | Id_Persona | Nome | Cognome | DataNascita | +------------+--------+---------+-------------+ | 1 | Paolo | Bianchi | 1950-03-28 | | 2 | Mario | Rossi | 1967-08-22 | | 3 | Gianni | Bianchi | 1985-03-24 | | 6 | Nino | Neri | 1990-04-21 | +------------+--------+---------+-------------+ 4 rows in set (0.00 sec) mysql> SELECT * FROM Cellulari; +------------+----------+----------+------+------------+ | NumCell | Marca | Modello | Tipo | Id_Persona | +------------+----------+----------+------+------------+ | 34729281 | Huawei | P9 Lite | 4G | 1 | | 342928283 | Apple | IPhone 5 | 4G | 3 | | 3459382811 | Samsung | J6 | 4G+ | 1 | | 3847191818 | Motorola | TAC | 4G | 2 | +------------+----------+----------+------+------------+ 4 rows in set (0.00 sec) mysql> SELECT * FROM Persone, Cellulari; +------------+--------+---------+-------------+------------+----------+----------+------+------------+ | Id_Persona | Nome | Cognome | DataNascita | NumCell | Marca | Modello | Tipo | Id_Persona | +------------+--------+---------+-------------+------------+----------+----------+------+------------+ | 1 | Paolo | Bianchi | 1950-03-28 | 34729281 | Huawei | P9 Lite | 4G | 1 | | 2 | Mario | Rossi | 1967-08-22 | 34729281 | Huawei | P9 Lite | 4G | 1 | | 3 | Gianni | Bianchi | 1985-03-24 | 34729281 | Huawei | P9 Lite | 4G | 1 | | 6 | Nino | Neri | 1990-04-21 | 34729281 | Huawei | P9 Lite | 4G | 1 | | 1 | Paolo | Bianchi | 1950-03-28 | 342928283 | Apple | IPhone 5 | 4G | 3 | | 2 | Mario | Rossi | 1967-08-22 | 342928283 | Apple | IPhone 5 | 4G | 3 | | 3 | Gianni | Bianchi | 1985-03-24 | 342928283 | Apple | IPhone 5 | 4G | 3 | | 6 | Nino | Neri | 1990-04-21 | 342928283 | Apple | IPhone 5 | 4G | 3 | | 1 | Paolo | Bianchi | 1950-03-28 | 3459382811 | Samsung | J6 | 4G+ | 1 | | 2 | Mario | Rossi | 1967-08-22 | 3459382811 | Samsung | J6 | 4G+ | 1 | | 3 | Gianni | Bianchi | 1985-03-24 | 3459382811 | Samsung | J6 | 4G+ | 1 | | 6 | Nino | Neri | 1990-04-21 | 3459382811 | Samsung | J6 | 4G+ | 1 | | 1 | Paolo | Bianchi | 1950-03-28 | 3847191818 | Motorola | TAC | 4G | 2 | | 2 | Mario | Rossi | 1967-08-22 | 3847191818 | Motorola | TAC | 4G | 2 | | 3 | Gianni | Bianchi | 1985-03-24 | 3847191818 | Motorola | TAC | 4G | 2 | | 6 | Nino | Neri | 1990-04-21 | 3847191818 | Motorola | TAC | 4G | 2 | +------------+--------+---------+-------------+------------+----------+----------+------+------------+ 16 rows in set (0.00 sec) Inner join L’operazione di inner join tra due insiemi di tuple mette in correlazione solo le tuple coinvolte nelle associazioni e non tutte indistintamente. Per raggiungere questo scopo però spesso si parte da un insieme che coincide con l’insieme pari al prodotto cartesiano, per poi selezionare solo le tuple che sono associate: SELECT * FROM Persone, Cellulari WHERE Persone.Id_Persona = Cellulari.Id_Persona; mysql> SELECT * -> FROM Persone, Cellulari -> WHERE Persone.Id_Persona = Cellulari.Id_Persona; +------------+--------+---------+-------------+------------+----------+----------+------+------------+ | Id_Persona | Nome | Cognome | DataNascita | NumCell | Marca | Modello | Tipo | Id_Persona | +------------+--------+---------+-------------+------------+----------+----------+------+------------+ | 1 | Paolo | Bianchi | 1950-03-28 | 34729281 | Huawei | P9 Lite | 4G | 1 | | 3 | Gianni | Bianchi | 1985-03-24 | 342928283 | Apple | IPhone 5 | 4G | 3 | Pagina 7
| 1 | Paolo | Bianchi | 1950-03-28 | 3459382811 | Samsung | J6 | 4G+ | 1 | | 2 | Mario | Rossi | 1967-08-22 | 3847191818 | Motorola | TAC | 4G | 2 | +------------+--------+---------+-------------+------------+----------+----------+------+------------+ 4 rows in set (0.00 sec) Come si può osservare i record della tabella Persone ora non sono collegati più in modo combinatorio con i record della tabella Cellulari, ma le tuple in relazione sono solo quelle che dovrebbero effettivamente esserlo, ossia quelle delle persone e ad ogni persona associato ognuno dei cellulari di sua proprietà. Quindi questo comando produce e rispecchia effettivamente la correlazione logica dei dati nel DB, e per questo motivo è usato in modo assai frequente in quasi tutte le query. Un altro modo per scrivere lo stesso comando è: SELECT * FROM Persone INNER JOIN Cellulari ON Persone.Id_Persona = Cellulari.Id_Persona; In genere utilizzeremo la prima forma, che si basa appunto su una selezione, rispetto al prodotto cartesiano generico, di tutte le tuple che esprimano effettivamente una relazione sui valori di chiave primaria / esterna (Id_Persona). Ovviamente un inner join può coinvolgere anche una serie di più tabelle se la query da programmare lo richiede. Semplici applicazioni di tale tipo di operazione possono essere dei problemi del tipo: “Individuare tutte le persone che hanno cellulari Huawei” mysql> SELECT Persone.* -> FROM Persone, Cellulari -> WHERE Persone.Id_Persona = Cellulari.Id_Persona AND -> Cellulari.Marca = 'Huawei'; +------------+-------+---------+-------------+ | Id_Persona | Nome | Cognome | DataNascita | +------------+-------+---------+-------------+ | 1 | Paolo | Bianchi | 1950-03-28 | +------------+-------+---------+-------------+ 1 row in set (0.00 sec) “Individuare i cellulari di Mario Rossi” mysql> SELECT Cellulari.* -> FROM Persone, Cellulari -> WHERE Persone.Id_Persona = Cellulari.Id_Persona AND -> Persone.Nome = 'Mario' AND Cognome = 'Rossi'; +------------+----------+---------+------+------------+ | NumCell | Marca | Modello | Tipo | Id_Persona | +------------+----------+---------+------+------------+ | 3847191818 | Motorola | TAC | 4G | 2 | +------------+----------+---------+------+------------+ 1 row in set (0.00 sec) Pagina 8
Puoi anche leggere