Appunti (tentativo di fare un manuale) su SQL con la spiegazione di cosa si intende con database e tabelle.
Vengono trattate le istruzioni SELECT, INSERT, UPDATE e DELETE.

Terminologia

Definiamo cosa si intende con il termine Database relazionale. Con Database (DB) si intende un insieme di dati memorizzati e correlati logicamente fra loro. A questi dati si può accedere attraverso vari strumenti e in multiutenza (più accessi in contemporanea). Questo tipo di database viene indicato con la sigla RDBMS ovvero Relational Database Management System.

Per meglio organizzare i dati all'interno di un database questi vengono raggruppati in Tabelle. Vediamo un esempio di tabella:
Tabella_1
id Nome Cognome Città COD Telefono
1 Paperino Paolino Paperopoli A1010 1001 34567
2 Paperone De Paperoni Paperopoli A1021 1001 98752
4 Topolino Toponi Topolinia A1030 1002 38988
Come si vede una tabella è composta da colonne e righe, chiamate record, e le loro intersezioni vengono definite campi. I titoli in grassetto sono i nomi dei campi che vengono usati (vedremo dopo come) per farsi ritornare il valore corrispondente all'intersezione della colonna e della riga corrente.

Ogni colonna della tabella può rappresentare un solo tipo di dati. Per tipo di dati intendiamo il valore che potranno contenere. Ovvero ogni colonna potrà contenere, in base a come viene definita, i seguenti valori:
  • valori stringa identificati come CHAR / VARCHAR / STRING, es.: 'Alberto'
  • valori numerici identificati come NUMERIC / FLOAT / MONEY / INTGER, es.: 1 1.2
  • valori data e/o ora identificati come DATETIME, es.: 25-02-2004 22.51.00
  • valori binari (BLOB Binary Large Object) identificati come MEMO / BYNARY / TEXT, es.: immagini o file
questi sono solo alcuni tipi di dato gestiti da SQLServer, altri database possono avere più o meno tipi di dato e/o identificati in modo diverso.

Per accedere ai dati contenuti in un DB viene utilizzato il linguaggio di interrogazione SQL ovvero Structured Query Language (in origine chiamato SEQUEL Structured English Query Language), standardizzato dall'istituto ANSI (American National Standards Institute) nel 1986, 89, 92 (chiamato anche SQL2 o SQL92) e infine nel 1999 (SQL3 o SQL99). La maggior parte dei DB è conforme, solitamente in parte, con lo standard SQL92, anche se ogni produttore introduce delle varianti/aggiunte/personalizzazioni. In ogni caso le istruzioni che vedremo in questo manuale dovrebbero andare bene per tutti i DB.

Linguaggio SQL

Il linguaggio SQL si divide in tre gruppi principali di istruzioni:
  • DDL Data Definition Language ovvero linguaggio di definizione dei dati: usato per la creazione e la definizione della struttura del DB
  • DML Data Manipulation Language ovvero linguaggio di manipolazione dei dati: usato per recuperare/modificare i dati dalle tabelle/oggetti
  • DCL Data Control Language ovvero linguaggio di controllo dei dati: usato gestire le autorizzazioni degli utenti sugli tabelle/oggetti
Non analizzeremo per ora il DDL in quanto quasi tutti i DB mettono a disposizione degli strumenti visuali per la gestione del DB o la creazione/modifica/cancellazione di Tabelle.

Andremo invece ad analizzare il DML, in quanto è (quasi) l'unica via per gestire i dati da un qualsiasi linguaggio di programmazione e soprattutto è uno standard riconosciuto e adottato da tutti i DB.

Data Manipulation Language (DML)

All'interno del DML possiamo fare una macro suddivisione di 4 istruzioni che permettono di fare tutte le operazioni necessarie relative a una o più tabelle. Queste istruzioni sono:
  • SELECT per estrarre dati dalle tabelle
  • INSERT per inserire un record in una tabella
  • UPDATE per modificare uno o più record di una tabella
  • DELETE per cancellare uno o più record da una tabella
