Usiamo un’architettura standard a 3 livelli per i DBMS, lo standard ANSI / SPARC:
- Livello interno - implementa le strutture fisiche di memorizzazione (file sequenziali, file hash etc…)
- Livello logico - Fornisce un modello logico dei dati, indipendenti da come sono memorizzati fisicamente, il modello relazione
- Livello esterno - Fornisce una o più descrizioni di porzioni della base di dati indipendenti dallo schema logico infatti può prevedere organizzazioni dei dati alternative rispetto a quelle utilizzate.
Quindi un esempio di livello logico è:

Mentre per il livello esterno:

Questa è una possibile vista del database, ogni utente con diversi privilegi avrà una vista diversa.
Il linguaggio SQL ci fornisce delle strutture per operare:
- A livello logico
- Data Definition Language (DDL) - per creare schemi di relazioni
- Data Manipolation Language (DML) - Per interrogare ed aggiornare i dati
- A livello esterno - costrutti DDL per creare viste della base di dati
Creazione di Database, Schemi e Tabelle
create database nome_database [opzioni]
Crea un database
create schema nome_schema [opzioni]
Crea uno schema (namespace) all'interno del database corrente
create table nome_table (...)
Crea una nuova tabella all'interno di uno schema del database corrente
Creazione di Tabelle
create table [nome_schema]nome_tabella (
nome_attributo dominio [vincoli di dominio]
...
[altri vincoli intra-relazionali]
[vincoli inter-relazionali]
)Il nome della schema è opzionale e se omesso viene usato lo schema di default senza nome.
Esempio
create table Corso (
codice integer not null,
nome character varying (100) not null,
aula character varying (10) not null,
primary key (codice)
)
create table Incarico (
docente integer not null,
corso integer not null,
primary key (docente, corso),
foreign key (docente) references Docente(matr),
foreign key (corso) references Corso(codice)
)Domini SQL predefiniti
- Domini numerici
- interi: integer, smallint…
- decimali: numeric(prec, scala), decimali(prec, scala)
- approssimati: float(prec), real, double precision
- Stringhe
- character [varying] (lung_max) (abbrev. in char / varchar)
- text
- …
- Istanti temporali
- date (tipo record con campi per anno, mese, giorno)
- time (tipo record con campi per ora, min, sec)
- timestamp (tipo record con campi per anno, …, sec)
- Intervalli temporali: interval
- Valori booleani: Boolean, da SQL:1999 in poi
- Dati non strutturati di grandi dimensioni: CLOB e BLOB
Valori di Deafult
create table Impiegato (
nome ...,
cognome ...,
stipendio integer default 0,
...
)Se durante un inserimento o una modifica di questa tabella non viene indicato un valore per la colonna stipendio allora questo verrà impostato a 0.
Vincoli di Dominio
create table Impiegato (
nome varchar(100) not null ,
cognome varchar(100) not null ,
stipendio integer default 0
check ( stipendio >= 0) ,
...
)- Ogni ennupla deve soddisfare il vincolo
stipendio >= 0 - Il vincolo viene controllato in automatico all’inserimento e alla modifica
- In caso di violazione, l’inserimento o la modifica non avvengono e viene generato un errore.
Vincoli di chiave
create table Studente (
matricola integer not null,
nome varchar(100) not null,
cognome varchar(100) not null,
nascita date,
cf character(16) not null,
// Chiave primaria (implica not null)
primary key (matricola),
unique (cf), //altra chiave
unique (cognome, nome, nascita) //altra chiave
)Se il vincolo di chiave è su un solo attributo possiamo usare anche:
create table Studente (
matricola integer primary key, // implica not null
...
)SQL e modello relazionale
Una tabella SQL non rappresenta sempre una relazione infatti può contenere ennuple uguali, affinché rappresenti una relazione è necessario definire almeno una chiave.
Esempio
create table Studente (
matr integer not null,
cognome varchar(100) not null,
nome varchar(100) not null
)Da questa tabella possiamo ottenere:

Mentre con questa:
create table Studente (
matr integer not null,
cognome varchar(100) not null,
nome varchar(100) not null,
primary key (matr)
)Non può accadere la situazione di prima con ennuple uguali.
Vincoli di integrità referenziale
Costruiamo un database di esempio

create table Officina (
nome varchar(100) not null,
indirizzo varchar(500) not null,
primary key (nome)
)
create table Veicolo (
targa char(8) not null,
tipo varchar(50) not null,
primary key (targa)
)
create table Riparazione (
officina varchar(100) not null,
codice integer not null,
veicolo char(8) not null
primary key (officina, codice)
foreign key (officina) references Officina(nome),
foreign key (veicolo) references Veicolo(targa)
)
create table RicambioRip (
officina varchar(100) not null,
rip int not null,
ricambio char(5) not null,
primary key (officina, rip, ricambio),
foreign key (officina) references Officina(nome),
foreign key (rip) references Riparazione(codice)
)
Modifica e Cancellazione di tabelle, schemi e database
Modifca:
alter tablealter table add columnalter table drop columnalter table alter columnalter table add constraintalter table drop constraint- …
Per la cancellazione.
drop table <nome tabella>drop schema <nome schema>drop database <nome database>
Domini SQL definiti dall’utente
Per l’utente è possibile definire:
- Domini specializzazione di altri domini
- Domini di tipo enumerativo
- Domini di tipo record
Ed SQL offre due comandi per fare questo:
create domaincreate typeChe offrono diverse funzionalità
Domini speciallizati
Un dominio specializzato definisce un sottoinsieme di valori di un dominio esistente
create domain nome_dominio as tipo_base
[valore di default]
[vincolo]Esempio - Definizione del dominio voto
create domain voto as integer
default 0
check (value >= 18 and value <= 30)Domini Enumerativi
Un dominio enumerativo definisce un insieme finito, piccolo e stabile di valori ognuno identificato da un’etichetta.
create type nome_dominio as enum('valore1',..., 'valore N')Esempio - Definizione del dominio genere
create type genere as enum('M', 'F')Etichette delle enum
Le etichette delle enum non sono strighe ma identificatori veri e propri.
Domini Tipi Record
I valori di un dominio di tipo record (o dominio composto) sono record di valori, uno per ogni campo del dominio. Il valore di ogni campo di un record è del rispettivo dominio.
create type nome_dominio as (
campo1 dominio1, ..., campoN dominioN
)Esempio - Definizione del dominio composto indirizzo
create type indirizzo (
via varchar(200), citta varchar(100)
)Costrutto Create type
Il costrutto create type non è implementato di standard e a seconda della versione può soffrire alcune limitazioni.
Modifica e Cancellazione di Domini
Tutti i domini che abbiamo creato possono essere modificati o rimossi.
Modifica:
alter domain <nome dominio>alter type <nome dominio>
Cancellazione:
drop dominio <nome dominio>drop type <nome dominio>
Generazione di Valori Progressivi
In alcune situazioni è necessario aggiungere un identificatore artificiale in una entità e quindi un attributo aggiuntivo.
Esempio

In questi casi è possibile lasciare al DBMS il compito di assegnare valori diversi per il campo id (generalmente progressivi) alle diverse ennuple.
Con PostgreSQL usiamo il seguente costrutto:
create table Prenotazione (
id integer default nextval ('Prenotazione_id_seq') not null,
istante timestamp not null,
primary key (id)
);Oppure in modo più breve:
create table Prenotazione (id serial not null, ...)Per inserire ennuple:
insert into Prenotazione(istante)
values ('2011-08-24 13:15:05') returning idQuesto costrutto PostgreSQL returning id permette al comando insert di restituire all’utente il valore per id scelto dal DBMS.
In MySQL invece abbiamo il modificatore auto_increment per gli attributi:
create table Prenotazione (
id integer not null auto_increment,
istante timestamp not null,
primary key (id)
);E per inserire ennuple usiamo:
insert into Prenotazione(istante) values ('2011-08-24 13:15:05')