Présentation de SQL. A. Terlutte. December 11, 2006



Documents pareils
Langage SQL : créer et interroger une base

Le langage SQL (première partie) c Olivier Caron

Le Langage De Description De Données(LDD)

COMMANDES SQL... 2 COMMANDES DE DEFINITION DE DONNEES... 2

Bases de données et sites WEB Licence d informatique LI345

Bases de Données relationnelles et leurs systèmes de Gestion

1. Qu'est-ce que SQL? La maintenance des bases de données Les manipulations des bases de données... 5

Langage propre à Oracle basé sur ADA. Offre une extension procédurale à SQL

SQL Historique

TP Contraintes - Triggers

Création et Gestion des tables

Le langage SQL pour Oracle - partie 1 : SQL comme LDD

Cours Bases de données 2ème année IUT

Olivier Mondet

Plan. Bases de Données. Sources des transparents. Bases de SQL. L3 Info. Chapitre 4 : SQL LDD Le langage de manipulation de données : LMD

Langage SQL (1) 4 septembre IUT Orléans. Introduction Le langage SQL : données Le langage SQL : requêtes

Cours Bases de données 2ème année IUT

Introduction au Système de Gestion de Base de Données et aux Base de Données

Introduction aux Bases de Données 2004/2005

ECR_DESCRIPTION CHAR(80), ECR_MONTANT NUMBER(10,2) NOT NULL, ECR_SENS CHAR(1) NOT NULL) ;

CREATION WEB DYNAMIQUE

SGBDR. Systèmes de Gestion de Bases de Données (Relationnelles)

Le Langage SQL version Oracle

14/04/2014. un ensemble d'informations sur un sujet : exhaustif, non redondant, structuré, persistant. Gaëlle PERRIN SID2 Grenoble.

FileMaker 13. Guide de référence SQL

Le langage SQL Rappels

Notes de cours : bases de données distribuées et repliquées

PHP 5. La base de données MySql. A. Belaïd 1

OpenPaaS Le réseau social d'entreprise

Auto-évaluation Oracle: cours de base

Module Administration BD Chapitre 1 : Surcouche procédurale dans les SGBDS

SQL. Oracle. pour. 4 e édition. Christian Soutou Avec la participation d Olivier Teste

Bases de données relationnelles

Les Triggers SQL. Didier DONSEZ. Université de Valenciennes Institut des Sciences et Techniques de Valenciennes

Licence de MIDO - 3ème année Spécialités Informatique et Mathématiques Appliquées

MySQL / SQL EXEMPLES

Exercices sur SQL server 2000

Gestion des utilisateurs et de leurs droits

Historisation des données

Partie 0 : Gestion des tablespace et des utilisateurs... 3

Gestion des transactions et accès concurrents dans les bases de données relationnelles

Initiation à SQL. Le langage de communication avec une base de données relationnelles. Application avec PostgreSQL. Nathalie Camelin 2011/2012

Pour les débutants. langage de définition des données

LE LANGAGE SQL2 1. INTRODUCTION

Bases de données Oracle Virtual Private Database (VPD) pour la gestion des utilisateurs d applications

Structured Query Language

Table des matières PRESENTATION DU LANGAGE DS2 ET DE SES APPLICATIONS. Introduction

SQL sous SqlServer OLIVIER D. DEHECQ Olivier 0

TP3 : Creation de tables 1 seance

1 Introduction et installation

Les BASES de DONNEES dans WampServer

Administration des bases de données. Jean-Yves Antoine

Présentation Windows Azure Hadoop Big Data - BI

Cours SQL. Base du langage SQL et des bases de données

Plan Général Prévisionnel (1/2) (non contractuel) Internet et Outils L1/IO S2-IO2 Bases de données: Jointures, Transactions

Intégrité des données

Encryptions, compression et partitionnement des données

PHP et mysql. Code: php_mysql. Olivier Clavel - Daniel K. Schneider - Patrick Jermann - Vivian Synteta Version: 0.9 (modifié le 13/3/01 par VS)

1. LA GESTION DES BASES DE DONNEES RELATIONNELLES

NFA 008. Introduction à NoSQL et MongoDB 25/05/2013

ORACLE 10G DISTRIBUTION ET REPLICATION. Distribution de données avec Oracle. G. Mopolo-Moké prof. Associé UNSA 2009/ 2010

Les transactions 1/46. I même en cas de panne logicielle ou matérielle. I Concept de transaction. I Gestion de la concurrence : les solutions

Résumé S Q L. Auteur: Alexandre PATIN Edition: 22 février alexandre.patin@free.fr URL :

ISC Système d Information Architecture et Administration d un SGBD Compléments SQL

I. MySQL : Serveur et SGBD

1. Base de données SQLite

A QUOI SERVENT LES BASES DE DONNÉES?

A QUOI SERVENT LES BASES DE DONNÉES?

Comprendre les bases de données

Introduction à MATLAB R

Paginer les données côté serveur, mettre en cache côté client

Bases de données et sites WEB

Intégrité sémantique dans les bases de données relationnelles

Cours: Administration d'une Base de Données

SQL Server 2000, Analysis Services et DTS

Les déclencheurs. Version 1.0. Grégory CASANOVA

1/ Présentation de SQL Server :

Les bases fondamentales du langage Transact SQL

Partie I : Créer la base de données. Année universitaire 2008/2009 Master 1 SIIO Projet Introduction au Décisionnel, Oracle

Système de Gestion de Bases de Données Relationnelles. MySQL. Youssef CHAHIR

Vincent Augusto

PHP. PHP et bases de données

BASES DE DONNEES TP POSTGRESQL

Mysql avec EasyPhp. 1 er mars 2006

Gestion de base de données

Optimisation SQL. Quelques règles de bases

Le langage procédural PL-PGSQL

SQL Server Cyril Gruau. 11 février 2003

Compétences Business Objects

Optimisations des SGBDR. Étude de cas : MySQL

Les bases de données

TD : Requêtes SQL (BDR.TD2-1) INSA 3IF

Devoir Data WareHouse

LES TYPES DE DONNÉES DU LANGAGE PASCAL

GUIDE D INSTALLATION DE L APPLICATION GECOL SUR

Support de Cours REQUÊTES TRANSACT-SQL DANS MICROSOFT SQL SERVER Stéphane N GUESSAN Groupe Pigier Abidjan Version 1.

Configurer la supervision pour une base MS SQL Server Viadéis Services

Présentation du langage et premières fonctions

Transcription:

