Assembler du texte
1
SELECT first_name || ' ' || last_name AS customer,
country
FROM customers
LIMIT 10;
Résultat — 5 premières lignes sur 10
| customer | country |
|---|---|
| Liam Fischer | ES |
| Mateo Costa | FR |
| Yuki Jang | DE |
| Ines Meyer | AU |
| Leo Novak | ES |
Planche s’ouvre dans un onglet séparé, la base d’exemple déjà chargée et cette requête prête dans l’éditeur. Tous les exemples de la page réutilisent cet onglet, et rien ne s’exécute tant que vous n’appuyez pas sur F9.
The same expression elsewhere
-- PostgreSQL, Oracle: identical to SQLite.
SELECT first_name || ' ' || last_name AS customer FROM customers;
-- MySQL / MariaDB: || means OR unless PIPES_AS_CONCAT is set.
SELECT CONCAT(first_name, ' ', last_name) AS customer FROM customers;
-- SQL Server: + concatenates, and CONCAT() exists from 2012.
SELECT first_name + ' ' + last_name AS customer FROM customers;
SELECT CONCAT(first_name, ' ', last_name) AS customer FROM customers;
The same expression elsewhere — donné à titre de comparaison. La base d’exemple du navigateur est SQLite, cette instruction ne peut donc pas s’exécuter ici.
L’opérateur || est celui du standard, et PostgreSQL, Oracle et SQLite l’utilisent. MySQL donne à || son propre sens — le OU logique — sauf si le serveur tourne avec PIPES_AS_CONCAT : sous MySQL, l’expression n’échoue donc pas, elle renvoie 0 ou 1. SQL Server utilise +, ambigu dans l’autre sens : avec deux colonnes numériques, il additionne.
CONCAT() existe sur MySQL, MariaDB, PostgreSQL et SQL Server (2012 et versions ultérieures). C’est donc la forme la plus portable entre ces quatre moteurs. Son comportement face à NULL diffère toutefois de celui des opérateurs.
Deux comportements diffèrent, pas seulement l’orthographe :
- NULL se propage à travers les opérateurs.
'a' || NULLvaut NULL sous PostgreSQL et SQLite, et'a' + NULLvaut NULL sous SQL Server. Un seul deuxième prénom manquant vide donc toute la colonne.CONCAT(), lui, traite NULL comme une chaîne vide. Le||d’Oracle ignore aussi NULL, à cause du point suivant. - Oracle traite la chaîne vide comme NULL. Là-bas,
'' IS NULLest vrai, et faux partout ailleurs : unWHERE name = ''qui trouve des lignes sous MySQL n’en trouve aucune sous Oracle.
Formater une date
3
SELECT order_number,
ordered_at,
strftime('%Y-%m', ordered_at) AS month,
strftime('%d/%m/%Y', ordered_at) AS day_first
FROM orders
LIMIT 10;
Résultat — 5 premières lignes sur 10
| order_number | ordered_at | month | day_first |
|---|---|---|---|
| ORD-2022-000001 | 2022-03-09 16:12:52 | 2022-03 | 09/03/2022 |
| ORD-2023-000002 | 2023-12-13 00:59:50 | 2023-12 | 13/12/2023 |
| ORD-2024-000003 | 2024-06-01 20:22:14 | 2024-06 | 01/06/2024 |
| ORD-2023-000004 | 2023-04-12 22:22:30 | 2023-04 | 12/04/2023 |
| ORD-2025-000005 | 2025-07-15 11:11:56 | 2025-07 | 15/07/2025 |
Formatting a date elsewhere
-- MySQL / MariaDB
SELECT DATE_FORMAT(ordered_at, '%Y-%m') AS month FROM orders;
-- PostgreSQL, Oracle
SELECT to_char(ordered_at, 'YYYY-MM') AS month FROM orders;
-- SQL Server (2012+)
SELECT FORMAT(ordered_at, 'yyyy-MM') AS month FROM orders;
-- ...or, much faster in bulk, and the usual choice for grouping:
SELECT CONVERT(char(7), ordered_at, 126) AS month FROM orders;
Formatting a date elsewhere — donné à titre de comparaison. La base d’exemple du navigateur est SQLite, cette instruction ne peut donc pas s’exécuter ici.
Quatre noms de fonctions différents et trois langages de motifs différents. strftime utilise le %Y-%m de style C, DATE_FORMAT les mêmes codes en pourcentage avec des sens différents pour certaines lettres, to_char utilise YYYY-MM, et FORMAT le yyyy-MM de .NET — où la casse compte, puisque mm désigne les minutes.
Pour regrouper plutôt que pour afficher, choisissez une forme peu coûteuse à calculer. Sous SQL Server, CONVERT(char(7), col, 126) est nettement plus rapide que FORMAT sur de nombreuses lignes. Sous PostgreSQL, date_trunc('month', col) est généralement préférable à to_char et conserve un type date. Enfin, une fonction appliquée à la colonne empêche souvent l’utilisation de son index.
Planche normalise ce qui revient, quel que soit le moteur qui l’a produit. Les pilotes affichent les dates au format YYYY-MM-DD HH:MM:SS[.mmm] pour que la grille reste cohérente, et le pilote Oracle règle NLS_DATE_FORMAT en conséquence : un TO_CHAR que vous écrivez vous-même s’accorde donc avec ce que la grille affiche à côté.
L’écart entre deux dates
5
SELECT o.order_number,
o.ordered_at,
s.delivered_at,
ROUND(julianday(s.delivered_at) - julianday(o.ordered_at), 1) AS days_to_deliver
FROM orders o
JOIN shipments s ON s.order_id = o.id
WHERE s.delivered_at IS NOT NULL
ORDER BY days_to_deliver DESC
LIMIT 15;
Résultat — 5 premières lignes sur 15
| order_number | ordered_at | delivered_at | days_to_deliver |
|---|---|---|---|
| ORD-2023-000152 | 2023-11-27 00:00:56 | 2023-12-07 22:33:00 | 10.9 |
| ORD-2025-001288 | 2025-10-18 04:20:05 | 2025-10-28 19:54:56 | 10.6 |
| ORD-2024-001816 | 2024-01-23 03:41:56 | 2024-02-02 18:40:52 | 10.6 |
| ORD-2023-002976 | 2023-05-23 02:17:37 | 2023-06-02 15:33:53 | 10.6 |
| ORD-2022-001345 | 2022-05-02 07:54:46 | 2022-05-12 19:12:56 | 10.5 |
Days between two dates elsewhere
-- MySQL / MariaDB: whole days, first argument minus second.
SELECT DATEDIFF(delivered_at, ordered_at) AS days FROM ...;
-- PostgreSQL: subtracting two timestamps gives an interval.
SELECT delivered_at - ordered_at AS elapsed FROM ...;
SELECT EXTRACT(DAY FROM delivered_at - ordered_at) AS days FROM ...;
-- SQL Server: the unit comes first, and the arguments are the other way round.
SELECT DATEDIFF(day, ordered_at, delivered_at) AS days FROM ...;
-- Oracle: subtracting two DATEs gives a number of days.
SELECT delivered_at - ordered_at AS days FROM ...;
Days between two dates elsewhere — donné à titre de comparaison. La base d’exemple du navigateur est SQLite, cette instruction ne peut donc pas s’exécuter ici.
Ces fonctions ne diffèrent pas seulement par leur nom. Le DATEDIFF(a, b) de MySQL prend deux arguments et renvoie a - b en jours entiers. Le DATEDIFF(day, a, b) de SQL Server prend d’abord l’unité et renvoie b - a. L’ordre des arguments est donc inversé : une requête copiée de l’un à l’autre peut produire un résultat de signe opposé. PostgreSQL et Oracle utilisent la soustraction, qui renvoie respectivement un intervalle et un nombre de jours.
La version de SQL Server compte en outre les frontières franchies, et non le temps écoulé : DATEDIFF(day, '2025-01-01 23:00', '2025-01-02 01:00') vaut 1, pour deux heures d’écart.
Remplacer un NULL
7
SELECT id,
first_name,
phone,
COALESCE(phone, '(none)') AS portable,
IFNULL(phone, '(none)') AS sqlite_and_mysql
FROM customers
WHERE phone IS NULL
LIMIT 10;
Résultat — 5 premières lignes sur 10
| id | first_name | phone | portable | sqlite_and_mysql |
|---|---|---|---|---|
| 2 | Mateo | NULL | (none) | (none) |
| 9 | Sven | NULL | (none) | (none) |
| 21 | Layla | NULL | (none) | (none) |
| 25 | Freya | NULL | (none) | (none) |
| 28 | Priya | NULL | (none) | (none) |
Replacing a NULL elsewhere
-- Everywhere, and the one to reach for:
SELECT COALESCE(phone, '(none)') FROM customers;
-- MySQL / MariaDB / SQLite
SELECT IFNULL(phone, '(none)') FROM customers;
-- SQL Server. Note ISNULL, not IFNULL, and it takes exactly two arguments.
SELECT ISNULL(phone, '(none)') FROM customers;
-- Oracle
SELECT NVL(phone, '(none)') FROM customers;
Replacing a NULL elsewhere — donné à titre de comparaison. La base d’exemple du navigateur est SQLite, cette instruction ne peut donc pas s’exécuter ici.
COALESCE est standard, existe partout, et prend autant d’arguments qu’on veut — il renvoie le premier qui n’est pas NULL. Les variantes propres à chaque moteur en prennent exactement deux, et deux de ces noms se ressemblent assez pour qu’on les intervertisse : MySQL et SQLite ont IFNULL, SQL Server a ISNULL. Il n’y a aucune raison de les préférer à COALESCE dans du code neuf.
En bref
Si une requête doit tourner sur plus d’un moteur, CONCAT(), COALESCE() et CAST() couvrent l’essentiel. Le formatage des dates ne se transporte pas, et se fait généralement mieux dans l’application, où vous avez de toute façon la langue et le fuseau horaire de l’utilisateur.