SQL - definizione dei dati e vincoli
In questa pagina 8
Prerequisiti: Modello relazionale - relazioni, chiavi e vincoliIl modello relazionale (Codd, IBM, 1970) rappresenta i dati con relazioni, cioè tabelle, ed è basato su valori: i legami tra relazioni sono confronti di valori, non puntatori, il che garantisce indipendenza dalle strutture fisiche, portabilità e bidirezionalità. Una relazione matematica è un sottoinsieme del prodotto cartesiano di n domini (insieme di n-uple ordinate, senza duplicati né ordine tra le righe); una relazione del modello è un insieme di tuple, funzioni dagli attributi ai valori del dominio, quindi non posizionale. Si distinguono schema di relazione e istanza, schema di base di dati (relazioni più vincoli) e istanza. NULL è un valore speciale fuori da ogni dominio. I vincoli di integrità sono intra-relazionali (di dominio, di tupla, di chiave) e inter-relazionali (integrità referenziale, con la chiave esterna). Superchiave: insieme di attributi che non ripete mai i valori; chiave: superchiave minimale; ogni relazione ne ha almeno una (tutti gli attributi); la chiave primaria è una chiave scelta, senza NULL.Modello relazionale - relazioni, chiavi e vincoli → (chiavi, chiavi esterne, vincoli di integrità) e la traduzione dallo schema ER in Ristrutturazione dello schema ER e traduzione nel modello relazionaleLa progettazione logica ha due passi. 1) Ristrutturazione dello schema ER, per togliere i costrutti che il modello relazionale non esprime: analisi delle ridondanze (attributi derivati e cicli di relazioni, decisa con volume dei dati e carico, tabelle di frequenza e accessi), eliminazione degli attributi multivalore (nuova entità), composti (appiattiti o nuova entità), delle IS-A (relazione con partecipazione (1,1) dalla sottoclasse) e delle generalizzazioni (opzione 1 relazioni, 2 accorpamento nel padre con attributo discriminante, 3 accorpamento nei figli, solo se completa e disgiunta), scelta degli identificatori principali (niente cicli di identificazione esterna), riscrittura dei vincoli esterni, partizionamento e accorpamento di entità. 2) Traduzione quasi automatica nel modello relazionale: ogni entità diventa una relazione con la chiave primaria data dall'identificatore principale (anche esterno); una relazione molti-a-molti diventa una relazione con le chiavi delle entità; una uno-a-molti con partecipazione obbligatoria si fonde con l'entità dal lato max 1 con una chiave esterna; con partecipazione opzionale si fonde (NULL) o si crea una relazione a parte; le uno-a-uno si fondono sul lato con partecipazione obbligatoria; le ternarie seguono la stessa logica con le chiavi di tutte le entità.Ristrutturazione dello schema ER e traduzione nel modello relazionale →: qui si trasforma lo schema relazionale in istruzioni SQL. Le interrogazioni sono in SQL - interrogazioni, join e aggregazioniUn'interrogazione SQL ha almeno SELECT e FROM; le altre clausole (WHERE, GROUP BY, HAVING, ORDER BY) sono opzionali e HAVING richiede GROUP BY. Ordine logico di valutazione: FROM, WHERE, GROUP BY, HAVING, SELECT, DISTINCT, ORDER BY. SELECT corrisponde a π (ma senza DISTINCT non elimina i duplicati), WHERE a σ, gli alias ad AS/ρ, i join a ⋈ (INNER, LEFT, RIGHT, FULL). WHERE seleziona le righe prima del raggruppamento, HAVING seleziona i gruppi dopo. Le funzioni COUNT, SUM, AVG, MIN, MAX ignorano i NULL (COUNT(*) conta le righe, DISTINCT toglie i duplicati dentro la funzione); con un aggregato o con GROUP BY nella SELECT possono comparire solo colonne di raggruppamento o aggregati. LIKE usa % (qualsiasi sequenza) e _ (un carattere). I confronti con NULL non sono veri: serve IS NULL. Un filtro sulla tabella di destra di un LEFT JOIN va nella clausola ON, non in WHERE, altrimenti il join diventa interno. Con interi COUNT(a)/COUNT(b) è una divisione intera: serve CAST.SQL - interrogazioni, join e aggregazioni →. Un esempio completo, con DDL, DML e interrogazioni, è nell'esercizio Esercizio - Laboratorio sul social network - DDL, DML e interrogazioni (laboratorio).
I comandi seguenti sono quelli di PostgreSQL, il DBMS del corso. Dove SQLite (che si è usato per provare gli esempi) si comporta in modo diverso, lo si dice.
Il linguaggio SQL
- DDL (Data Definition Language): crea e modifica la struttura (database, schemi, tabelle, vincoli, viste, indici);
- DML (Data Manipulation Language): legge e modifica i dati (
SELECT,INSERT,UPDATE,DELETE).
Implementa il modello relazionale e l'algebra (Algebra relazionale - operatori di base e joinLe operazioni sul modello relazionale sono di aggiornamento (inserimento, modifica, cancellazione, che possono violare i vincoli di integrità: si rifiuta, si corregge, si propaga con cascade o si imposta NULL/default) e di interrogazione (funzioni che da un'istanza del database producono una relazione). L'algebra relazionale è il linguaggio procedurale delle interrogazioni: gli operatori primitivi sono unione, differenza, prodotto, rinomina ρ, selezione σ e proiezione π; derivati sono intersezione, theta-join, equi-join, join naturale. Unione, intersezione e differenza richiedono relazioni compatibili all'unione (stessi attributi e domini). La selezione è una decomposizione orizzontale, la proiezione verticale (commutano solo se gli attributi della selezione sono nella proiezione). Il theta-join è σ_φ(R1×R2), il join naturale equivale a un equi-join sugli attributi omonimi seguito da una proiezione; la sua cardinalità è tra 0 e |R1||R2|, ≤|R1| se gli attributi comuni sono chiave di R2, =|R1| se sono anche chiave esterna di R1 con vincolo di integrità referenziale. Le tuple senza corrispondente sono "dangling". I valori NULL richiedono condizioni esplicite IS NULL / IS NOT NULL, perché σ_{A>40} ∪ σ_{A≤40} non restituisce le tuple con A nullo.Algebra relazionale - operatori di base e join →) con alcune estensioni. Lo standard è ISO/IEC 9075 (SQL-86, SQL-89, SQL-92, SQL:1999 e seguenti, fino a SQL:2016); ha tre livelli di conformità: Entry, Intermediate (quello implementato da quasi tutti i DBMS commerciali) e Full. Vantaggi: curva di apprendimento bassa, portabilità e longevità delle applicazioni. Svantaggi: ogni DBMS ha le sue varianti (portabilità limitata), il linguaggio è lontano da uno "ideale", e lo standard lascia alcune scelte implementation-defined o implementation-dependent.
Tabelle, righe, query
- Tabella di base (base table): contiene i dati; è un insieme di zero o più colonne e zero o più righe; le righe non sono ordinate e hanno tutte lo stesso tipo di riga; due colonne non possono avere lo stesso nome.
- Interrogazione: operazione su una o più tabelle che restituisce una tabella derivata. Le righe di una tabella derivata possono essere ordinate (
ORDER BY) e la tabella può avere più colonne con lo stesso nome. - Una tabella SQL è un multi-insieme di righe: può contenere duplicati. Quindi non è una relazione in senso stretto (nell'algebra una relazione è un insieme).
Catalogo, schema e identificatori
Un catalogo è un insieme di schemi; uno schema è un insieme di descrittori di oggetti (tabelle, viste, domini...). Come si creano è implementation-defined. Lo information schema descrive tutti gli oggetti del catalogo.
Parole chiave e identificatori sono insensibili alle maiuscole. Un identificatore regolare è di al più 128 caratteri, inizia con una lettera, contiene lettere, cifre e _, e non può essere una parola riservata. Un identificatore delimitato è tra doppi apici ("SELECT" è valido come nome) ed è sensibile alle maiuscole: "SELECT", "select" e "SeLeCt" sono tre identificatori diversi.
Database e schema
CREATE DATABASE Example ENCODING 'UTF-8'; -- PostgreSQL
DROP DATABASE Example;
CREATE SCHEMA Test;
DROP SCHEMA Test CASCADE;DROP SCHEMA ... CASCADEcancella anche tutti gli oggetti dello schema;RESTRICT(il comportamento predefinito) cancella lo schema solo se è vuoto. Lo stessoCASCADE/RESTRICTvale perDROP TYPE,DROP DOMAIN,DROP TABLE,DROP VIEW,DROP INDEX,DROP TRIGGER.- Nello stesso catalogo si possono creare più schemi, di proprietari diversi; di norma gli oggetti creati in uno schema appartengono al suo proprietario.
Tipi di dato
| Tipo | Significato |
|---|---|
CHAR(n), CHARACTER(n) |
stringa a lunghezza fissa di esattamente caratteri |
VARCHAR(n), CHARACTER VARYING(n) |
stringa a lunghezza variabile fino a caratteri |
BINARY(n), VARBINARY(n) |
stringa di byte (in PostgreSQL BYTEA) |
NUMERIC(p, s) |
numero esatto con cifre totali e decimali: per importi di denaro e dove serve esattezza |
SMALLINT, INTEGER, BIGINT |
interi con segno (in PostgreSQL 2, 4, 8 byte) |
REAL, DOUBLE PRECISION |
virgola mobile (4 byte con 6 cifre, 8 byte con 15 cifre) |
SMALLSERIAL, SERIAL, BIGSERIAL |
intero autoincrementale (solo PostgreSQL) |
BOOLEAN |
valori logici |
DATE, TIME, TIMESTAMP |
data, ora, data e ora, con o senza fuso (WITH/WITHOUT TIME ZONE) |
INTERVAL |
intervallo di tempo |
Tipi avanzati di PostgreSQL:
UUID: identificatore a 128 bit, per esempioa0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11, generato in modo che sia praticamente impossibile ottenere lo stesso valore due volte (il modulouuid-osspfornisce le funzioni di generazione);- tipi intervallo (
int4range,int8range,numrange,tsrange,tstzrange,daterange): rappresentano molti valori in uno solo (per esempio le ore in cui una sala riunioni è prenotata) ed esprimono bene la sovrapposizione tra intervalli; il sottotipo deve avere un ordine totale; jsonejsonb:jsonconserva il testo esatto e lo rianalizza a ogni uso,jsonbè in formato binario, più lento da scrivere ma molto più veloce da interrogare, e supporta gli indici. Sono la strada flessibile verso i database NoSQL.
Tipo enumerato (insieme statico e ordinato di valori; l'ordine è quello della creazione):
CREATE TYPE visibility AS ENUM ('public', 'private', 'friends');
DROP TYPE visibility CASCADE; -- o RESTRICT (predefinito)Dominio definito dall'utente: un tipo con un vincolo, riusabile in più tabelle.
CREATE DOMAIN Identifier AS VARCHAR(32);
CREATE DOMAIN Mark AS SMALLINT
DEFAULT NULL
CHECK (VALUE >= 18 AND VALUE <= 30);DEFAULT dà il valore usato se non se ne specifica uno; NOT NULL/NULL indica se NULL è ammesso; CHECK pone vincoli aggiuntivi su VALUE. DROP DOMAIN Identifier CASCADE cancella anche gli oggetti che dipendono dal dominio.
In SQLite non esistono
CREATE DOMAIN,CREATE TYPE ... ENUM,SERIAL,UUID, tipi intervallo néjsonb: si usanoVARCHAR/TEXT,CHECK (x IN (...))per gli enumerati,INTEGER PRIMARY KEY AUTOINCREMENTper gli autoincrementali. I tipi sono "indicazioni": SQLite non li impone rigidamente.
Creare una tabella
La definizione di una tabella è l'elenco delle colonne con nome, tipo e vincoli, seguito dagli eventuali vincoli sulla tabella intera.
I vincoli
| Vincolo | Significato |
|---|---|
NOT NULL |
il valore NULL non è ammesso. È implicito nella chiave primaria |
DEFAULT <costante> |
valore assegnato all'inserimento se non specificato; può essere una costante, NULL o una funzione senza argomenti (CURRENT_USER, CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP) |
CHECK (<espressione>) |
vincolo di dominio se riferito a una sola colonna, vincolo di tupla se a livello di tabella (confronta più colonne della stessa riga) |
PRIMARY KEY (c1, c2,...) |
chiave primaria, composta da una o più colonne. Una sola per tabella; si può dare un nome al vincolo |
UNIQUE (c1, c2,...) |
una chiave non primaria (una colonna o più): non ammette righe ripetute |
FOREIGN KEY (c1,...) REFERENCES T(d1,...) |
chiave esterna con vincolo di integrità referenziale: i valori di c1,... devono comparire come valori di d1,... in T (o essere NULL) |
Per la chiave esterna si dichiara anche che cosa fare quando la riga puntata viene cancellata o modificata:
FOREIGN KEY (...) REFERENCES T(...)
[ON DELETE {NO ACTION | CASCADE | SET NULL | SET DEFAULT}]
[ON UPDATE {NO ACTION | CASCADE | SET NULL | SET DEFAULT}]NO ACTION(predefinito): l'operazione è vietata;CASCADE: si cancellano (o si aggiornano) anche tutte le righe che puntano;SET NULL: le colonne della chiave esterna diventano NULL;SET DEFAULT: le colonne diventano il valore di default dichiarato.
Un esempio completo: i riferimenti bibliografici
Schema relazionale (la chiave primaria è id, tranne in Information, dove è reference, e in Write): Author(id, name, surname), Publisher(id, name), Reference(id, title, year, publisher) con publisher Publisher, Information(reference, notes) con reference Reference, Write(reference, author, authorNumber) con chiave e le due chiavi esterne.
CREATE DOMAIN Identifier AS VARCHAR(32);
CREATE TABLE Author (
id Identifier PRIMARY KEY, -- vincolo di colonna
name VARCHAR(30),
surname VARCHAR(30) NOT NULL
);
CREATE TABLE Publisher (
id Identifier,
name VARCHAR(150) NOT NULL,
PRIMARY KEY (id) -- vincolo di tabella: equivalente
);
CREATE TABLE Reference (
id Identifier,
title VARCHAR(200) NOT NULL,
year SMALLINT NOT NULL CHECK (year > 0),
publisher Identifier,
PRIMARY KEY (id),
FOREIGN KEY (publisher) REFERENCES Publisher(id)
);
CREATE TABLE Information (
reference Identifier,
notes VARCHAR(200) NOT NULL,
PRIMARY KEY (reference),
FOREIGN KEY (reference) REFERENCES Reference(id)
);
CREATE TABLE Write (
reference Identifier,
author Identifier,
authorNumber SMALLINT DEFAULT 1 NOT NULL CHECK (authorNumber > 0),
PRIMARY KEY (reference, author), -- chiave primaria COMPOSTA
FOREIGN KEY (reference) REFERENCES Reference(id),
FOREIGN KEY (author) REFERENCES Author(id)
);Punti da notare:
- Ordine di creazione:
Publisherprima diReference, perché una chiave esterna può puntare solo a una tabella già esistente (o a una tabella aggiunta dopo conALTER TABLE). Per cancellare si fa l'inverso, oppureDROP TABLE ... CASCADE. Informationha come chiave primaria la stessa chiave esterna: è la traduzione di una relazione 1-a-1 (almeno 0 o 1 informazione per riferimento).Writeè la traduzione di una relazione molti-a-molti: la chiave è la coppia. ScriverePRIMARY KEYaccanto a ciascuna delle due colonne non significa chiave composta ma tentare di creare due chiavi primarie, e dà errore (SQLite: table has more than one primary key).authorNumberè la posizione dell'autore nell'elenco:DEFAULT 1,NOT NULLeCHECK (authorNumber > 0)insieme.
Chiavi e NULL.
UNIQUEammette più righe con NULL (due NULL non sono "uguali"), mentre la chiave primaria non ammette NULL. Conemail VARCHAR(50) UNIQUE, due righe conemail = NULLsono accettate, due con'a@x'no (verificato).
Esempio di vincoli violati
Con PRAGMA foreign_keys = ON in SQLite (in PostgreSQL le chiavi esterne sono sempre attive) sulle tabelle sopra:
| Istruzione | Esito |
|---|---|
INSERT INTO Write VALUES ('T1996','TanenbaumAS',1) due volte |
errore: la chiave esiste già |
INSERT INTO Write VALUES ('T2001','Nessuno',1) |
errore: l'autore Nessuno non esiste (chiave esterna) |
INSERT INTO Write VALUES ('T2001','TanenbaumAS',0) |
errore: CHECK (authorNumber > 0) |
INSERT INTO Reference VALUES ('X','Senza titolo',-5,'PH') |
errore: CHECK (year > 0) |
INSERT INTO Reference(id, year) VALUES ('Y', 2000) |
errore: title è NOT NULL e non ha default |
INSERT INTO Reference VALUES ('Z','Ok',2000,NULL) |
accettato: publisher può essere NULL |
Modificare ed eliminare una tabella
ALTER TABLE Author ADD COLUMN SecondName VARCHAR(20);
ALTER TABLE Author
DROP COLUMN Surname,
ADD COLUMN Surname VARCHAR(50);
ALTER TABLE Author DROP CONSTRAINT author_pkey, -- PostgreSQL: si toglie per nome
ADD PRIMARY KEY (name);
DROP TABLE Author CASCADE; -- cancella anche le tabelle che la referenziano via FKALTER TABLE aggiunge o toglie colonne e vincoli. Cancellare una colonna perde i suoi dati. La forma DROP PRIMARY KEY è di MySQL: in PostgreSQL si cancella il vincolo per nome (DROP CONSTRAINT). DROP TABLE ... RESTRICT (predefinito) rifiuta se un altro oggetto dipende dalla tabella.
Manipolazione dei dati
Inserimento. Si può omettere l'elenco delle colonne se si danno tutti i valori nell'ordine della tabella; con l'elenco si omettono le colonne con default (o NULL):
INSERT INTO Author VALUES ('BuckJR', 'John R.', 'Buck');
INSERT INTO Write VALUES ('Tanenbaum2001', 'TanenbaumAS', DEFAULT); -- PostgreSQL
INSERT INTO Write (reference, author) VALUES ('Tanenbaum2001', 'TanenbaumAS'); -- equivalente, valido anche in SQLiteLa parola DEFAULT dentro VALUES è di PostgreSQL; SQLite non la accetta (si omette la colonna).
Cancellazione. Senza WHERE si cancellano tutte le righe (la tabella resta):
DELETE FROM Write; -- svuota la tabella
DELETE FROM Write WHERE author = 'BuckJR'; -- solo le righe di quell'autoreModifica.
UPDATE Author SET name = 'Giacomo' WHERE surname = 'Pagano';
UPDATE Author SET name = 'Giacomo'; -- TUTTE le righe!
UPDATE Write SET authorNumber = authorNumber + 1; -- espressione sul valore vecchio
UPDATE Write SET authorNumber = authorNumber + 1
WHERE reference = 'CastelliPagano2002a';Nel SET il valore a destra è calcolato sulla riga prima della modifica. Un UPDATE o DELETE senza WHERE agisce su tutta la tabella: è l'errore più costoso (si può proteggere con una transazione, vedi SQL avanzato - indici, transazioni e triggerUn file di record può essere heap (inserimento in ordine, ricerca per uguaglianza in media n/2 accessi), ordinato (log2 n), hash (costante, solo uguaglianza) o B-tree (log_F n, anche intervalli). Un indice è una struttura ausiliaria di coppie (chiave K, puntatore P) ordinate, molto più piccola della tabella: l'indice primario è sul campo di ordinamento del file ordinato (una chiave per blocco, non denso, log2(m)+1 accessi), l'indice secondario è su un campo qualsiasi (denso). CREATE [UNIQUE] INDEX, anche su espressioni; PostgreSQL usa tabelle heap con indici secondari B-tree (predefinito) o hash, e PRIMARY KEY e UNIQUE creano un indice implicito. Gli indici velocizzano le letture ma costano nelle scritture e in spazio. Una transazione è una sequenza atomica di operazioni con proprietà ACID (atomicità, consistenza, isolamento, durabilità): START TRANSACTION, COMMIT, SAVEPOINT, ROLLBACK [TO SAVEPOINT]. Un trigger è una regola evento-condizione-azione (ECA): BEFORE/AFTER, ROW/STATEMENT, WHEN, con funzione PL/pgSQL che usa NEW e OLD; serve per vincoli complessi e attributi derivati.SQL avanzato - indici, transazioni e trigger →).
Effetto delle azioni sulle chiavi esterne (provato)
Con Reference.publisher REFERENCES Publisher(id) ON DELETE SET NULL ON UPDATE CASCADE e Write.reference REFERENCES Reference(id) ON DELETE CASCADE:
UPDATE Publisher SET id = 'PRH' WHERE id = 'PH': tutte le righe diReferenceconpublisher = 'PH'diventano'PRH'(cascade);DELETE FROM Publisher WHERE id = 'PRH': quelle righe restano, conpublisher = NULL(set null);DELETE FROM Reference WHERE id = 'T1996': spariscono anche le righe diWritecon quel riferimento (cascade);- una chiave esterna senza azione (
NO ACTION):DELETE FROM Author WHERE id = 'TanenbaumAS'fallisce finché esistono righe diWriteche puntano all'autore. - con
ON DELETE SET DEFAULTla colonna torna al suo default (che deve esistere come valore della tabella referenziata).
Quale azione scegliere? CASCADE per le entità dipendenti (le righe di Write non hanno senso senza il riferimento), SET NULL per legami opzionali (un riferimento può non avere un editore), NO ACTION per le entità importanti (non si deve poter cancellare un autore per sbaglio).
Errori tipici
- Usare
PRIMARY KEYdue volte nelle colonne per una chiave composta (serve il vincolo di tabella). - Creare le tabelle nell'ordine sbagliato (la tabella referenziata deve esistere) o cancellarle senza
CASCADE. - Usare
FLOAT/REALper i soldi (errori di arrotondamento):NUMERIC(p, s). UPDATE/DELETEsenzaWHERE.- Dimenticare che
UNIQUEammette più NULL, e che il confronto con NULL non è vero (Algebra relazionale - operatori di base e joinLe operazioni sul modello relazionale sono di aggiornamento (inserimento, modifica, cancellazione, che possono violare i vincoli di integrità: si rifiuta, si corregge, si propaga con cascade o si imposta NULL/default) e di interrogazione (funzioni che da un'istanza del database producono una relazione). L'algebra relazionale è il linguaggio procedurale delle interrogazioni: gli operatori primitivi sono unione, differenza, prodotto, rinomina ρ, selezione σ e proiezione π; derivati sono intersezione, theta-join, equi-join, join naturale. Unione, intersezione e differenza richiedono relazioni compatibili all'unione (stessi attributi e domini). La selezione è una decomposizione orizzontale, la proiezione verticale (commutano solo se gli attributi della selezione sono nella proiezione). Il theta-join è σ_φ(R1×R2), il join naturale equivale a un equi-join sugli attributi omonimi seguito da una proiezione; la sua cardinalità è tra 0 e |R1||R2|, ≤|R1| se gli attributi comuni sono chiave di R2, =|R1| se sono anche chiave esterna di R1 con vincolo di integrità referenziale. Le tuple senza corrispondente sono "dangling". I valori NULL richiedono condizioni esplicite IS NULL / IS NOT NULL, perché σ_{A>40} ∪ σ_{A≤40} non restituisce le tuple con A nullo.Algebra relazionale - operatori di base e join →). - Mettere
DEFAULToCHECKnel posto sbagliato: ilCHECKsu più colonne va a livello di tabella. - Credere che le chiavi esterne di SQLite siano attive: serve
PRAGMA foreign_keys = ON.
Domande d'esame
1. Scrivere in SQL la tabella Write(reference, author, authorNumber) con chiave primaria sui primi due attributi, chiavi esterne verso Reference e Author, e authorNumber positivo con valore di default 1.
Traccia. Come nell'esempio: PRIMARY KEY (reference, author) a livello di tabella, due FOREIGN KEY, authorNumber SMALLINT DEFAULT 1 NOT NULL CHECK (authorNumber > 0).
2. Cosa succede con ON DELETE CASCADE, SET NULL e NO ACTION se si cancella la riga referenziata?
Traccia. CASCADE cancella le righe che puntano; SET NULL mette a NULL la chiave esterna (non è possibile se fa parte della chiave primaria); NO ACTION (predefinito) vieta l'operazione.
3. Differenza tra tabella SQL e relazione.
Traccia. La relazione è un insieme di tuple, senza duplicati e senza ordine; la tabella SQL è un multi-insieme: ammette righe uguali, a meno che una chiave o DISTINCT non le eviti.
Versione ripasso
Linguaggio: SQL è dichiarativo. DDL crea e modifica la struttura; DML legge e modifica i dati (SELECT, INSERT, UPDATE, DELETE). Standard ISO 9075, livelli Entry, Intermediate, Full. Una tabella SQL è un multi-insieme di righe (ammette duplicati): non è una relazione in senso stretto. Le righe non sono ordinate. Identificatori regolari insensibili alle maiuscole; quelli delimitati "..." sono sensibili. Base: Modello relazionale - relazioni, chiavi e vincoliIl modello relazionale (Codd, IBM, 1970) rappresenta i dati con relazioni, cioè tabelle, ed è basato su valori: i legami tra relazioni sono confronti di valori, non puntatori, il che garantisce indipendenza dalle strutture fisiche, portabilità e bidirezionalità. Una relazione matematica è un sottoinsieme del prodotto cartesiano di n domini (insieme di n-uple ordinate, senza duplicati né ordine tra le righe); una relazione del modello è un insieme di tuple, funzioni dagli attributi ai valori del dominio, quindi non posizionale. Si distinguono schema di relazione e istanza, schema di base di dati (relazioni più vincoli) e istanza. NULL è un valore speciale fuori da ogni dominio. I vincoli di integrità sono intra-relazionali (di dominio, di tupla, di chiave) e inter-relazionali (integrità referenziale, con la chiave esterna). Superchiave: insieme di attributi che non ripete mai i valori; chiave: superchiave minimale; ogni relazione ne ha almeno una (tutti gli attributi); la chiave primaria è una chiave scelta, senza NULL.Modello relazionale - relazioni, chiavi e vincoli → e Ristrutturazione dello schema ER e traduzione nel modello relazionaleLa progettazione logica ha due passi. 1) Ristrutturazione dello schema ER, per togliere i costrutti che il modello relazionale non esprime: analisi delle ridondanze (attributi derivati e cicli di relazioni, decisa con volume dei dati e carico, tabelle di frequenza e accessi), eliminazione degli attributi multivalore (nuova entità), composti (appiattiti o nuova entità), delle IS-A (relazione con partecipazione (1,1) dalla sottoclasse) e delle generalizzazioni (opzione 1 relazioni, 2 accorpamento nel padre con attributo discriminante, 3 accorpamento nei figli, solo se completa e disgiunta), scelta degli identificatori principali (niente cicli di identificazione esterna), riscrittura dei vincoli esterni, partizionamento e accorpamento di entità. 2) Traduzione quasi automatica nel modello relazionale: ogni entità diventa una relazione con la chiave primaria data dall'identificatore principale (anche esterno); una relazione molti-a-molti diventa una relazione con le chiavi delle entità; una uno-a-molti con partecipazione obbligatoria si fonde con l'entità dal lato max 1 con una chiave esterna; con partecipazione opzionale si fonde (NULL) o si crea una relazione a parte; le uno-a-uno si fondono sul lato con partecipazione obbligatoria; le ternarie seguono la stessa logica con le chiavi di tutte le entità.Ristrutturazione dello schema ER e traduzione nel modello relazionale →.
Database e schema: CREATE/DROP DATABASE, CREATE/DROP SCHEMA. DROP ... CASCADE cancella anche gli oggetti dipendenti; RESTRICT (predefinito) cancella solo se vuoto.
Tipi:
CHAR(n)lunghezza fissa,VARCHAR(n)variabile fino a ;NUMERIC(p,s)per gli importi di denaro:REALeFLOATarrotondano;SMALLINT,INTEGER,BIGINT;SERIAL(solo PostgreSQL, autoincrementale);BOOLEAN,DATE,TIME,TIMESTAMP,INTERVAL;- PostgreSQL:
UUID, tipi intervallo (daterangee simili),json(testo) ejsonb(binario, indicizzabile).
CREATE TYPE visibility AS ENUM ('public', 'private', 'friends');
CREATE DOMAIN Mark AS SMALLINT DEFAULT NULL CHECK (VALUE >= 18 AND VALUE <= 30);Un dominio è un tipo con un vincolo, riusabile in più tabelle.
CREATE TABLE: elenco di colonne con nome, tipo e vincoli, seguito dai vincoli di tabella.
| Vincolo | Significato |
|---|---|
NOT NULL |
NULL non ammesso; implicito nella chiave primaria |
DEFAULT |
valore se non specificato: costante, NULL, CURRENT_DATE... |
CHECK (...) |
su una colonna è vincolo di dominio; a livello di tabella è vincolo di tupla |
PRIMARY KEY (...) |
una sola per tabella, anche composta; implica NOT NULL |
UNIQUE (...) |
niente righe ripetute; ammette più NULL |
FOREIGN KEY (c) REFERENCES T(d) |
integrità referenziale: i valori compaiono in T oppure sono NULL |
Azioni sulle chiavi esterne: ON DELETE e ON UPDATE con NO ACTION (predefinito, vieta l'operazione), CASCADE, SET NULL, SET DEFAULT. Sono le scelte restrict/cascade/set null/set default di Algebra relazionale - operatori di base e joinLe operazioni sul modello relazionale sono di aggiornamento (inserimento, modifica, cancellazione, che possono violare i vincoli di integrità: si rifiuta, si corregge, si propaga con cascade o si imposta NULL/default) e di interrogazione (funzioni che da un'istanza del database producono una relazione). L'algebra relazionale è il linguaggio procedurale delle interrogazioni: gli operatori primitivi sono unione, differenza, prodotto, rinomina ρ, selezione σ e proiezione π; derivati sono intersezione, theta-join, equi-join, join naturale. Unione, intersezione e differenza richiedono relazioni compatibili all'unione (stessi attributi e domini). La selezione è una decomposizione orizzontale, la proiezione verticale (commutano solo se gli attributi della selezione sono nella proiezione). Il theta-join è σ_φ(R1×R2), il join naturale equivale a un equi-join sugli attributi omonimi seguito da una proiezione; la sua cardinalità è tra 0 e |R1||R2|, ≤|R1| se gli attributi comuni sono chiave di R2, =|R1| se sono anche chiave esterna di R1 con vincolo di integrità referenziale. Le tuple senza corrispondente sono "dangling". I valori NULL richiedono condizioni esplicite IS NULL / IS NOT NULL, perché σ_{A>40} ∪ σ_{A≤40} non restituisce le tuple con A nullo.Algebra relazionale - operatori di base e join →. Scelta: cascade per le entità dipendenti, set null per i legami opzionali, no action per le entità importanti.
Esempio: riferimenti bibliografici. Write(reference, author, authorNumber) traduce una relazione molti-a-molti; Information(reference, notes) è 1-a-1 con chiave uguale alla chiave esterna:
CREATE TABLE Write (
reference Identifier,
author Identifier,
authorNumber SMALLINT DEFAULT 1 NOT NULL CHECK (authorNumber > 0),
PRIMARY KEY (reference, author),
FOREIGN KEY (reference) REFERENCES Reference(id),
FOREIGN KEY (author) REFERENCES Author(id)
);- Si crea prima la tabella referenziata (
Publisherprima diReference). PRIMARY KEYscritto accanto a ciascuna colonna crea due chiavi primarie e dà errore: la chiave composta va a livello di tabella.
ALTER e DROP:
ALTER TABLE Author ADD COLUMN SecondName VARCHAR(20);
DROP TABLE Author CASCADE; -- cancella anche le tabelle che la referenzianoADD/DROP COLUMN e ADD/DROP CONSTRAINT. Cancellare una colonna perde i suoi dati. In PostgreSQL il vincolo di chiave si toglie per nome (DROP CONSTRAINT), non con DROP PRIMARY KEY (MySQL).
DML:
INSERT INTO Write (reference, author) VALUES ('Tanenbaum2001', 'TanenbaumAS');
DELETE FROM Write WHERE author = 'BuckJR';
UPDATE Write SET authorNumber = authorNumber + 1 WHERE reference = 'CastelliPagano2002a';- Senza
WHERE,DELETEeUPDATEagiscono su tutta la tabella. È l'errore più costoso. - Nel
SETil valore a destra si calcola sulla riga prima della modifica. DEFAULTdentroVALUESè di PostgreSQL.
SQLite: niente DOMAIN, ENUM, SERIAL, UUID; per gli enumerati CHECK (x IN (...)), per gli autoincrementali INTEGER PRIMARY KEY AUTOINCREMENT. Le chiavi esterne sono attive solo con PRAGMA foreign_keys = ON.
Errori tipici
PRIMARY KEYripetuto su due colonne invece del vincolo di tabella.- Tabelle create o cancellate nell'ordine sbagliato.
REALoFLOATper i soldi.UPDATEoDELETEsenzaWHERE.- Dimenticare che
UNIQUEammette più NULL.
Domande d'esame (tracce)
Writecon chiave su due attributi, due chiavi esterne eauthorNumberpositivo con default 1: vincolo di tabella per la chiave,DEFAULT 1 NOT NULL CHECK (authorNumber > 0)sulla colonna.ON DELETE SET NULLnon è possibile se la chiave esterna fa parte della chiave primaria.- Tabella SQL e relazione: la relazione è un insieme senza duplicati, la tabella SQL può averne.
Esempio completo: Esercizio - Laboratorio sul social network - DDL, DML e interrogazioni (laboratorio). Seguito: SQL - interrogazioni, join e aggregazioniUn'interrogazione SQL ha almeno SELECT e FROM; le altre clausole (WHERE, GROUP BY, HAVING, ORDER BY) sono opzionali e HAVING richiede GROUP BY. Ordine logico di valutazione: FROM, WHERE, GROUP BY, HAVING, SELECT, DISTINCT, ORDER BY. SELECT corrisponde a π (ma senza DISTINCT non elimina i duplicati), WHERE a σ, gli alias ad AS/ρ, i join a ⋈ (INNER, LEFT, RIGHT, FULL). WHERE seleziona le righe prima del raggruppamento, HAVING seleziona i gruppi dopo. Le funzioni COUNT, SUM, AVG, MIN, MAX ignorano i NULL (COUNT(*) conta le righe, DISTINCT toglie i duplicati dentro la funzione); con un aggregato o con GROUP BY nella SELECT possono comparire solo colonne di raggruppamento o aggregati. LIKE usa % (qualsiasi sequenza) e _ (un carattere). I confronti con NULL non sono veri: serve IS NULL. Un filtro sulla tabella di destra di un LEFT JOIN va nella clausola ON, non in WHERE, altrimenti il join diventa interno. Con interi COUNT(a)/COUNT(b) è una divisione intera: serve CAST.SQL - interrogazioni, join e aggregazioni →.