Présentation de SQL A. Terlutte December 11, 2006 Ce document est un mémento simplifié des principales commandes du Structured Query Language. Il ne se veut pas complet ; cela serait inutilement complexe (la documentation PostgreSQL contient 1500 pages). N hésitez pas à vous reporter à l aide en ligne, aux différents manuels ou à internet... Toutes les commandes données dans ce mémento sont des formes simplifiées des commandes SQL. Pour avoir la syntaxe complète, reportez-vous aux manuels de références. Différents manuels de référence de PostgreSQL sont téléchargeables à partir de l adresse suivante : http://www.postgresql.org/docs/manuals/ Les commandes PSQL sont données en annexe. Préambule Prenez l habitude de nommer correctement vos identifiants même si les noms sont longs. Cela permet de savoir à quoi correspond un identifiant... même si c est plus long à écrire! villes_codepostal_index chercheurs_nochercheur_pk reservations_refexpose_fk Par contre, à l intérieur de certaines commandes, vous pourrez utiliser des alias. 1 INTERROGATION Toute la puissance d interrogation du langage SQL est contenue dans une seule commande : la commande select SELECT [ ALL DISTINCT ] * expression [ AS AliasColonne ][,...] [ FROM ClauseFrom [,...]] [ WHERE condition ], [ GROUP BY expression [,...]] [ HAVING condition [,...]] [ { UNION INTERSECT EXCEPT } [ ALL ] select ] [ ORDER BY expression [ ASC DESC ][,...]] où ClauseFrom peut être : NomTable [ [ AS ] AliasTable [ ( AliasColonne [,...] ) ] ] ( select ) [ AS ] AliasTable [ ( AliasColonne [,...] ) ] ClauseFrom [ NATURAL ] TypeJointure ClauseFrom [ ON ConditionJointure ] L alias de colonne peut servir dans les sections GROUP BY ou ORDER BY mais pas dans les autres expressions de calcul ou de conditions. La section 2 développe quelques possibilités offertes pour écrire des expressions SQL. Les conditions sont des expressions à résultat booléen ; reportez-vous aussi à la section 2 pour les conditions. 1

Les expressions dans les colonnes peuvent utiliser les fonctions AVG(expression ), MIN(expression ), MAX(expression ), SUM(expression ), COUNT(expression ). On peut préciser ALL ou DISTINCT dans la fonction (qui ne tient compte que des valeurs non nulles). La fonction Count peut ne pas s appliquer à un champ : COUNT(*). Si on ouvre deux tables simultanément, le résultat de la sélection est le produit (cartésien) des deux tables. Exécutez, pour vérifier cette assertion, la commande select count(*) from salles; select count(*) from exposes; select count(*) from exposes,salles; La jointure s obtient par la sélection d un attribut qui est commun aux deux tables. select codeexpose,codesalle from exposes,salles where codesalle=refsalle; Pour éviter toute ambiguïté, lorsque plusieurs tables sont ouvertes, il faut préciser le nom de la table avant le nom du champ select exposes.codeexpose,salles.codesalle from exposes,salles where salles.codesalle=exposes.refsalle; On peut utiliser des alias pour les noms de tables select ex.codeexpose,sl.codesalle from exposes as ex,salles as sl where sl.codesalle=ex.refsalle; On peut aussi relier deux tables par l opérateur JOIN select ex.codeexpose,sl.codesalle from exposes as ex join salles as sl on sl.codesalle=ex.refsalle; Si les champs de la jointure portent le même nom dans les deux tables, on peut simplifier l écriture avec NATURAL JOIN ; la jointure s effectue alors sur tous les champs de même nom. Sur plus de deux tables, la technique est similaire select co.nomeco, au.nomeco from ((economistes as co left join exposes as ex on co.codeeco=ex.refconf) join reservations as re on ex.codeexpose=re.refexpose) join economistes as au on re.refeco=au.codeeco; L opérateur LEFT JOIN permet de relier deux tables en faisant apparaître tous les éléments d une table même si la condition de jointure n est pas satisfaite. select co.nomeco, ex.titre from economistes as co left join exposes as ex on co.codeeco=ex.refconf); fera apparaître tous les économistes même s ils ne font pas d exposés. Il existe évidemment un opérateur RIGHT JOIN. Vous remarquerez aussi que la syntaxe de ClauseFrom autorise l utilisation d une autre clause select. On peut ainsi utiliser le résultat d une requête comme étant une nouvelle table ; il faut obligatoirement utiliser un alias pour cette sous-requête. December 11, 2006 à 22h02 2/39 December 11, 2006 à 22h02

Une sous-requête peut aussi être utilisée dans une condition ; dans ce cas, l alias n est pas utilisé. Dans une condition, la sous-requête peut apparaître là où une liste aurait pu être utilisée. Il s agit des conditions utilisant les opérateurs IN, > ALL, >= ALL,... > ANY,... ; la sous-requête doit fournir une liste, donc une seule colonne. Une sous-requête peut aussi apparaître, lorsqu elle fournit une valeur unique, avec des opérateurs classiques de comparaison =, >... Avec l opérateur EXISTS, une ligne de la requête principale sera affichée si la sous-requête est non vide. Dans la sous-requête, il y a souvent une référence à la requête principale. Dans le cas des opérations algébriques sur les requêtes (union, intersection, différence), il est nécessaire que les différentes requêtes aient la même structure (même nombre de colonnes et même type de données). 2 FONCTIONS ET EXPRESSIONS PostgreSQL offre de nombreuses fonctions. La plupart des fonctions que l on rencontre dans les langages de programmation sont disponibles ; si vous avez besoin d une opération ou d un calcul sur certains types de données, consultez l adresse suivante pour vérifier s il n existe pas déjà : http://www.postgresql.org/docs/8.1/interactive/functions.html Voici quelques fonctions ou opérateurs disponibles en SQL. 2.1 expressions arithmétiques Les opérateurs arithmétiques habituels sont disponibles mais SQL en propose d autres % modulo 11%3 vaut 2 ˆ exposant 4ˆ3 vaut 4*4*4=64 / racine carrée / 9 vaut 3... Toutes les fonctions classiques existent et de nombreuses autres... 2.2 expressions caractères L opérateur effectue la concaténation de chaînes de caractères. Toutes les fonctions classiques existent : length(chaîne ), lower(chaîne ), substring(chaîne [from PositionDépart ] [for NombreCaractères ] ), position(souschaîne in chaîne )... et de nombreuses autres, avec des syntaxes particulières. 2.3 expressions dates Les opérateurs + et - permettent aussi d ajouter ou de soustraire des dates, des horaires et des entiers... Reportez-vous aux documentations pour connaître les différentes possibilités. Les dates devraient être, par défaut, sous la forme année-mois-jour heure:minute:seconde mais la configuration peut spécifier d autres formats. Dans une expression, une date ou un horaire peuvent souvent être écrites directement entre apostrophes (exemple 2006-11-27 ) mais il faut parfois préciser le type (exemple date 2006-11-27 ) Les fonctions CURRENT_DATE et CURRENT_TIME fournissent la date et l heure actuelles. La fonction EXTRACT permet d extraire toutes sortes d informations contenues dans une date ou d un horaire (l année, les minutes,... mais aussi le trimestre, le numéro de semaine...). Interval présente une quantité dans une certaine unité. December 11, 2006 à 22h02 3/39 December 11, 2006 à 22h02