Per seguire gli esempi ti consiglio di utilizzare Query Analizer, con cui potrai
creare la Tabella_1 (in fondo all'articolo trovi il codice) e seguire gli esempi riportati.

Vediamo la struttura del comando SELECT

SQL
SELECT <elenco campi separato da virgole>
      FROM <nome della tabella>
      WHERE <condizione di selezione>
      ORDER BY <elenco campi separato da virgola>
Dove tutto l'insieme viene definito comando o istruzione SQL mentre le singole keyword (es. SELECT, FROM, ecc...) vengono definite clausole e gli argomenti tra i simboli maggiore e minore sono definiti modificatori.
Le uniche clausole che sono sempre presenti sono SELECT e FROM, mentre le altre sono opzionali, ma quando presenti devono essere nell'ordine visualizzato.
Il comando SELECT prevede altre clausole che vedremo successivamente.

La forma più semplice di utilizzo è la seguente:
SQL
SELECT *
FROM Tabella_1
Che applicata alla tabella vista prima (Tabella_1) restituisce tutti i campi (l'asterisco indica tutti i campi della tabella) .

Se non servono tutti i campi della tabella, si possono specificare i nome dei campi che si vuole estrarre:
SQL
SELECT [nome], [cognome]
FROM Tabella_1
Restituisce solo le colonne identificate dal nome: 'nome' e 'cognome', ovvero:
Nome Cognome
Paperino Paolino
Paperone De Paperoni
Topolino Toponi
Nel caso non volessi farmi restituire tutti i record della tabella (nel caso precedente 3 record / righe), devo usare la clausola WHERE per selezionare solo i record che interessano.
Facciamo un esempio, supponiamo di volere estrarre i campi nome, cognome e telefono di tutti gli abitanti di 'paperopoli':
SQL
SELECT [nome], [cognome], [telefono]
FROM Tabella_1
WHERE [città] = 'paperopoli'
Nome Cognome Telefono
Paperino Paolino 1001 34567
Paperone De Paperoni 1001 98752
A questo punto è necessario fare alcune precisazioni.
Nella Tabella_1 il nome di città 'Paperopoli' è stato inserito con la prima lettere in maiuscolo, mentre nella clausola WHERE è stato scritto 'paperopoli' con la prima lettera minuscola. Questo perché il DB preso in considerazione (SQL Server) è case-insensitive ovvero non fa differenza tra maiuscole e minuscole (in realtà dipende da come viene installato). Altri DB invece sono case-sensitive, es.: AS/400.
Inoltre dato che il campo 'città' o di tipo carattere, il valore nella clausola WHERE è stato racchiuso tra apici singoli. Se fosse stato di tipo numerico gli apici non andavano messi.
Esempio
SQL
SELECT [id], [nome], [cognome], [telefono]
FROM Tabella_1
WHERE [id] >= 2
id Nome Cognome Telefono
2 Paperone De Paperoni 1001 98752
4 Topolino Toponi 1002 38988
Gli operatori di confronto disponibili sono: = , >= , <= , !=
Nel caso si dovesse testare se un campo contiene il valore null si usa l'oeratore IS. Esempio:
SQL
SELECT [id], [nome], [cognome], [telefono]
FROM Tabella_1
WHERE [telefono] IS null
che non ritorna niente in quanto nell'esempio non c'è nessun campo con valore null.


Supponiamo adesso di voler ordinare la tabella per 'cognome' in ordine ascendente:
SQL
SELECT [nome], [cognome], [telefono]
FROM Tabella_1
WHERE [città] = 'paperopoli'
ORDER BY [cognome]
id Nome Cognome Telefono
2 Paperone De Paperoni 1001 98752
1 Paperino Paolino 1001 34567
Oppure discendente
SQL
SELECT [nome], [cognome], [telefono]
FROM Tabella_1
WHERE [città] = 'paperopoli'
ORDER BY [cognome] DESC
id Nome Cognome Telefono
1 Paperino Paolino 1001 34567
2 Paperone De Paperoni 1001 98752
Posso anche usare delle condizioni di rcerca (clausola WHERE) più complesse usando gli operatori logici AND e OR. Esempio:
SQL
SELECT [id], [nome], [cognome], [città], [telefono]
FROM Tabella_1
WHERE [nome] = 'paperino' OR [id]=4
id Nome Cognome Città Telefono
1 Paperino Paolino Paperopoli 1001 34567
2 Paperone De Paperoni Paperopoli 1001 98752
4 Topolino Toponi Topolinia 1002 38988
Ovvero, estai tutte le righe dove il campo 'nome' contiene 'paperino' oppure il campo 'id' contiene il valore 4. Quindi basta che sia soddisfatta almeno una delle condizioni perché la riga venga restituita. Al contrario l'operatore AND richiede che entrambi le condizioni siano soddisfatte contemporaneamente. Esempio:
SQL
SELECT [id], [nome], [cognome], [città], [telefono]
FROM Tabella_1
WHERE [id] > 1 AND [cognome]= 'toponi'
id Nome Cognome Città Telefono
4 Topolino Toponi Topolinia 1002 38988
Come si può vedere in questo caso sia il record con 'id' 2 e 4 soddisfa la prima condizione, ma solo nel record con 'id' uguale a 4 abbiamo anche (ovvero contemporaneamente) il campo 'cognome' uguale a 'toponi'.

Gli operatori logici disponibili sono: AND , OR e NOT

Per quanto riguarda i campi stringa esistono anche altri operatori. Uno molto potente e flessibile è l'operatore 'LIKE'. Questo permette di fare delle ricerche parziali all'interno dei campi.Esempio
SQL
SELECT [id], [nome], [cognome], [città], [telefono]
FROM Tabella_1
WHERE [nome] LIKE 'pap%'
id Nome Cognome Città Telefono
1 Paperino Paolino Paperopoli 1001 34567
2 Paperone De Paperoni Paperopoli 1001 98752
Il simbolo '%' (percentuale, detto anche carattere jolly, che su altri DB può essere sostituito da '*' asterisco) indica nessuno o più caratteri. Ovvero vengono ricercate tutte le parole che iniziano con 'pap'. Quindi andrà bene 'pap', 'pap1', 'paperone', 'paperino'. Ecc…
Un altro carattere jolly è '?' (punto di domanda) che indica nessuno o al massimo un carattere qualsiasi. Esempio:
SQL
SELECT [id], [nome], [cognome], [città], [cod], [telefono]
FROM Tabella_1
WHERE [cod] LIKE 'A10?0'
id Nome Cognome Città COD Telefono
1 Paperino Paolino Paperopoli A1010 1001 34567
4 Topolino Toponi Topolinia A1030 1002 38988
Il record con 'id' uguale a 2 non viene restituita in quanto l'ultimo carattere del campo 'cod' è uguale a '1'.
Un altro operatore molto interessante è 'IN' , che permette di specificare una serie di valori. Vediamo un esempio:
SQL
SELECT [id], [nome], [cognome], [città], [cod], [telefono]
FROM Tabella_1
WHERE [nome] IN ( 'Paperino', 'Topolino')
id Nome Cognome Città COD Telefono
1 Paperino Paolino Paperopoli A1021 1001 98752
4 Topolino Toponi Topolinia A1030 1002 38988

Vediamo la struttura del comando INSERT

SQL
INSERT <nome della tabella> (<elenco campi separato da virgole>)
VALUES (<elenco valori>)
Dove tutte le clausole sono sempre presenti e obbligatorie. Le parentesi tonde sono anch'esse obbligatorie.
Adesso vediamo degli esempi in cui andremo ad inserire dei valori nella tabella:
SQL
INSERT Tabella_1 ([id], [nome], [cognome], [città], [cod], [telefono])
VALUES (5, 'pippo', 'de pippis', 'topolinia', 'B1030', '1002 345345')
Modifica la tabella ma non ritorna nessun risultato, per vedere le modifiche apportate digitare:
SQL
SELECT *
FROM Tabella_1
id Nome Cognome Città COD Telefono
1 Paperino Paolino Paperopoli A1010 1001 34567
2 Paperone De Paperoni Paperopoli A1021 1001 98752
4 Topolino Toponi Topolinia A1030 1002 38988
5 pippo de pippis topolinia B1030 1002 345345
A riguardo del comando INSERT non c'è molto da dire in quanto l'unica sintassi è quella mostrata. Bisogna solo fare attenzione (come con tutti gli altri comandi) a racchiudere i valori stringa all'interno delle virgolette singole e specificare i valori dei campi con lo stesso ordine con cui sono stati specificati i nomi dei campi.

Vediamo la struttura del comando UPDATE

SQL
UPDATE <nome della tabella> SET
	<nome campo 1> = <valore campo 1>,
	<nome campo 2> = <valore campo 2>,
	. . .
	<nome campo n> = <valore campo n>
WHERE <condizione di selezione>
Dove tutte le clausole sono sempre presenti e obbligatorie ad eccezione di WHERE, in questo caso le modifiche avranno effetto su tutta la tabella. Le virgole separano le coppie nome campo e valore.
Adesso vediamo degli esempi in cui andremo a modificare alcuni valori in alcuni record della tabella:
SQL
UPDATE Tabella_1 SET
	[cognome] = 'de topis',
	[cod] = 'B1031
WHERE [id] = 4
Modifica la tabella ma non ritorna nessun risultato, per vedere le modifiche apportate digitare:
SQL
SELECT *
FROM Tabella_1
id Nome Cognome Città COD Telefono
1 Paperino Paolino Paperopoli A1010 1001 34567
2 Paperone De Paperoni Paperopoli A1021 1001 98752
4 Topolino de topis Topolinia B1031 1002 38988
5 pippo de pippis topolinia B1030 1002 345345
Anche riguardo del comando UPDATE non c'è molto da dire in quanto l'unica sintassi è quella mostrata. Le uniche cosa da sottolineare sono che, a differenza del comando INSERT, non è necessario specificare tutti i campi ma solo quelli che si vogliono aggiornare. Inoltre il comando UPDATE può agire contemporaneamente su più record. Esempio
SQL
UPDATE Tabella_1 SET
	[città] = 'Mondo Disney'
WHERE [città] = 'paperopoli'
 
SELECT *
FROM Tabella_1
id Nome Cognome Città COD Telefono
1 Paperino Paolino Mondo Disney A1010 1001 34567
2 Paperone De Paperoni Mondo Disney A1021 1001 98752
4 Topolino de topis Topolinia B1031 1002 38988
5 pippo de pippis topolinia B1030 1002 345345
Dove sono stati aggiornati contemporaneamente i record con 'id' uguale a 1 e 2, ovvero dove il campo città conteneva 'paperopoli'

Vediamo la struttura del comando DELETE

SQL
DELETE <nome della tabella>
WHERE <condizione di selezione>
Dove tutte le clausole sono sempre presenti e obbligatorie ad eccezione di WHERE, in questo caso le modifiche avranno effetto su tutta la tabella.
Adesso vediamo degli esempi in cui andremo a cancellare alcuni record della tabella:
SQL
DELETE Tabella_1
WHERE [id] = 2
Modifica la tabella ma non ritorna nessun risultato, per vedere le modifiche apportate digitare:
SQL
SELECT *
FROM Tabella_1
id Nome Cognome Città COD Telefono
1 Paperino Paolino Mondo Disney A1010 1001 34567
4 Topolino de topis Topolinia B1031 1002 38988
5 pippo de pippis topolinia B1030 1002 345345
Anche riguardo del comando DELETE non c'è molto da dire in quanto l'unica sintassi è quella mostrata. Come con il comando UPDATE è possibile agire su più record contemporaneamente. Esempio:
SQL
DELETE Tabella_1
WHERE left([cod], 1) = 'B'
Modifica la tabella ma non ritorna nessun risultato, per vedere le modifiche apportate digitare:
SQL
SELECT *
FROM Tabella_1
id Nome Cognome Città COD Telefono
1 Paperino Paolino Mondo Disney A1010 1001 34567
In questo caso abbiamo usato anche una nuova funzione LEFT che, nello specifico esempio, ritorna 1 carattere del campo a partire da sinistra, se coincide con 'B' la condizione è vera e la riga viene eliminata. Avremmo anche potuto usare l'operatore LIKE visto prima per raggiungere lo stesso risultato:
SQL
DELETE Tabella_1
WHERE [cod] LIKE  'B%'
Altre funzioni simili sono:
  • RIGHT(<nome campo>, <numero caratteri>) : ritorna i caratteri partendo da destra
  • SUBSTRING(<nome campo>, <start>, <length>) : ritorna <length> caratteri a partire dal carattere <start>
  • CHARINDEX(<nome campo>, <str>, <start>) : ritorna la posizione in cui si trova la stringa <nome campo> all'interno della stringa <str> iniziando la ricerca dal carattere <start>
  • LEN(<nome campo>) : che ritorna la lunghezza, in caratteri, del campo
  • LTRIM(<nome campo>) : ritorna una stringa senza spazi a sinistra
  • RTRIM(<nome campo>) : ritorna una stringa senza spazi a DESTRA
  • LOWER(<nome campo>) : ritorna una stringa con tutti i caratteri in minuscolo
  • UPPER(<nome campo>) : ritorna una stringa con tutti i caratteri in maiuscolo
  • e molte altre...

Conclusioni

Come si è visto i comandi fondamentali sono solo 4 e quasi tutti hanno in comune (a parte INSERT) la clausola WHERE per selezionare un certo insieme di record.
Quello che abbiamo visto finora sono i comandi SQL con una sintassi di base, nella pratica, soprattutto il comando SELECT, ha molte più clausole che permettono di fare delle interrogazioni più complesse mettendo in relazione più tabelle tra loro oltre a tutti i comandi del gruppo DDL per creare, modificare o eliminare tabelle o più in generale per intervenire sulla struttura del DB.


Per ora è tutto.

Il codice sql per creare la tabella usata in questo articolo:
SQL
CREATE TABLE [dbo].[Tabella_1] (
	[id] [int] IDENTITY (1, 1) NOT NULL ,
	[Nome] [varchar] (50)  NOT NULL ,
	[Cognome] [varchar] (50) NOT NULL ,
	[Città] [varchar] (50) NOT NULL ,
	[COD] [char] (10)  NOT NULL ,
	[Telefono] [varchar] (50) NOT NULL 
) 
GO
INSERT INTO [Tabella_1] ([Nome], [Cognome], [Città], [COD], [Telefono])
VALUES('Paperino', 'Paolino', 'Paperopoli', 'A1010', '1001 32567')
GO
INSERT INTO [Tabella_1] ([Nome], [Cognome], [Città], [COD], [Telefono])
VALUES('Paperone', 'De Paperoni', 'Paperopoli', 'A1021', '1001 98752')
GO
INSERT INTO [Tabella_1] ([Nome], [Cognome], [Città], [COD], [Telefono])
VALUES('Topolino', 'Toponi', 'Topolinia', 'A1030', '1002 38988')
GO
Potrebbe interessarti anche: