NULL
représente une valeur inconnue
Vrai, Faux, Inconnu
Vrai
Inconnu
Inconnu
Inconnu
= Inconnu
Vrai
si un des arguments est
Vrai
, Faux
si les deux arguments sont
Faux
, Inconnu
sinon
Vrai
si les deux arguments sont
Vrai
…
SELECT * WHERE (name <> 'Jean') OR name='Jean';
SELECT * WHERE name = name;
CREATE TABLE Film (Titre CHAR(20), MeS CHAR(20), Acteur VARCHAR(20))
CREATE TABLE Film (Titre CHAR(20) NOT NULL,Acteur VARCHAR(20),
Realisateur CHAR(20) NOT NULL DEFAULT 'Kurosawa')
TITRE ACTEUR REALISATEUR ----------------------------------------------- Les petits mouchoirs Cotillard Canet La plage Canet <-- Mon Idole Canet Canet Bienvenus chez les ch'tis Boon Boon
CREATE TABLE Prog ( Nom_Cine CHAR(20), Titre CHAR(20), Salle INT,
Horaire TIME, UNIQUE (Nom_Cine,Titre, Horaire))
CREATE TABLE Cine ( Nom_Cine CHAR(20) PRIMARY KEY,
Adresse VARCHAR(60), Telephone CHAR(8))
CREATE TABLE Cine ( NomCine CHAR(20), Adresse VARCHAR(60),
Telephone CHAR(8), CONSTRAINT pk_nc PRIMARY KEY (Nom_Cine))
CREATE TABLE Prog ( Nom_Cine CHAR(20) REFERENCES
Cine(Nom_Cine), Titre CHAR(20), Salle INT, Horaire TIME, CONSTRAINT
fk_titre FOREIGN KEY (Titre) REFERENCES Film(Titre))
# dans Cine:
Telephone CHAR(8) NOT NULL CONSTRAINT pk_nc PRIMARY KEY (Nom_Cine)
# dans Prog:
CONSTRAINT fk_cine FOREIGN KEY (Nom_Cine) REFERENCES Cine(Nom_Cine)
UNIQUE (Nom_Cine,Titre, Horaire)
Les tables ci-dessous violent des contraintes (donc instance
impossible) :
NOM_CINE ADRESSE TELEPHONE --------- --------- --------- ugc bercy 3 rue... 06043494 le champo 17 av... 01049059 ugc bercy 18 bd...
NOM_CINE TITRE SALLE HORAIRE --------- --------------------- ----- ------- ugc bercy Le discours d'un roi 1 20h00 ugc bercy Le discours d'un roi 3 20h00 ugc bercy Le discours d'un roi 2 22h00 ugc bercy Inception 1 14h00 le champo Le discours d'un roi 1 18h00 le campo Inception 1 20h00
Faux
:
CREATE TABLE Prog ( Nom_Cine CHAR(20), Titre CHAR(20),
Salle INT NOT NULL CHECK (1<=salle AND salle<10), Horaire TIME)
La condition peut porter sur plusieurs colonnes de la table, faire
appel à une requête SQL sur une autre table, etc. :
CREATE TABLE Prog ( ..., CHECK ('France'= SELECT pays FROM Cine
WHERE Prog.Nom_Cine=Cine.nom))
Vérifié à chaque modification
de Prog, mais pas de Cine.
DROP TABLE Prog; # Erreur si d'autres objets dépendent de la table
En présence de clefs étrangères, respecter l'ordre pour détruire les
tables, ou bien:DROP TABLE Prog CASCADE;
# Détruit aussi les objets faisant référence à Prog
ALTER TABLE Prog ADD COLUMN jour: DATE
SELECT
: pour interroger
INSERT
: pour insérer des tuples dans une
table
UPDATE
: pour modifier des données dans une
table
DELETE
: pour supprimer des tuples dans une
table
INSERT, UPDATE, DELETE
.
UPDATE
UPDATE Prog SET Heure = '21h00'
WHERE Nom_Cine LIKE 'ugc%' AND Titre= 'Dersou Ouzala';
# Autres expressions possibles:
UPDATE Prog SET Heure = Heure+1;
# les séances seront retardées
UPDATE Produits SET PrixTTC = PrixHT * TVA;
NOM_CINE TITRE SALLE HEURE ugc bercy Dersou Ouzala 1 20h00 ugc bercy Dersou Ouzala 2 22h00 ugc bercy Kagemusha 1 14h00 le champo Dersou Ouzala 1 18h00 le champo Kagemusha 1 20h00Prog après mise à jour
NOM_CINE TITRE SALLE HEURE ugc bercy Dersou Ouzala 1 21h00 ugc bercy Dersou Ouzala 2 21h00 ugc bercy Kagemusha 1 14h00 le champo Dersou Ouzala 1 18h00 le champo Kagemusha 1 20h00
INSERT
INSERT INTO Prog (Nom_Cine, Titre, Salle, Horaire)
VALUES ('ugc', 'Dersou Ouzala', 1, '20h00'); % ne pas oublier
les ' ' pour les chaînes de caractères
Préciser les noms de colonnes n'est pas nécessaire ici, mais permet
en général
DELETE
DELETE FROM Prog WHERE Heure >= '20h00';
DELETE FROM Prog WHERE Titre in (SELECT Titre FROM Film
WHERE LOWER(Acteur) Like 'Jean-%');
# Comportements possible en cas de Foreign Key: échec ou cascade.
TRUNCATE
est plus
rapide.
TRUNCATE Prog;
Ne parcourt pas la table. À utiliser avec prudence !
(pas d'entrée dans le journal ⇒
perturbe MVCC, ne déclenche pas les triggers).
WHERE
optionnelle. Garde les tuples évaluant
condition à “Vrai
”.FROM
aussi optionnelle pour PostgreSQL (pas
Oracle: FROM DUAL
)
SELECT Nom_Cine FROM Prog WHERE Titre='Marion'
SELECT 2+3
Les doublons ne sont pas
éliminés
SELECT * FROM FILM WHERE Acteur='Lonsdale'
SELECT Titre FROM FILM WHERE Acteur='Lonsdale' OR Acteur='Astaire'
NOM_CINE TITRE SALLE HORAIRE --------- --------------------- ----- ------- ugc bercy Le discours d'un roi 1 20h00 ugc bercy Le discours d'un roi 2 22h00 ugc bercy Inception 1 14h00 le champo Le discours d'un roi 1 18h00 le champo Inception 1 20h00
SELECT Nom_cine, Titre
FROM Prog
WHERE Nom_cine = 'ugc bercy' AND HORAIRE < 23h00 AND HORAIRE > 10h00
NOM_CINE TITRE --------- -------------------- ugc bercy Le discours d'un roi ugc bercy Le discours d'un roi ugc bercy Inception
SELECT Nom_Cine, Film.Titre, Horaire FROM Film,
Prog WHERE Film.Titre = Prog.Titre AND Acteur = 'M.Freeman'
↔︎
πNom_Cine,
Film.titre,
Horaire(σActeur
=
′M.Freeman′(Film⋈Prog))
SELECT Nom_Cine, Film.Titre, Horaire
FROM Film, Prog
WHERE Film.Titre = Prog.Titre AND Acteur = 'M.Freeman'
NOM_CINE TITRE SALLE HORAIRE --------- --------------------- ----- ------- ugc bercy Le discours d'un roi 1 20h00 ugc bercy Le discours d'un roi 2 22h00 ugc bercy Inception 1 14h00 le champo Le discours d'un roi 1 18h00 le champo Inception 1 20h00
NOM_CINE ADRESSE TELEPHONE --------- --------- --------- ugc bercy 3 rue... 06043494 le champo 17 av... 01049059 nef chava 18 bd... 04387953
SELECT Telephone, Horaire FROM Prog, Cine
WHERE Prog.Nom_cine = Cine.Nom_cine AND Titre = 'Inception'
TELEPHONE HORAIRE --------- ------- 06043494 14h00 01049059 20h00
SELECT Acteur AS Personne FROM Film WHERE Titre = 'Marion'
UNION
SELECT MeS AS Personne FROM Film WHERE Titre = 'Marion'
SELECT F2.Titre , F2.MeS, F2.Acteur
FROM FILM F1, FILM F2
WHERE F1.Titre = F2.Titre AND F1.Acteur = 'M-F. Pisier'
Interprétations de F1 et F2:
SELECT Nom_Cine, Titre
FROM Prog
NOM_CINE TITRE --------- -------------------- ugc bercy Le discours d'un roi ugc bercy Le discours d'un roi ugc bercy Le discours d'un roi ugc bercy Inception le champo Le discours d'un roi le champo Inception
SELECT DISTINCT Nom_Cine, Titre
FROM Prog
NOM_CINE TITRE --------- -------------------- ugc bercy Le discours d'un roi ugc bercy Inception le champo Le discours d'un roi le champo Inception
SELECT 3*montant FROM Ventes;
SELECT SUBSTR('ABCDEFG',3,4) FROM DUAL; # (oracle): 'CDEF'
SELECT substring('Thomas' from 2 for 3); # (postgresql): 'hom'
TITRE ACTEUR ------------------------- ------ Rien à Declarer Boon La plage Canet Bienvenus chez les ch'tis Boon
SELECT Titre
FROM Films
WHERE LOWER(Titre) LIKE '%bien%'
OR Titre LIKE '%declarer%'
# LOWER: convertir en minuscule
TITRE ------------------------- Bienvenus chez les ch'tis
SELECT R.A FROM R,S,T WHERE R.A=S.A OR R.A=T.A
SELECT P.name FROM Personnes P WHERE P.age > 10 OR P.age <= 10
SELECT Nom_Cine, Titre
FROM Prog
ORDER BY Titre
NOM_CINE TITRE --------- -------------------- ugc bercy Inception le champo Inception ugc bercy Le discours d'un roi ugc bercy Le discours d'un roi ugc bercy Le discours d'un roi le champo Le discours d'un roi
SELECT Nom_Cine, Titre
FROM Prog
ORDER BY Titre DESC,
Nom_Cine ASC
NOM_CINE TITRE --------- -------------------- le champo Le discours d'un roi ugc bercy Le discours d'un roi ugc bercy Le discours d'un roi ugc bercy Le discours d'un roi le champo Inception ugc bercy Inception
ALL
pour garder les doublons
SELECT Acteur AS Personne FROM Film WHERE Titre = 'Marion'
UNION SELECT MeS AS Personne FROM Film WHERE Titre = 'Marion'
SELECT Acteur AS Personne FROM Film WHERE Titre = 'Marion'
UNION ALL SELECT MeS AS Personne FROM Film WHERE Titre = 'Marion'
SELECT Titre FROM Film WHERE Acteur = 'M-F.
Pisier' INTERSECT SELECT Titre FROM Prog ORDER BY Titre
Les titres des films qui ne sont pas à l'affiche:
SELECT Titre FROM Film EXCEPT SELECT Titre FROM Prog
Remarque: MySQL supporte seulement UNION
. Certains SGBD
utilisent MINUS
au lieu de EXCEPT
.
SELECT Acteur FROM FILM WHERE Titre =
(SELECT Titre FROM FILM-DEB WHERE Acteur = 'M-F. Pisier')
FROM
SELECT Acteur FROM FILM,
(SELECT Titre FROM Film Where Acteur = 'M-F. Pisier') F2
WHERE Film.Titre = F2.titre
WHERE/HAVING
IN
sous-requête
vrai si la valeur apparaît dans le résultat de la
sous-requête
EXISTS
sous-requête
vrai si le résultat de la sous-requête contient au moins un
tuple
op ANY
sous-requête
vrai si il existe une valeur dans le résultat de la sous-requête qui
satisfait la comparaison
op ALL
sous-requête
vrai si toutes les valeurs dans le résultat de la sous-requête
satisfont la comparaison
op
∈ {=,<,>, < =, > = ≠ }
NOT IN, NOT EXISTS
SELECT DISTINCT Titre FROM FILM
WHERE MeS IN (SELECT Acteur FROM FILM)
SELECT DISTINCT F1.Titre FROM FILM F1
WHERE EXISTS (SELECT F2.MeS FROM FILM F2
WHERE F1.Titre=F2.Titre AND NOT F1.MeS=F2.MeS)
ALL
SELECT DISTINCT Titre FROM PROG
WHERE Nom_Cine='UGC' AND
Horaire > ALL (SELECT Horaire FROM PROG WHERE Nom_Cine='Trianon')
ANY
SELECT Telephone FROM CINE AS C1
WHERE 23 < ANY ( SELECT Horaire FROM PROG
WHERE C1.Nom_Cine=PROG.Nom_Cine)
SELECT R.a,S.b
FROM R,S
SELECT R.a,S.b
FROM R,S
WHERE R.c=S.c
(INNER) JOIN
LEFT/RIGHT/FULL(OUTER)
JOIN
CROSS JOIN
JOIN
... ON
: le plus général,
condition quelconque (pas forcément equi-jointure), colonnes non
fusionnées.
JOIN
... USING
: jointure naturelle
restreinte aux attributs listées, colonnes fusionnées.
NATURAL JOIN
... : jointure naturelle sur toutes les
colonnes de même nom.
SELECT F1.Titre, F2.Acteur FROM FILM F1
INNER JOIN FILM F2 ON F1.Titre = F2.Titre
WHERE F1.Acteur = 'M-F. Pisier'
Le mot-clé INNER est facultatif : lorsque l'on écrit une
jointure sans en préciser le type(JOIN) c'est bien
INNER JOIN qui est calculé.
SELECT Film.Titre, Pers.nom, Pers.taille
FROM Film JOIN Programme Prog ON Film.Titre = Programme.Titre
JOIN Personne Pers ON Film.acteur = Pers.nom
SELECT F1.Titre, F1.Acteur, F2.Acteur, F3.Acteur
FROM FILM F1 JOIN FILM F2 ON F1.Titre = F2.Titre
JOIN FILM F3 ON F1.Titre = F3.Titre
WHERE F1.Acteur != F2.Acteur AND F1.Acteur != F3.Acteur
SELECT Nom_Cine,Film.Titre, Horaire FROM Film NATURAL JOIN Prog
WHERE Acteur = 'M.Freeman'
Jointure naturelle sur tous les attributs communs.
On peut restreindre la jointure naturelle à un sous ensemble
(attr_a,
attr_b, …,
attr_c)
des attributs communs avec la syntaxe:
# préciser les attributs d'une jointure naturelle est recommandé
# (par ex: le schéma risque de changer par la suite)
SELECT attr_a, attr_b, nom_table1.attr1... FROM nom_table1
INNER JOIN nom_table2 USING(attr_a,attr_b,...,attr_c)
SELECT attr1, attr2,... FROM nom_table1
LEFT OUTER JOIN nom_table2 USING(attr_a,attr_b,...,attr_c)
Permet d'afficher additionnellement les lignes de la table gauche (à
gauche du mot clé JOIN) qui n'ont pas de ligne correspondante à droite
pour la jointure, en complétant par des NULL à droite.
RIGHT OUTER JOIN
: affiche les lignes de la table
droite sans correspondance
FULL OUTER JOIN
: affiche les lignes des tables
gauche ou droite sans correspondance
TITRE ID_ACT PERSONNAGE ------------------------- ------- --------------- It's a Wonderful Life 35 George Bailey It's a Wonderful Life Mary Bailey It's a Wonderful Life 36 Clarence Odbody Rear Window 35 LB Jeffries The Shawshank Redemption 40 red
ID NOM PRENOM -- -------- ------ 35 Stewart James 40 Freeman Morgan 50 Serrault Michel
SELECT titre, personnage, nom FROM roles LEFT OUTER JOIN acteurs ON id_act=id;
TITRE PERSONNAGE NOM ------------------------- --------------- ------- Rear Window LB Jeffries Stewart It's a Wonderful Life George Bailey Stewart The Shawshank Redemption red Freeman It's a Wonderful Life Mary Bailey It's a Wonderful Life Clarence Odbody
TITRE ID_ACT PERSONNAGE ------------------------- ------- --------------- It's a Wonderful Life 35 George Bailey It's a Wonderful Life Mary Bailey It's a Wonderful Life 36 Clarence Odbody Rear Window 35 LB Jeffries The Shawshank Redemption 40 red
ID NOM PRENOM -- -------- ------ 35 Stewart James 40 Freeman Morgan 50 Serrault Michel
SELECT titre, personnage, nom FROM roles FULL OUTER JOIN acteurs ON id_act=id;
TITRE PERSONNAGE NOM ------------------------- --------------- ------- It's a Wonderful Life George Bailey Stewart <- in both Rear Window LB Jeffries Stewart <- in both The Shawshank Redemption red Freeman <- in both It's a Wonderful Life Mary Bailey <- in LEFT OUTTER JOIN It's a Wonderful Life Clarence Odbody <- in LEFT OUTTER JOIN Serrault <- in RIGHT OUTTER JOIN
COUNT()
: cardinalité du multiensemble
SUM()
: somme
MAX/MIN()
: valeur max/min
AVG()
: moyenne
TITRE ACTEUR ------------------------- --------- Rien à Declarer Boon <-- Brice de Nice Cornillac La vie de Chantier Boon <-- Ensemble c'est tout Canet Mon Idole Canet The dark knight rises Cotillard Les petits mouchoirs Cotillard La plage Canet Inception Cotillard Bienvenus chez les ch'tis Boon <--
SELECT acteur, COUNT(*)
FROM film GROUP BY acteur
ACTEUR COUNT(*) -------- -------- Canet 3 Cotillard 3 --> Boon 3 Cornillac 1
GROUP BY
: 1
groupe=table entière
GROUP BY
ne peuvent apparaître
dans SELECT
qu'à l'intérieur d'une fonction
d'agrégation
TITRE ACTEUR QT ------------------- -------- -- Rien à Declarer Boon 2 Brice de Nice Cornillac 5 La vie de Chantier Boon 7 Ensemble c'est tout Canet 2 Mon Idole Canet 3
SELECT COUNT(*) c, SUM(QT) s FROM film
c | s --+-- 5 | 19
SELECT SUBSTR(MAX(Titre),0,4) mx,
SUM(QT)/COUNT(*) s
FROM t WHERE Titre>'L'
mx | s ----+--- Rie | 4
FROM
WHERE
GROUP BY
HAVING
SELECT
ORDER BY
SELECT acteur, nomrealisateur, COUNT(*) NB
FROM film
WHERE acteur < 'D'
GROUP BY acteur, nomrealisateur
ORDER BY NB
TITRE ACTEUR NOMREALISATEUR ------------------------- -------- --------------- Les petits mouchoirs Cotillard Canet La plage Canet Boyle Mon Idole Canet Canet The dark knight rises Cotillard Nolan La vie de Chantier Boon Boon Brice de Nice Dujardin Dujardin Ensemble c'est tout Canet Canet Gran Torino Eastwood Eastwood Inception Cotillard Nolan Brice de Nice Cornillac Dujardin Rien à Declarer Boon Boon Bienvenus chez les ch'tis Boon Boon
COUNT(*)
retourne le nombre de lignes.
COUNT(a)
retourne le nombre de lignes non nulles sur
colonne a.
COUNT(DISTINCT a)
retourne le nombre de valeurs
distinctes sur la colonne a.
titre | acteur | nomrealisateur ----------------------+-----------+--------------- Green Book | Mortensen | Farrelly Seigneur des Anneaux | Mortensen | Jackson Coda | Jones | Heder Nomadland | |Zhao
SELECT COUNT(*) A,
COUNT(acteur) B,
COUNT(DISTINCT acteur) C
FROM film
WHERE Titre != 'Coda'
a | b | c --+---+--- 3 | 2 | 1
SUM(DISTINCT a)
,
AVG(DISTINCT a)
.
ACTEUR NB_FILMS -------- -------- Canet 3 Cotillard 3 Boon 3 Cornillac 1
NB_MAX NB_MOY ------ ------ 3 2.5
HAVING
permet de ne garder que les groupes satisfaisant
une condition:
SELECT acteur, COUNT(*) NB
FROM film
GROUP BY acteur
HAVING COUNT(*) > 2
ACTEUR NB -------- -- Canet 3 Cotillard 3 Boon 3
SELECT ... <-- évalué une fois par groupe (pas par ligne) FROM ... GROUP BY A_1 HAVING ... <-- évalué une fois par groupe (pas par ligne)
A_1 | A_2 | ... ---- + ---- + --- ... | ... | ... Le regroupement ---- + ---- + --- partitionne les bindings the x_i group --> x_i | y_i1 | ... de lignes : the x_i group --> x_i | y_i2 | ... - il n'y a pas de ---- + ---- + --- groupe vide the x_j group --> x_j | y_j1 | ... - chaque ligne the x_j group --> x_j | y_j2 | ... appartient à ---- + ---- + --- exactement un groupe ... | ... | ...
agg
(comme fold en programmation
fonctionnelle): on initialise un accumulateur à la valeur
zagg.
Aggregate agg | ∅agg | zagg | ⊕agg(a, x) |
---|---|---|---|
COUNT | 0 | 0 | a + 1 |
SUM | NULL | 0 | a + x |
AVG | NULL | <0, 0> | <a.1 + x, a.2 + 1> |
MAX | NULL | −∞ | max2(a, x) |
MIN | NULL | +∞ | min2(a, x) |
bool_and | NULL | true | a ∧ x |
bool_or | NULL | false | a ∨ x |
... | ... | ... | ... |
SELECT a, b, count(*), max(c)
FROM t GROUP BY a, b
# nothing special there
SELECT a, count(*)
FROM t
GROUP BY a, b
# sometimes it makes sense not to display b
SELECT a, sum(a), max(b+d)
FROM t
GROUP BY a
/* we can group *and* aggregate on a,
though it seldom makes sense */
SELECT a, b, sum(a)
FROM t
GROUP BY a
/* Incorrect query:
b is not a group by expression */
SELECT SUM(a) + SUM(b) c1, SUM(a+b) c2 FROM t;
SELECT a FROM t; # la colonne nommée a
SELECT 'a'; # constant string 'a'
CREATE TABLE "ma table" ("select" int); # identificateur entre guillemets
SELECT "select" from "ma table"; # faisable mais à éviter.
SELECT Titre FROM Film WHERE Acteur = 'O”Brien'; # cherche O'Brien
CREATE SCHEMA mon_schema;
CREATE TABLE mon_schema.t(id int) # voir: base.schema.table
SELECT a FROM mon_schema.t;
CREATE SCHEMA mon_schema2;
CREATE TABLE mon_schema2.t(id int) # valide car pas dans le même schéma
# DROP SCHEMA mon_schema CASCADE; # pour effacer un schéma non-vide
SET search_path TO mon_schema, mon_schema2, public;
SHOW search_path; # SELECT * FROM t utilisera la table dans mon_schema
search_path -------------------------------- mon_schema, mon_schema2, public;
CREATE SEQUENCE serie INCREMENT BY 100 START 101;
SELECT nextval('serie'); # 101
SELECT currval('serie'); # le résultat du dernier nextval: ici, 101
Outils similaires sous Oracle, MariaDB, MySQL, SQL Server…
CREATE TABLE t ( a SERIAL, b string );
# revient à
CREATE SEQUENCE t_a_seq;
CREATE TABLE t ( a NOT NULL DEFAULT nextval('t_a_seq'), b string );
SELECT country FROM cities GROUP BY city;
# valid if city is PK.
# Or more generally FD city -> country
# Optional extensions of standard
cities(id, city, country) ...
FOREIGN KEY REFERENCES (cities.country)
# FK referencing a non unique column!
# Non standard
SELECT a AS bbb FROM t GROUP BY bbb;