Voici quelques exemples d expressions valides : date 2001-09-28 + interval 1 hour vaut 2001-09-28 01:00:00 date 2001-09-28 + time 03:00 vaut 2001-09-28 03:00:00 timestamp 2001-09-28 01:00 + interval 23 hours vaut 2001-09-29 00:00:00 date 2001-10-01 - date 2001-09-28 vaut integer 3 date 2001-10-01 - integer 7 vaut date 2001-09-24 900 * interval 1 second vaut interval 00:15:00 2.4 expressions booléennes On peut tester si une expression, souvent une colonne, est nulle expression IS NULL expression IS NOT NULL Les conditions peuvent utiliser les opérateurs habituels (=, <> etc...) mais aussi expression BETWEEN expression AND expression expression IS [ NOT ] NULL expression [ NOT ] LIKE modèle avec les jokers % pour une chaîne quelconque et _ pour un caractère expression [ NOT ] IN (liste selection ) Une structure CASE permet de faire un calcul alternatif CASE WHEN condition THEN expression WHEN condition THEN expression... ELSE expression END 3 CREATION D UTILISATEURS 3.1 Création de la base à partir du terminal CREATEUSER options NomUtilisateur Les options principales sont - -createdb l utilisateur aura le droit de créer des bases de données - -no-createdb l utilisateur n aura pas le droit de créer des bases de données - -createrole l utilisateur aura le droit de créer des utilisateurs - -no-createrole l utilisateur n aura pas le droit de créer des utilisateurs - -pwprompt l utilisateur aura à utiliser un mot de passe - -host hote vous précisez la machine hote sur laquelle se trouve le serveur. - -username utilisateur vous précisez le nom de l utilisateur qui crée ces nouveaux utilisateurs. Il existe des abréviations -d pour - -createdb ou -h pour - -host ; reportez-vous aux documentations pour les connaître. 3.2 Création d un utilisateur ou d un groupe CREATE USER NomUtilisateur [ WITH ] options est maintenant un alias de la commande CREATE ROLE NomUtilisateur [ WITH ] options Les options principales sont createdb l utilisateur aura le droit de créer des bases de données December 11, 2006 à 22h02 4/39 December 11, 2006 à 22h02

nocreatedb l utilisateur n aura pas le droit de créer des bases de données createrole l utilisateur aura le droit de créer d autres utilisateurs. nocreaterole l utilisateur n aura pas le droit de créer d utilisateur. login indique que l utilisateur aura le droit de se connecter. nologin indique que l utilisateur n aura pas le droit de se connecter ; utile pour créer un compte d administrateur. C est l option par défaut. in role NomGroupe crée l utilisateur et le place dans un groupe. 4 CREATION DE BASE Une fois la base conçue, c est à dire une fois le MCD et le MLD conçus, quelques commandes sont nécessaires pour créer d abord la base, puis chacune des tables. 4.1 Création de la base à partir du terminal La commande createdb permet de créer une base sans avoir à lancer le terminal postgresql par la commande psql. CREATEDB - -host hote - -username utilisateur NomBase La documentation de postgresql renvoie vers les explications de la commande CREATE DATABASE mais il est plus logique de créer une base de données sans être connecté à une autre base. 4.2 Création de la base Lorsque vous êtes dans un terminal postgresql, vous pouvez créer une nouvelle base par la commande CREATE DATABASE mais cela signifie que vous êtes déjà connecté à une base... CREATE DATABASE NomBase [ [ WITH ] [ OWNER [=] Proprétaire ] [ TEMPLATE [=] BaseModèle ] [ ENCODING [=] encodage ] ] Le nom de la base ne doit pas exister. Par défaut, le créateur est propriétaire. La commande PSQL \c permet de se connecter à une base, donc de changer de base de travail. 4.3 Renommage de la base ALTER DATABASE NomBase RENAME TO NouveauNom 4.4 Suppression de la base DROP DATABASE NomBase 5 STRUCTURE DE TABLE 5.1 Types de données Les types les plus courants sont : VARCHAR(longueur ) ou CHARACTER VARYING(longueur ) INTEGER REAL NUMERIC(LongueurTotale,NombreDécimales ) DATE December 11, 2006 à 22h02 5/39 December 11, 2006 à 22h02

BOOLEAN... Mais voici la liste quasi-complète des types SQL (tout au moins en PostgreSQL 8.1.4) : Name Aliases Description bigint int8 signed eight-byte integer bigserial serial8 autoincrementing eight-byte integer bit [ (n) ] fixed-length bit string bit varying [ (n) ] varbit variable-length bit string boolean bool logical Boolean (true/false) box rectangular box in the plane bytea binary data ("byte array") character varying [ (n) ] varchar [ (n) ] variable-length character string character [ (n) ] char [ (n) ] fixed-length character string cidr IPv4 or IPv6 network address circle circle in the plane date calendar date (year, month, day) double precision float8 double precision floating-point number inet IPv4 or IPv6 host address integer int, int4 signed four-byte integer -2147483648 to +2147483647 interval [ (p) ] time span line infinite line in the plane lseg line segment in the plane macaddr MAC address money currency amount numeric [ (p, s) ] decimal [ (p, s) ] exact numeric of selectable precision path geometric path in the plane point geometric point in the plane polygon closed geometric path in the plane real float4 single precision floating-point number smallint int2 signed two-byte integer -32768 to +32767 serial serial4 autoincrementing four-byte integer text variable-length character string time [ (p) ] [ without time zone ] time of day time [ (p) ] with time zone timetz time of day, including time zone timestamp [ (p) ] [ without time zone ] date and time timestamp [ (p) ] with time zone timestamptz date and time, including time zone La time zone spécifie le décalage horaire. Le type money est déconseillé ; le type numeric est conseillé pour le remplacer. Les types serial et bigserial sont des types autoincrémentés, tout à fait adaptés aux identifiants. Définir une colonne de ce type définit une séquence qui servira pour la génération des valeurs insérées dans cette colonne. Il faudra utiliser le mot clé DEFAULT lors des insertions dans la table. La séquence sera suivie indépendamment des suppressions dans la table ou des insertions n utilisant pas DEFAULT. Ceci peut mener à des doublons et la déclaration d une colonne de type serial ne dispense pas de la contrainte UNIQUE. 5.2 Création de table La création d une table nécessite la définition du nom de la table et la définition des colonnes qui la composent. Chaque colonne a un nom et un type de données. De plus, il est possible de définir certaines contraintes d intégrité de la table : structure : la valeur de la clé primaire est unique et toujours définie, domaine : les valeurs prises par un attribut doivent vérifier des contraintes, December 11, 2006 à 22h02 6/39 December 11, 2006 à 22h02

référence : les valeurs d une clé étrangère doivent correspondre à des valeurs existantes dans la table d origine. La vérification de certaines contraintes peut être demandée dès la création de la table. Elle sera assurée par le système. CREATE TABLE NomTable ( { NomColonne Type [ DEFAULT expression ] [ ContrainteColonne [... ] ] ContrainteTable } [,... ] ) où ContrainteColonne peut être : [ CONSTRAINT NomContrainte ] { NOT NULL NULL UNIQUE PRIMARY KEY CHECK (expression ) REFERENCES TableReliée [ ( ColonneReliée ) ] } et ContrainteTable peut être : [ CONSTRAINT NomContrainte ] { UNIQUE ( NomColonne [,... ] ) PRIMARY KEY ( NomColonne [,... ] ) CHECK ( expression ) FOREIGN KEY ( NomColonne [,... ] ) REFERENCES TableReliée [ ( ColonneReliée [,... ] ) ] } D après la syntaxe, le nom de contrainte est facultatif. Mais il est préférable de nommer toutes les contraintes ; dans certains cas, c est même obligatoire (quand plusieurs contraintes portent sur une même colonne). 5.3 Modifications de table ALTER TABLE [ ONLY ] NomTable ADD [ COLUMN ] NomColonne type [ ContrainteColonne [... ] ] ALTER TABLE [ ONLY ] NomTable DROP [ COLUMN ] NomColonne ALTER TABLE [ ONLY ] NomTable ALTER [ COLUMN ] NomColonne { SET DEFAULT expression DROP DEFAULT } ALTER TABLE [ ONLY ] NomTable ALTER [ COLUMN ] NomColonne { SET DROP } NOT NULL ALTER TABLE [ ONLY ] NomTable RENAME [ COLUMN ] NomColonne TO NouveauNomColonne ALTER TABLE NomTable RENAME TO NouveauNomTable ALTER TABLE [ ONLY ] NomTable December 11, 2006 à 22h02 7/39 December 11, 2006 à 22h02

