A. Veneziani - Primi elementi di Linguaggio SQL

Pagina creata da Maria Fiori
 
CONTINUA A LEGGERE
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