Requêtes SQL

Module N3

Dalibo SCOP

24.12

18 décembre 2024

Sur ce document

Formation Module N3
Titre Requêtes SQL
Révision 24.12
PDF https://dali.bo/n3_pdf
EPUB https://dali.bo/n3_epub
HTML https://dali.bo/n3_html
Slides https://dali.bo/n3_slides
TP https://dali.bo/n3_tp
TP (solutions) https://dali.bo/n3_solutions

Licence Creative Commons CC-BY-NC-SA

Cette formation est sous licence CC-BY-NC-SA. Vous êtes libre de la redistribuer et/ou modifier aux conditions suivantes :

  • Paternité
  • Pas d’utilisation commerciale
  • Partage des conditions initiales à l’identique

Marques déposées

PostgreSQL® Postgres® et le logo Slonik sont des marques déposées par PostgreSQL Community Association of Canada.

Versions de PostgreSQL couvertes

Ce document ne couvre que les versions supportées de PostgreSQL au moment de sa rédaction, soit les versions 13 à 17.

Requêtes SQL

Introduction

Ce module est organisé en quatre parties :

  • Compatibilité avec Oracle
  • Types de données
  • Différences de syntaxes
  • Transactions

Compatibilité avec Oracle

Oracle et PostgreSQL sont assez proches :

  • Tous deux des SGBDR
  • Le langage d’accès aux données est SQL
  • Les deux ont des connecteurs pour la majorité des langages (Java, C, .Net…)
  • Les langages embarqués sont différents
  • C’est dans les détails que se trouvent les problèmes

Points communs

PostgreSQL et Oracle :

  • Ont le même langage d’accès aux données (SQL)
    • mais des « variantes » différentes (extensions au standard)
  • Nombreux concepts en commun:
    • transactions et savepoints
    • MVCC et verrouillage
  • Conservation
    • des logiques applicative et algorithmique
    • de l’architecture applicative

Différences de schéma - 1

  • Le schéma sous Oracle : USER.OBJECT
    • sous PostgreSQL, véritable espace de nommage
  • La création des tables est entièrement compatible mais :
    • les tables temporaires globales n’existent pas sous PostgreSQL
    • INITTRANS, MAXEXTENTS sont inutiles (et n’existent pas)
    • PCTFREE correspond au paramètre fillfactor
    • PCTUSED est inutile (et n’existe pas)
  • Les colonnes générées sont disponibles depuis PostgreSQL 12
    • uniquement pour les colonnes stockées
    • utilisation de vues pour simuler les colonnes virtuelles

Différences de schéma - 2

  • Casse par défaut du nom des objets différente entre Oracle et PostgreSQL
  • Si casse non spécifiée :
    • majuscule sous Oracle
    • minuscule sous PostgreSQL
  • Forcer la casse
    • " " autour des identifiants

Différences de schéma - 3

  • Les contraintes sont identiques (clés primaires, étrangères et uniques, …)
  • Les index : btree uniquement, les autres n’existent pas (bitmap principalement)
  • Les tablespaces : la même chose dans sa fonctionnalité principale
  • Les types utilisateurs (CREATE TYPE) nécessitent une réécriture
  • Les liens inter-bases (DBLINK) n’existent pas sauf sous forme d’extensions (dblink ou fdw)

Autres différences anecdotiques

  • HAVING et GROUP BY
    • Oracle permet GROUP BY après HAVING
    • PostgreSQL impose GROUP BY avant HAVING
  • Table DUAL n’est pas nécessaire
  • Conversions implicites de et vers un type text
    • supporté par Oracle
    • plus supporté par PostgreSQL depuis la version 8.3
    • convertir explicitement :
         SELECT 1 = 'a'::text;

Types de données

  • Plusieurs incompatibilités
    • Oracle ne supporte pas bien la norme SQL
    • types numériques, chaînes, binaires, dates
  • PostgreSQL fournit également des types spécialisés

Différences sur les types numériques

  • Oracle ne gère pas les types numériques « natifs » SQL :
    • smallint, integer, bigint
  • Le type numeric du standard SQL est appelé number sous Oracle

Différences sur les types chaînes

  • Pas de varchar2 dans PostgreSQL
    • mais varchar
    • varchar (n) : taille en nombre de caractères
  • Le type text équivalent à varchar sans taille (1 Go maximum)
  • Attention, sous Oracle, '' équivaut à NULL
    • sous PostgreSQL, '' et NULL sont distincts
  • Un seul encodage par base
  • Collationnement par colonne

Différences sur le type booléen

  • Oracle n’a pas de type boolean
    • émulé de diverses manières
  • Attention aux ORM (Hibernate) suite à la migration de données
    • ils chercheront un boolean sous PostgreSQL alors que vous aurez migré un int

Différences sur les types binaires

  • 2 implémentations différentes sous PostgreSQL
    • large objects et fonctions lo_*
    • bytea

Différences sur les types dates

  • PostgreSQL :
    • date : jour
    • time : heure seule
    • timestamp : date + heure (alias timestamptz)
  • Fuseaux horaires
    • YYYY-MM-DD HH24:MI:SS.mmmmmmm+TZ (conforme SQL)
  • Type interval sous PostgreSQL

Différences sur les fonctions temporelles

  • SYSDATE
    • retourne la date et l’heure courante, sans timezone
    • équivalent avec PostgreSQL : localtimestamp
  • PostgreSQL ne propose pas de fonctions add_months, etc.
  • NLS_DATE_FORMAT (TO_CHAR et TO_DATE)
    • configuration DateStyle

Différences sur les types spécialisés

PostgreSQL fournit de nombreux types de données spécialisés :

  • timestamps et intervalles, avec opérations arithmétiques
  • Adressage IP (CIDR), avec opérateurs de masquage
  • Grande extensibilité des types : il est très facile d’en rajouter un nouveau
    • PERIOD
    • ip4r
  • Nombreuses extensions
    • PostGIS

Différences de syntaxes

  • Expressions conditionnelles DECODE et NVL
  • Concaténation de chaînes avec NULL
  • Pseudo-colonne ROWNUM
  • Jointures
  • Opérateurs ensemblistes
  • Hiérarchies

DECODE

Équivalent de la clause CASE du standard

CASE expr
  WHEN valeur1 THEN valeur_retour1
  WHEN valeur2 THEN valeur_retour2
  ELSE valeur_retour3
END
CASE
  WHEN expr1 THEN valeur_retour1
  WHEN expr2 THEN valeur_retour2
  ELSE valeur_retour3
END

NVL

  • Retourne le premier argument non NULL
SELECT NVL(description, description_courte, '(aucune)') FROM articles;
  • Équivalent de la norme SQL : COALESCE
SELECT COALESCE(description, description_courte, '(aucune)') FROM articles;

Concaténation avec NULL

Changement de comportement de l’opérateur ||

  • Rappel : pour Oracle, NULL équivaut à une chaîne vide ''
  • Pour PostgreSQL : SELECT 'chaîne' || NULL équivaut à NULL
  • Réécritures possibles :
SELECT 'chaîne' || COALESCE(null, '');
SELECT CONCAT('chaîne', null);

ROWNUM

  • Pseudo-colonne Oracle
  • Numérote les lignes du résultat
    • parfois utiliser pour limiter le résultat

Numéroter les lignes

  • ROWNUM n’existe pas dans PostgreSQL
    • row_number() OVER ()
    • attention si ORDER BY

Limiter le résultat

  • Retourne les dix premières lignes de résultats :
    • WHERE ROWNUM < 11
  • PostgreSQL propose l’ordre LIMIT xx :
SELECT *
  FROM employees
 LIMIT 10;

ROWNUM et ORDER BY

  • Oracle effectue le tri après l’ajout de ROWNUM
  • PostgreSQL applique le tri avant de limiter le résultat
  • Résultats différents

Jointures

  • Jointures internes
    • FROM tab1, tab2 WHERE tab1.col = tab2.col
    • FROM tab1 JOIN tab2 ON (tab1.col = tab2.col)

Jointures externes

  • Syntaxe (+) d’Oracle historique
  • LEFT JOIN
  • RIGHT JOIN
  • FULL OUTER JOIN

Produit cartésien

  • FROM t1, t2;
  • FROM t1 CROSS JOIN t2

Opérateurs ensemblistes

  • UNION / UNION ALL
  • INTERSECT
  • EXCEPT
    • équivalent de MINUS

Hiérarchies

  • Explorer un arbre hiérarchique
    • CONNECT BY Oracle
    • WITH RECURSIVE PostgreSQL

Syntaxe CONNECT BY

  • START WITH
    • condition de départ
  • CONNECT BY PRIOR
    • lien hiérarchique
SELECT empno, ename, job, mgr
  FROM emp
  START WITH mgr IS NULL
  CONNECT BY PRIOR empno = mgr

WITH RECURSIVE

WITH RECURSIVE hierarchie AS (
condition de départ
UNION ALL
clause de récursion
)
SELECT * FROM hierarchie

Niveau de hiérarchie

  • LEVEL donne le niveau de hiérarchie
  • Condition de départ
   1 AS level
  • Clause de récursion
   prior.level + 1

Chemin de hiérarchie

  • niveau 1/niveau 2/niveau 3
  • Condition de départ
    • niveau initial AS path
  • Clause de récursion
    • concatène le niveau précédent avec le path
    • prior.path || niveau courant

Détection des cycles

  • Équivalent de NOCYCLE
  • Tableau contenant les éléments
    • pseudo-colonne cycle
    • element = ANY (tableau) AS cycle
    • WHERE cycle = false

Common Table Expressions

  • Syntaxe quasiment identique
  • Attention à la récursion
    • WITH RECURSIVE obligatoire dans PostgreSQL

Transactions

  • Les transactions ne sont pas démarrées automatiquement
    • BEGIN
    • sauf avec JDBC (BEGIN caché)
  • Toute erreur non gérée dans une transaction entraîne son annulation
    • Oracle revient à l’état précédent de l’ordre en échec
    • PostgreSQL plus strict de ce point de vue
  • DDL transactionnels

Niveaux d’isolation

  • BEGIN TRANSACTION ISOLATION LEVEL xxxx
    • READ COMMITTED
    • REPEATABLE READ
    • SERIALIZABLE

SAVEPOINT

  • SAVEPOINT
  • RELEASE SAVEPOINT
  • ROLLBACK TO SAVEPOINT

Verrous explicites

  • SELECT FOR SHARE/UPDATE
    • quelques subtilités
  • LOCK TABLE

Conclusion

  • Oracle et PostgreSQL répondent à la même norme ISO SQL
    • … mais la conversion des requêtes SQL sera nécessaire
    • le typage des données est bien plus fourni avec PostgreSQL
  • Pour détecter les erreurs de syntaxe :
    • faire fonctionner l’application
    • repérer tous les ordres SQL en erreur (traces applicatives)
    • les corriger
  • Attention aux mots réservés

Questions

N’hésitez pas, c’est le moment !

Quiz

Travaux pratiques

Travaux pratiques (solutions)