ADD NouveauNomTable ALTER TABLE [ ONLY ] NomTable ADD ContrainteTable ALTER TABLE [ ONLY ] NomTable DROP CONSTRAINT ContrainteTable ALTER TABLE NomTable OWNER TO NouveauPropriétaire 5.4 Suppression de table DROP TABLE NomTable [,...] 5.5 Quelques exemples alter table chercheurs add constraint chercheurs_nochercheur_pk primary key (nochercheur); alter table parcelles add constraint parcelles_refsite_fk foreign key (refsite) references sites(nosite); alter table parcelles add constraint testlg check (longueur>largeur); 6 INDEXATION Les index accélèrent les recherches mais alourdissent la base. Si vous estimez qu un champ va être l objet de recherches fréquentes, il peut être judicieux de créer un index sur ce champ. Par exemple, PostgreSQL crée une table d index lorsque l utilisateur déclare une clé primaire. Les index servent évidemment principalement lors de la commande SELECT, pour les jointures... mais servent aussi pour les commandes UPDATE, DELETE... On peut aussi créer des index sur des expressions, en créer sur une partie de table... Il existe différents types d index (B-Tree, R-Tree, Hash, GiST) correspondant à différentes organisations dans les tables d index. Les B-Trees sont utilisés par défaut et correspondent aux utilisations les plus fréquentes, mais il faut savoir que d autres types sont possibles : pour une recherche en deux dimensions,... Les Hash index n ont d intérêt que pour une recherche avec un critère d égalité. Ils offrent des performances de recherche équivalentes à celles des B-Trees, mais leur taille et leur temps de construction sont meilleurs. Nous ne donnerons que l utilisation des B-Trees. La commande la plus simple pour construire une table d index est la suivante. CREATE INDEX NomIndex ON NomTable (NomChamp ) Si les recherches sont fréquentes, on peut aussi indexer sur une expression. CREATE INDEX NomIndex ON NomTable (expressions ); On peut aussi indexer sur plusieurs champs. December 11, 2006 à 22h02 8/39 December 11, 2006 à 22h02

CREATE INDEX test2_mm_idx ON test2 (major, minor); sera utile pour des recherches comme SELECT colonne FROM test2 WHERE major = constant AND minor = constant; Il peut être nécessaire de créer des index à entrées uniques. Il serait interdit d avoir deux lignes de la table ayant même clé, même valeur d index. CREATE UNIQUE INDEX NomIndex ON NomTable (NomColonne [,...]) ATTENTION : quand l utilisateur crée des contraintes primary key ou unique sur une table, PostgreSQL génère automatiquement des index uniques. Les créer par la commande create index dupliquerait les tables d index. Enfin on peut créer un index sur une partie de table si on est sûr que les recherches ne porteront que sur cette partie. CREATE INDEX NomIndex ON NomTable (NomChamp ) WHERE condition Cela diminue la taille de la table d index, accélère la recherche et la mise à jour. Si une recherche s effectue en dehors des valeurs de la table d index, celle-ci n est tout simplement pas utilisée. CREATE INDEX factures_montant_idx ON factures (montant) WHERE paye is not true; L index serait utilisé par postgresql même pour des requêtes n utilisant pas le montant comme SELECT nofacture FROM factures WHERE paye is not true AND nofacture like 2006* ; L exemple suivant illustre une méthode garantissant des lignes uniques sur une partie de la table, multiples sur le reste. CREATE TABLE tests ( subject text, target text, success boolean,... ); L index va permettre de garantir que pour les lignes successfull, la correspondance sujet/cible est unique. CREATE UNIQUE INDEX tests_success_constraint ON tests (subject, target) WHERE success; Dans les applications réelles, l utilisation de tables d index est une question majeure. Mais déterminer si un index va améliorer l accès à une table est un problème complexe. PostgreSQL préconise l emploi des commandes ANALYZE et EXPLAIN sur les données réelles. Lors de la création d une table avec les lignes qu elle contient, il est préférable d insérer d abord les lignes puis de créer les index plutôt que de mettre à jour un index à chaque insertion. December 11, 2006 à 22h02 9/39 December 11, 2006 à 22h02

7 CONTENU D UNE TABLE 7.1 Insertion de lignes INSERT INTO NomTable [ ( NomColonne [,...] ) ] { DEFAULT VALUES VALUES ( { expression DEFAULT } [,...] ) requête } Si aucune colonne n est spécifiée les valeurs sont affectées aux colonnes dans l ordre déterminée par la structure. Vous pouvez donc soit créer une ligne ayant les valeurs par défaut, soit créer une ligne en donnant explicitement les valeurs, soit remplir la table avec le résultat d une requête. On peut aussi remplir une table avec des données contenues dans un fichier. COPY NomTable FROM chemin/nomfichier copy essaitable from /Users/alain/Documents/basesdedonnees/donnees.txt ; Les données dans le fichier sont séparées par des tabulations, sans autres délimiteurs. 7.2 Modification de lignes UPDATE [ ONLY ] NomTable SET NomColonne = { expression DEFAULT } [,...] [ WHERE condition ] La mise à jour peut évidemment calculer une valeur à partir de la valeur actuellement dans la table. update parcelles set longueur=longueur-1 where noparcelle=1; 7.3 Suppression de lignes DELETE FROM [ ONLY ] NomTable [ WHERE condition ] Attention : la condition est facultative, mais sans condition, tous les enregistrements sont supprimés!!! 8 PRIVILÈGES Le propriétaire d une table peut attribuer aux autres utilisateurs, les droits (privilèges) d utilisation de la table. GRANT { { SELECT INSERT UPDATE DELETE } [,...] ALL [ PRIVILEGES ] } ON [ TABLE ] NomTable [,...] TO { NomUtilisateur GROUP NomGroupe PUBLIC } [,...] De même, il peut retirer les droits sur une table à ces utilisateurs. REVOKE [ GRANT OPTION FOR ] { { SELECT INSERT UPDATE DELETE } [,...] ALL [ PRIVILEGES ] } ON [ TABLE ] NomTable [,...] FROM { NomUtilisateur GROUP NomGroupe PUBLIC } [,...] December 11, 2006 à 22h02 10/39 December 11, 2006 à 22h02

Il existe aussi des droits ou privilèges pour une base de données (droit de création), pour des fonctions (droit d exécution),... GRANT { { CREATE TEMPORARY TEMP } [,...] ALL [ PRIVILEGES ] } ON DATABASE dbname [,...] TO { username GROUP groupname PUBLIC } [,...] [ WITH GRANT OPTION ] Expérimentation 1. 1. Concevez le MCD de la base filmo. Concevez le script de création de la base (avec le logiciel analysesi, par exemple). 2. Créez votre base filmo. Afin de nommer les bases avec une certaine organisation, faites suivre le nom de votre base par votre propre nom. Exemple : create database filmo_terlutte; 3. Créez les tables avec leurs clés primaires, clés étrangères et autres contraintes. 4. Ajoutez quelques éléments dans chacune des tables. 5. Vérifiez auprès de votre voisin le nom de sa base de données. Connectez-vous à sa base. Essayez de consulter les différentes tables. 6. Demandez qu il vous donne les droits de consulter et de modifier mais ni d ajouter, ni de supprimer des lignes dans ses tables. 7. Faites quelques modifications de lignes. 9 TRANSACTION Toutes les commandes qui agissent sur le contenu d une base sont dangereuses ; certaines sont irréversibles. Il est prudent de réaliser ses instructions à l intérieur d une transaction. Une transaction permet de regrouper une suite d instructions pour la considérer comme une instruction élementaire. Les transactions permettent aussi de gérer les conflits. Une transaction commence par l instruction START TRANSACTION ou par BEGIN et se termine par COMMIT si vous voulez valider la transaction ou ROLLBACK si vous voulez annuler la transaction. Expérimentation 2. December 11, 2006 à 22h02 11/39 December 11, 2006 à 22h02

1. Connectez-vous à votre base filmo 2. Commencez une transaction. 3. Ajoutez quelques éléments dans une des tables (la table rayons par exemple). 4. Affichez le contenu de la table. 5. Terminez la transaction par la commande Rollback. 6. Affichez de nouveau le contenu de la table. 7. Recommencez la transaction mais terminez par Commit. 8. Affichez le contenu de la table. 10 CONFLITS 10.1 Présentation des conflits possibles Pour comprendre comment les transactions permettent de gérer les conflits, regardons les différents cas d accès concurrents à une même information qui provoquent des conflits. Il faut imaginer deux personnes travaillant sur la même base de données. 10.1.1 Lecture inconsistante T 1 T 2 update enregistrement select enregistrement rollback Premier cas de conflit, l utilisateur T2 met à jour un enregistrement. L utilisateur T1 lit l enregistrement. Mais l utilisateur T2 annule sa modification. L utilisateur T1 a donc lu une information qui n a pas été validée. 10.1.2 Lecture non répétitive T 1 T 2 select enregistrement 1 (consultation) select enregistrement 2 (consultation) update enregistrement 1 update enregistrement 1 Deuxième cas de conflit, l utilisateur T1 consulte un enregistrement, puis un autre afin de savoir lequel modifier. Il choisit de modifier l enregistrement 1. December 11, 2006 à 22h02 12/39 December 11, 2006 à 22h02

Mais, après qu il ait lu les informations et avant qu il ne fasse sa modification, l utilisateur T2 modifie l enregistrement 1. L utilisateur T1 modifie donc un enregistrement qui n est pas celui qu il a lu ; peut-être même, l enregistrement ne vérifie plus les raisons pour lesquelles l utilisateur T1 l avait choisi. 10.1.3 Lignes fantômes T 1 T 2 select enregistrement 1 (sommation) select enregistrement 2 (sommation) select enregistrement 3 (sommation) select enregistrement 5 (sommation) select enregistrement 6 (sommation) update enregistrement 2 delete enregistrement 3 delete enregistrement 4 update enregistrement 5 insert enregistrement 6 Autre cas de conflit, l utilisateur T1 commence une consultation d une série d enregistrements dans le but de faire un calcul sur l ensemble de la série (par exemple, une sommation), Mais, pendant qu il effectue son parcours, l utilisateur T2 modifie des enregistrements : il en modifie, en supprime, en ajoute. Il est clair que l utilisateur T1 ne fera pas son calcul sur les enregistrements qui existaient au début du calcul. Au début du calcul, les enregistrements corrects sont les enregistrements 1, 2, 3, 4 et 5. Mais il ne verra pas l enregistrement 4 qui est supprimé entre temps et il verra l enregistrement 6 qui est ajouté ; de plus, l enregistrement 3 est supprimé et les enregistrements 2 et 5 sont modifiés. 10.2 Outils de gestion des conflits Pour assurer que l utilisateur T1 effectue des instructions cohérentes, il faut qu il puisse verrouiller les enregistrements sur lesquels il veut travailler. Une solution serait de verrouiller complètement la table, c est à dire d interdir l accès à cette table pendant qu on travaille dessus. Mais cela serait au dépend de l efficacité. Il existe donc différents niveaux de verrouillage. verrou partagé (shared lock) utilisé pour lire un enregistrement. Les autres utilisateurs peuvent lire l enregistrement et peuvent poser le même type de verrou sur cet enregistrement. Mais il ne peuvent pas poser un autre type de verrou. verrou exclusif (exclusive lock) utilisé pour modifier un enregistrement. Les autres utilisateurs ne peuvent pas lire l enregistrement et ne peuvent poser aucun verrou sur l enregistrement. verrou global (global lock) utilisé pour bloquer une série d enregistrements. Les autres utilisateurs ne peuvent pas lire la série d enregistrements et ne peuvent poser aucun verrou sur la série. 10.3 Solutions aux conflits L utilisation des verrous permet d apporter des solutions aux conflits. Il s agit de trouver le meilleur verrou à appliquer pour éviter un problème sans gêner abusivement les autres utilisateurs. December 11, 2006 à 22h02 13/39 December 11, 2006 à 22h02

10.3.1 Solution à la lecture inconsistante Pour éviter la lecture inconsistante, l utilisateur T2 devrait verrouiller l enregistrement qu il pense modifier afin qu aucun autre utilisateur ne risque de lire une information erronée. T 1 attente enregistrement... select enregistrement T 2 verrou exclusif sur enregistrement update enregistrement rollback En posant un verrou exclusif, l utilisateur T2 protège les autres utilisateurs contre des lectures inconsistantes. L enregistrement est libéré à la fin de la transaction. 10.3.2 Solution à la lecture non répétitive Vous pouvez vérifier que si l utilisateur T2 pose un verrou exclusif sur l enregistrement, l utilisateur T1 n est pas protégé contre la lecture non répétitive. Ici c est l utilisateur T1 qui doit se protéger contre ce problème. On voit donc que l utilisation des verrous constitue une stratégie que tous les utilisateurs doivent respecter. Si l utilisateur T1 veut garantir qu un enregistrement ne changera pas de valeur, il doit le verrouiller. Il peut le faire de telle façon que les autres puissent lire mais pas modifier l enregistrement. T 1 T 2 verrou partagé sur enregistrement 1 select enregistrement 1 verrou partagé sur enregistrement 2 select enregistrement 2 attente verrou exclusif sur enregistrement 1... update enregistrement 1 commit verrou exclusif sur enregistrement 1 update enregistrement 1 commit En posant un verrou partagé, l utilisateur T1 protège l accès à l enregistrement 1 ; il autorise la lecture de l enregistrement mais interdit sa modification. 10.3.3 Solution aux lignes fantômes Dans le cas d un traitement qui nécessite la cohérence d une série d enregistrements, l utilisateur doit verrouiller la totalité de la série. December 11, 2006 à 22h02 14/39 December 11, 2006 à 22h02

T 1 T 2 verrou global select enregistrement 1 (sommation) select enregistrement 2 (sommation) select enregistrement 3 (sommation) attente verrou exclusif sur enregistrement 2... select enregistrement 4 (sommation) select enregistrement 5 (sommation) verrou exclusif sur enregistrement 2 update enregistrement 2 verrou exclusif sur enregistrement 3 delete enregistrement 3... L utilisateur T1 pose un verrou sur la totalité de la table ; aucun autre utilisateur ne peut modifier les enregistrements concernés. 10.4 Modes de transaction Le langage SQL propose quatre modes d isolation qui permettent d éviter les cas de conflits que nous venons de voir. La théorie définit READ UNCOMMITTED aucun verrou READ COMMITTED toute transaction qui désire modifier un enregistrement acquiert un verrou exclusif sur celui-ci, jusqu à la fin de ladite transaction. REPEATABLE READ la transaction acquiert des verrous partagés sur tous les enregistrements lus. SERIALIZABLE verrou global (souvent par blocs d enregistrements). niveau d isolation lecture inconsistante lecture non répétitive lignes fantômes read uncommitted possible possible possible read committed impossible possible possible repeatable read impossible impossible possible serializable impossible impossible impossible Evidemment, le mode serializable est le plus protégé, mais il interdit les accès concurrents. PostgreSQL n utilise que deux niveaux d isolation et les traite d une façon particulière. READ COMMITTED La transaction voit des copies de la base prises au début des requêtes. Ces copies contiennent les modifications effectuées par des transactions qui se sont terminées par commit. C est le fonctionnement par défaut. Deux requêtes successives peuvent donc afficher des résultats différents si des transactions ayant modifié les enregistrements se sont terminées par commit. Pour résumer, vous pouvez lire les données mais vous n êtes pas sûrs qu elles ne seront pas modifiées à la prochaine lecture. Mais si vous voulez lire les données, autant lire leurs mises à jour. SERIALIZABLE December 11, 2006 à 22h02 15/39 December 11, 2006 à 22h02

La transaction voit les enregistrements effectivement modifiés (et validés par un commit) avant le début de la transaction. PostgreSQL essaiera de réaliser les différentes transactions concurrentes. Mais il est possible que des modifications soient impossibles parce que d autres transactions impliquant les mêmes enregistrements auront été validées par commit. Pour résumer, vous accédez aux données prises au début de la transaction. Pendant des transactions concurrentes, chacun voit ses modifications. Si vous modifiez l enregistrement A pendant qu une transaction concurrente modifie l enregistrement B, postgresql synchronisera les deux transactions. A la fin des transactions, les enregistrements A et B seront modifiés. Mais si vous essayez de modifier un enregistrement qu une autre transaction (pas forcément serializable) a déjà modifié, vous êtes bloqué en attendant le rollback ou le commit du concurrent. Si la transaction concurrente valide sa modification, un message vous indiquera que la transaction a échoué. Dans ce cas, toute votre transaction doit être annulée. READ UNCOMMITTED est traité comme READ COMMITTED REPEATABLE READ est traité comme SERIALIZABLE. Vous définissez le mode d isolation lors de la commande de début de transaction. START TRANSACTION [ ISOLATION LEVEL { READ UNCOMMITTED READ COMMITTED REPEATABLE READ SERIALIZABLE } ] [ READ WRITE READ ONLY ] La commande set transaction précise les caractéristiques des transactions suivantes qui commencent par begin. SET TRANSACTION [ ISOLATION LEVEL { READ COMMITTED SERIALIZABLE } ] [ READ WRITE READ ONLY ] Expérimentation 3. 1. Ouvrez deux terminaux. 2. Connectez-vous à votre base filmo dans les deux. 3. Créez une table essai avec un seul champ entier. create table essai (e int); 4. Exécutez les commandes suivantes en respectant la chronologie. dans le terminal 1 dans le terminal 2 insert into essai values (1); insert into essai values (2); insert into essai values (3); insert into essai values (4); insert into essai values (5); insert into essai values (6); insert into essai values (7); Constat. 5. Continuez dans le terminal 1 dans le terminal 2 start transaction isolation level read committed; start transaction isolation level read committed; update essai set e=11 where e=1; update essai set e=22 where e=2; commit; commit; December 11, 2006 à 22h02 16/39 December 11, 2006 à 22h02

Constat : chacun voit ses modifications. Il voit celles des autres lorsqu elles sont validées par commit. 6. Continuez dans le terminal 1 dans le terminal 2 start transaction isolation level serializable; start transaction isolation level serializable; update essai set e=33 where e=3; update essai set e=44 where e=4; commit; commit; Constat : chacun voit ses modifications. Mais il voit celles des autres seulement lorsque les validations par commit sont faites. PostgreSQL effectue les deux modifications parce qu elles portent sur des enregistrements différents. 7. Continuez dans le terminal 1 dans le terminal 2 start transaction isolation level serializable; start transaction isolation level serializable; update essai set e=55 where e=5; update essai set e=555 where e=5; commit; rollback; Constat : le terminal 1 va être bloqué en attente soit de commit, soit de rollback. modification par commit, terminal 1 ne peut qu annuler la sienne. Si terminal 2 valide sa 8. Continuez dans le terminal 1 dans le terminal 2 start transaction isolation level serializable; start transaction isolation level serializable; update essai set e=66 where e=6; update essai set e=666 where e=6; rollback; rollback; Constat : Sa modification passera si terminal 2 invalide la sienne. 9. Continuez dans le terminal 1 dans le terminal 2 start transaction isolation level read committed; start transaction isolation level serializable; update essai set e=77 where e=7; update essai set e=777 where e=7; commit; commit; December 11, 2006 à 22h02 17/39 December 11, 2006 à 22h02

Constat : terminal 2 va être bloqué. Après déblocage par le commit, il ne pourra pas continuer ses modifications. Et même son commit sera remplacé par rollback. 10. Pour bien comprendre la différence dans le terminal 1 dans le terminal 2 delete from essai; insert into essai values (1); insert into essai values (2); insert into essai values (3); start transaction isolation level read committed; start transaction isolation level read committed; update essai set e=11 where e=1; update essai set e=222 where e=2; update essai set e=333 where e=3; update essai set e=33 where e=3; commit; commit; Constat : chacun travaille sur sa copie. Le terminal 1 va être bloqué lorsqu il accédera au même enregistrement qu une transaction concurrente. Après déblocage par le commit, il voit tout de suite les modifications. Les données lues peuvent être modifiées à tout moment. Et recommencez avec l autre mode de transaction. dans le terminal 1 dans le terminal 2 delete from essai; insert into essai values (1); insert into essai values (2); insert into essai values (3); start transaction isolation level serializable; start transaction isolation level serializable; insert into essai values (7); insert into essai values (8); update essai set e=11 where e=1; update essai set e=222 where e=2; update essai set e=333 where e=3; update essai set e=33 where e=3; commit; rollback; Constat : chacun travaille sur sa copie. Le terminal 1 va être bloqué lorsqu il accédera au même enregistrement qu une transaction concurrente. Après déblocage par le commit, il ne peut plus qu annuler toutes ses modifications. 11. Pour vraiment bien comprendre la différence entre la théorie et la pratique. December 11, 2006 à 22h02 18/39 December 11, 2006 à 22h02

dans le terminal 1 dans le terminal 2 delete from essai; insert into essai values (1); insert into essai values (2); insert into essai values (3); start transaction isolation level serializable; start transaction isolation level serializable; select sum(e) from essai; insert into essai values (7); delete from essai where e=2; commit; select sum(e) from essai; commit; select sum(e) from essai; Constat : le mode serializable évite-t-il le problème des lignes fantômes? Selon moi, non! Le mode serializable devrait garantir qu aucune intervention sur les éléments consultés ne puisse être validée pendant la transaction. Certains logiciels l interprètent ainsi (SQL Anywhere Studio, par exemple). Mais cette interprétation du mode serializable se fait au dépend de l efficacité. Et bon nombre de logiciels interprètent le problème des lignes fantômes par la condition suivante : deux requêtes successives de la transaction ne doivent pas donner des résultats différents. PostgreSQL vérifie bien cette condition... même si à l issue de la transaction, les résultats n ont aucune pertinence puisque la base de données a été modifiée. 10.5 Conclusion Faites des transactions courtes et faites des transactions correspondant à vos besoins. N oubliez pas qu avec PostgreSQL, une transaction s exécute sur une copie de la base de données. Utilisez le verrouillage explicite de tables si votre intervention sur la base nécessite absolument que les données ne puissent être modifiées pendant votre action. 11 VERROUILLAGE EXPLICITE Comme vous avez pu le constater, des conflits persistent. Dans certaines situations, il faut garantir que l on possède un accès exclusif à une table (pour en modifier la structure, par exemple). Il est possible de verrouiller explicitement une table par la commande LOCK [ TABLE ] NomTable [,...] [ IN ModeVerrou MODE ] [ NOWAIT ] avec ModeVerrou qui peut prendre les valeurs suivantes : ACCESS SHARE ROW SHARE ROW EXCLUSIVE SHARE UPDATE EXCLUSIVE SHARE SHARE ROW EXCLUSIVE EXCLUSIVE ACCESS EXCLUSIVE Le verrouillage se fera pour la transaction, après résolution des éventuels conflits. L option NoWait, comme son nom l indique, n attend pas. Mais si la table n est pas disponible, la commande sera annulée et un message d erreur sera reçu. Quelques mode de verrouillage : December 11, 2006 à 22h02 19/39 December 11, 2006 à 22h02

ACCESS SHARE : l accès est partagé. C est le mode à utiliser pour lire des enregistrements. Ce mode rentrera en conflit uniquement avec une transaction en access exclusive. SHARE : Ce mode protège contre les changements de données par d autres transactions. Il rentrera en conflit avec les transactions en row exclusive, share update exclusive, share row exclusive, exclusive et access exclusive. ACCESS EXCLUSIVE : Ce mode ne permet aucune autre transaction. verrouillage posé sur cette table. Expérimentation 4. 1. Ouvrez deux terminaux. 2. Connectez-vous à votre base filmo dans les deux. 3. Créez une table essai avec un seul champ entier. create table essai (e int); 4. Exécutez les commandes suivantes en respectant la chronologie. dans le terminal 1 dans le terminal 2 insert into essai values (1); insert into essai values (2); Constat. Il rentrera en conflit avec tout mode de 5. Continuez dans le terminal 1 dans le terminal 2 start transaction isolation level read committed; start transaction isolation level read committed; lock essai in access share mode; insert into essai values (3); lock essai in access share mode; insert into essai values (4); insert into essai values (5); commit; commit; Constat : chacun a accès à la table. 6. Continuez dans le terminal 1 dans le terminal 2 start transaction isolation level read committed; start transaction isolation level read committed; lock essai in access share mode; insert into essai values (6); lock essai in share mode; insert into essai values (7); commit; commit; Constat : blocage de terminal 1. 7. Continuez December 11, 2006 à 22h02 20/39 December 11, 2006 à 22h02

dans le terminal 1 dans le terminal 2 start transaction isolation level read committed; start transaction isolation level read committed; lock essai in access share mode; insert into essai values (8); lock essai in access exclusive mode; commit; start transaction isolation level read committed; lock essai in access share mode; insert into essai values (9); commit; commit; Constat : terminal 2 bloquera dans un premier temps pour obtenir l accès. Une fois obtenu, il interdit l accès aux autres. Le verrouillage d enregistrements est réalisé par la commande SELECT, telle qu elle a été présentée pour la sélection/affichage, à laquelle on ajoute la clause FOR UPDATE. SELECT...FROM... FOR UPDATE [ OF NomTable [,...] ] [ NOWAIT ] Les enregistrements sélectionnés par cette commande seront verrouillés pour éviter toute tentative de modification ou suppression par d autres transactions. Cette commande se met en attente de libération de verrou si les enregistrements sont déjà verrouillés par une autre transaction. La commande peut spécifier une clause FOR TABLE de sorte que seuls les enregistrements de cette table seront verrouillés même si la requête porte sur des enregistrements d autres tables aussi. Bien sûr, la commande n est valide que si elle désigne bien des enregistrements. Particulièrement, SELECT FOR UPDATE ne fonctionnera pas avec des agrégats (GROUP BY). 11.1 Conclusion Faites des transactions courtes. Verrouillez les tables si vous avez besoin de garantir la permanence de toutes les données sur lesquelles vous travaillez. Verrouillez uniquement les enregistrements si vous avez besoin de garantir simplement la permanence de l enregistrement sur lequel vous travaillez. Libérez les tables dès que leur verrouillage n est plus nécessaire. 12 COMMENTAIRES EN SQL Des commentaires peuvent être écrits entre /* et */ dans un script SQL. 13 DEFINITION DE FONCTIONS SQL Les fonctions SQL sont une suite d instructions qui retourne un résultat (qui peut être vide). La fonction possède des paramètres dont on indique simplement le type. Ils seront référencés par $1, $2... dans la fonction. Les instructions effectuent des actions. Le résultat de la dernière instruction définit le résultat de la fonction. C est évidemment au concepteur de la fonction de faire la correspondance entre cette instruction et le résultat. La fonction peut renvoyer un ensemble de lignes (setof type). December 11, 2006 à 22h02 21/39 December 11, 2006 à 22h02

CREATE FUNCTION NomFonction (types ) RETURNS type AS $$ instructions $$ LANGUAGE sql; Attention, c est la syntaxe de postgresql 8.1 ; dans les versions précédentes, le texte de la fonction doit être entre apostrophes... ce qui oblige à doubler les apostrophes quand la fonction contient une valeur date ou texte. On a les instructions suivantes pour changer ou pour supprimer une fonction : CREATE OR REPLACE FUNCTION NomFonction (types ) RETURNS type AS $$ instructions $$ LANGUAGE sql; DROP FUNCTION NomFonction (types ) [ CASCADE RESTRICT ] Voici quelques exemples de fonctions (que vous pouvez essayer) : CREATE FUNCTION addition(integer, integer) RETURNS integer AS $$ SELECT $1 + $2 AS resultat; $$ LANGUAGE SQL; SELECT addition(1, 2) AS reponse; \c crash CREATE FUNCTION capacitetotale() RETURNS integer AS $$ BEGIN SELECT sum(capacite) AS RESULT from salles ; END; $$ LANGUAGE sql; SELECT capacitetotale() - capacite FROM salles; Une fonction qui fait une action sans renvoyer de résultat peut être définie avec un type de résultat void. \c filmo CREATE FUNCTION AjoutVente (integer, integer, integer) RETURNS void AS $$ UPDATE BilletsVendus SET nombre = nombre + $3 WHERE idfseance = $1 and codetarif = $2; $$ LANGUAGE SQL; SELECT AjoutVente(1, 2, 5); ajoute 5 places vendues à la séance dont l identifiant est 1 et du tarif dont le code est 2. December 11, 2006 à 22h02 22/39 December 11, 2006 à 22h02

create or replace function programme() returns setof record as select titre,jour from films, seances where films.idffilm=seances.idffilm; language sql; select * from programme() as (film varchar(30),jour date); CREATE TYPE ProgrammeJour AS (titrefilm varchar(50), horairefilm time); create or replace function programme(date) returns setof ProgrammeJour as select titre,horaire from films, seances where films.idffilm=seances.idffilm and jour=$1; language sql; select * from programme( 2006/11/28 ) ; Expérimentation 5. 1. Une fonction permettra de ne pas réécrire un calcul fréquemment utilisé. Sachant que l expression pour ajouter une durée numérique à un horaire de type time suit la syntaxe horaire + (ValeurNumerique*interval 1 hour ) créez une fonction qui possède deux paramètres (l horaire de début et la durée) et renvoie l horaire de fin. Testez-la! CREATE FUNCTION HeureFin(time, numeric) RETURNS time AS SELECT $1 + ($2*interval 1 hour ) as result; LANGUAGE SQL; select seances.jour,seances.horaire, HeureFin(seances.horaire,films.duree) from seances,films where seances.idffilm=films.idffilm; S il existe des films qui sont programmés à une heure tardive, que constatez-vous pour l affichage de l horaire de fin? S il n en existe pas, ajoutez une séance vers 23h30 et testez votre fonction. 2. Une fonction peut être utile pour décomposer un problème. Sur la base de données crash, répondez à la question "Quel est le nom du conférencier qui a fait le plus de conférences" en utilisant des fonctions. December 11, 2006 à 22h02 23/39 December 11, 2006 à 22h02

CREATE TYPE ConfNbConf AS (nom varchar(60), nb bigint); create or replace function NbConference() returns setof ConfNbConf as select nomeco,count(codeexpose) from economistes,exposes where codeeco=refconf group by nomeco; language sql; create or replace function MaxConf() returns bigint as select max(nb) from NbConference(); language sql; select nomeco from economistes,exposes where codeeco=refconf group by nomeco having count(codeexpose)=maxconf(); 3. Sachant que la salle de cinéma contient 200 places, écrire une fonction qui calcule le nombre de places restantes pour une séance donnée en paramètre. Procédez par étapes Afficher les séances et le nombre de places vendues. select idfseance,sum(nombre) from BilletsVendus group by IdfSeance; Ecrire une fonction pour afficher les places vendues d une séance. CREATE FUNCTION NbVendus(integer) RETURNS bigint AS select sum(nombre) as resultat from BilletsVendus where IdfSeance = $1 ; LANGUAGE SQL; select idfseance, nbvendus(idfseance) from seances; Terminer par la fonction demandée. CREATE OR REPLACE FUNCTION NbRestantes(integer) RETURNS bigint AS SELECT 200 - (select sum(nombre) from BilletsVendus where IdfSeance = $1) as resultat; LANGUAGE SQL; ou CREATE OR REPLACE FUNCTION NbRestantes(integer) RETURNS bigint AS SELECT 200 - VentesFilm.nbvendus as resultat from (select sum(nombre) as nbvendus from BilletsVendus where IdfSeance = $1) as VentesFilm; LANGUAGE SQL; select idfseance, nbrestantes(idfseance) from seances; Testez-la! December 11, 2006 à 22h02 24/39 December 11, 2006 à 22h02

A partir d ici, ce sont des prises de notes non rédigées 14 PROGRAMMATION EN PLPGSQL Pour utiliser le langage PLPGSQL, exécuter les trois commandes décrites dans la doc PostgreSQL, page 645. CREATE FUNCTION plpgsql_call_handler() RETURNS language_handler AS $libdir/plpgsql LANGUAGE C; CREATE FUNCTION plpgsql_validator(oid) RETURNS void AS $libdir/plpgsql LANGUAGE C; CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql HANDLER plpgsql_call_handler VALIDATOR plpgsql_validator; Ces commandes doivent être exécutées une fois dans chaque base de données pour laquelle on veut utiliser PLPGSQL. Le langage est interprété. Ceci signifie que les erreurs se remarquent à l exécution. On peut passer dans une partie d alternative sans erreur alors qu une autre partie est erronée. 14.1 Commentaires en PLpgSQL pour un commentaire de fin de ligne /* bloc de commentaires */ 14.2 Déclarations de fonctions CREATE FUNCTION NomFonction (parametres ) RETURNS type AS $$ DECLARE déclarations BEGIN instructions RETURN resultat ; END; $$ LANGUAGE plpgsql; L emploi de $$ comme délimiteur de chaîne permet d imbriquer plus facilement les chaînes en indiquant un label entre les $. Ce qui donne CREATE FUNCTION NomFonction (parametres ) RETURNS type AS $LabelFonction $ DECLARE déclarations BEGIN RETURN quantity; END; $LabelFonction $ LANGUAGE plpgsql; December 11, 2006 à 22h02 25/39 December 11, 2006 à 22h02

Si la fonction renvoie un résultat unique on emploie la commande RETURN expression; Si la fonction est censée renvoyer un ensemble de lignes, elle contiendra une itération sur la commande RETURN NEXT expression; et se terminera par un RETURN sans argument. En général, les fonctions qui construisent un ensemble de lignes sont utilisées comme des tables. SELECT * FROM some_func(); On peut définir des blocs délimités par BEGIN et END qui permettront de traiter les erreurs par une section EXCEPTION. 14.3 Suppression des fonctions DROP FUNCTION nomfunc(typeparametres); 14.4 syntaxe des déclarations: name [ CONSTANT ] type [ NOT NULL ] [ { DEFAULT := } expression ]; exemples : quantity numeric; qx integer := 10; Dans les versions antérieures, pour les paramètres, on ne mettait que les types et les paramètres étaient ensuite nommés $1, $2... Mais on peut faire directement CREATE FUNCTION nomfunc(nomparam nomtype, nomparam nomtype) RETURNS type AS $$ on peut faire des appels de fonctions avec des paramètres passés par variables CREATE FUNCTION sum_n_product(x int, y int, OUT sum int, OUT prod int) AS $$ Pour info, cela revient à faire un RETURNS record. On peut utiliser des paramètres de type table. A l exécution, la variable prendra la valeur de chaque ligne. Exemple CREATE FUNCTION augm(unesalle salles) RETURNS integer AS $$ BEGIN IF unesalle.capacite<100 THEN RETURN 3; ELSE RETURN 2; END IF END; $$ LANGUAGE plpgsql; select augm(salles)*capacite from salles; December 11, 2006 à 22h02 26/39 December 11, 2006 à 22h02