Aller au contenu
Accueil IntoSQL

Passer un dump PostgreSQL vers un PostgreSQL plus ancien ou plus récent

Déposez un dump texte de pg_dump ou pg_dumpall, en .sql ou .sql.gz, et téléchargez un script qui se charge sur PostgreSQL 13 à 18, quelle que soit la version qui a écrit le dump. Identités, enums, tableaux et jsonb restent tels quels, les types apportés par une extension deviennent du texte, et chaque changement figure dans le rapport.

Votre fichier
sqlshop_2024_postgres.sqlFichier d'exemple, 6,2 ko
Votre base de données

18 lignes converties, aucune correction, aucune rejetée

Afficher

Tables de shop_2024_postgres.sqlDump PostgreSQL 18.6 · écrit par pg_dump · utf8mb4

  • customers8 lignes
    8 colonnes
    idinteger not null
    nametext not null
    emailtext not null
    countryvarchar(2) not null
    is_activeboolean not null
    tagstext[] not null
    signed_update
    created_attimestamptz(6) not null
  • orders10 lignes
    10 colonnes
    idinteger not null
    customer_idinteger not null
    statusorder_status not null
    totalnumeric(10,2) not null
    itemssmallint not null
    ordered_attimestamp(6) not null
    shipped_attimestamp(6)
    notetext
    detailsjsonb
    deliveryinterval

Non converti

  • Vue paid_orders

Chaque base de données les écrit dans son propre langage. Réécrivez-les pour PostgreSQL.

-- Written by IntoSQL from a PostgreSQL dump. Load it with: psql -v ON_ERROR_STOP=1 -f <file>
SET client_encoding = 'UTF8';
SET standard_conforming_strings = on;
SET check_function_bodies = false;
SET client_min_messages = warning;
SET synchronous_commit = off;
SET maintenance_work_mem = '512MB';

CREATE TYPE order_status AS ENUM ('pending', 'paid', 'shipped', 'cancelled');
CREATE TABLE customers (
    id integer GENERATED BY DEFAULT AS IDENTITY NOT NULL,
    name text NOT NULL,
    email text NOT NULL,
    country varchar(2) DEFAULT 'US' NOT NULL,
    is_active boolean DEFAULT true NOT NULL,
    tags text[] DEFAULT '{}' NOT NULL,
    signed_up date,
    created_at timestamptz(6) DEFAULT CURRENT_TIMESTAMP NOT NULL
);

CREATE TABLE orders (
    id integer GENERATED BY DEFAULT AS IDENTITY NOT NULL,
    customer_id integer NOT NULL,
    status order_status DEFAULT 'pending' NOT NULL,
    total numeric(10,2) NOT NULL,
    items smallint DEFAULT 1 NOT NULL,
    ordered_at timestamp(6) NOT NULL,
    shipped_at timestamp(6),
    note text,
    details jsonb,
    delivery interval,
    CONSTRAINT orders_total_check CHECK (total >= (0))
);

COPY customers (id, name, email, country, is_active, tags, signed_up, created_at) FROM stdin;
1	Ana Martínez	ana@example.com	MX	t	{vip}	2023-01-15	2023-01-15 10:24:00+00
2	Zoë Müller	zoe@example.de	DE	t	{}	2023-02-03	2023-02-03 08:11:42+00
3	José Peña	jose@example.es	ES	f	{wholesale,"late payer"}	2023-03-21	2023-03-21 19:05:17+00
4	李雷	lilei@example.cn	CN	t	{}	2023-05-09	2023-05-09 02:40:00+00
5	Noah O'Brien	noah@example.ie	IE	t	{}	\N	2023-06-30 14:00:00+00
6	Amélie Laurent	amelie@example.fr	FR	t	{vip}	2024-01-02	2024-01-02 09:30:00+00
7	Ravi Patel	ravi@example.in	IN	f	{}	2024-02-29	2024-02-29 23:59:59+00
8	Sofia Rossi 🌻	sofia@example.it	IT	t	{}	2024-04-12	2024-04-12 12:12:12+00
\.

COPY orders (id, customer_id, status, total, items, ordered_at, shipped_at, note, details, delivery) FROM stdin;
1	1	shipped	129.90	3	2024-03-01 10:00:00	2024-03-02 16:30:00	\N	{"gift": false}	1 day 06:30:00
2	2	paid	54.00	1	2024-03-02 11:15:00	\N	Gift wrap 🎁	{"gift": true, "wrap": "red"}	\N
3	1	cancelled	12.50	1	2024-03-03 09:45:00	\N	Customer changed their mind	\N	\N
4	4	shipped	980.00	12	2024-03-05 02:10:00	2024-03-07 08:00:00	请小心轻放	{"fragile": true}	2 days 05:50:00
5	5	pending	45.75	2	2024-03-08 17:20:00	\N	Leave at the door; ring twice	\N	\N
6	6	shipped	310.40	5	2024-03-10 13:00:00	2024-03-11 09:00:00	Fragile: "glass"	{"fragile": true}	20:00:00
7	8	paid	76.20	2	2024-03-11 18:45:00	\N	\N	\N	\N
8	2	shipped	19.99	1	2024-03-12 08:00:00	infinity	Shipped date set to infinity by an old import	\N	\N
9	3	shipped	64.00	2	2024-03-14 15:30:00	2024-03-15 10:00:00	Two parcels	{"parcels": [1, 2]}	18:30:00
10	7	paid	1499.00	1	2024-03-15 21:05:00	\N	C:\\Users\\ravi\\invoice.pdf	\N	\N
\.


-- Keys, indexes and constraints, after the rows so each builds once.
CREATE UNIQUE INDEX customers_email_key ON customers (email);
CREATE UNIQUE INDEX customers_pkey ON customers (id);
CREATE UNIQUE INDEX orders_pkey ON orders (id);
CREATE INDEX idx_orders_customer ON orders (customer_id);
CREATE INDEX idx_orders_status_date ON orders (status, ordered_at);
ALTER TABLE customers ADD CONSTRAINT customers_email_key UNIQUE USING INDEX customers_email_key;
ALTER TABLE customers ADD CONSTRAINT customers_pkey PRIMARY KEY USING INDEX customers_pkey;
ALTER TABLE orders ADD CONSTRAINT orders_pkey PRIMARY KEY USING INDEX orders_pkey;
ALTER TABLE orders ADD CONSTRAINT orders_customer_id_fkey FOREIGN KEY (customer_id) REFERENCES customers (id) NOT VALID;
DO $f$ BEGIN
    ALTER TABLE orders VALIDATE CONSTRAINT orders_customer_id_fkey;
EXCEPTION WHEN foreign_key_violation THEN
    RAISE WARNING 'foreign key % has rows without a parent: it stays NOT VALID, and new rows are checked', 'orders_customer_id_fkey';
END $f$;
SELECT setval(pg_get_serial_sequence('customers', 'id'), LEAST(GREATEST(COALESCE((SELECT max(id) FROM customers)::numeric, 0) + 1, 1001), 2147483647)::bigint, false);
COMMENT ON TABLE customers IS 'People who bought at least once';
SELECT setval(pg_get_serial_sequence('orders', 'id'), LEAST(GREATEST(COALESCE((SELECT max(id) FROM orders)::numeric, 0) + 1, 5001), 2147483647)::bigint, false);

Corrections

Rien n'avait besoin d'être corrigé.

À vérifier

  • 1 objet non converti (vues, déclencheurs, routines ou événements) ; le rapport les liste un par un. Recréez-les à la main dans PostgreSQL.
  • L'index idx_orders_details sur orders utilise une expression qui ne peut pas être écrite pour PostgreSQL (a gin index) ; il n'est donc pas créé. Créez l'index à la main si les requêtes en ont besoin.

Votre fichier est converti sur cet ordinateur et n'est jamais envoyé.

Autres exemples :

Ce qui change entre le fichier et le script

Chaque ligne est une règle appliquée par le convertisseur, avec la ligne de rapport qu'il écrit quand la règle change quelque chose dans vos données.

  • varchar(n), char(n), text

    les mêmes types

    Les mêmes types, avec les mêmes longueurs.

  • numeric(p,s), numeric without a precision, NaN and Infinity

    les mêmes types et valeurs

    Le même type : chaque chiffre est copié tel que le dump l'a écrit.

  • money

    numeric(19,2)

    L'écriture de money dépend du lc_monetary du serveur ; le montant est donc gardé comme nombre sans symbole monétaire, et il se charge quelle que soit la locale de la cible.

    Ligne du rapport: type_replaced

  • enum types

    les mêmes types enum, créés avant les tables

    Les libellés gardent leur ordre.

  • enum columns holding values outside their labels

    text sans CHECK

    Le type rejetterait ces valeurs ; la colonne est donc en text et les garde toutes.

    Ligne du rapport: enum_check_skipped

  • composite and range types the dump defines, extension types (citext, hstore, ltree, PostGIS) and multiranges

    text avec le texte de PostgreSQL

    Le script ne crée ni extensions ni types composites ; chaque valeur garde donc le texte écrit par PostgreSQL. Créez le type et modifiez la colonne après le chargement.

    Ligne du rapport: type_replaced

  • citext

    text, comparé exactement

    Le script ne crée pas l'extension citext ; ces colonnes comparent donc le texte exactement. Créez-la et rétablissez les colonnes après le chargement.

    Ligne du rapport: case_insensitive_collation

  • json, jsonb

    les mêmes types

    json garde le texte tel qu'écrit ; jsonb garde les valeurs telles que le serveur les a normalisées.

  • timestamp with time zone

    timestamptz, les mêmes instants

    Chaque valeur garde le décalage écrit par le dump, donc l'instant est le même dans tout fuseau horaire.

  • time, time with time zone

    les mêmes types

    Les mêmes types, 24:00:00 compris.

  • infinity, -infinity and BC dates

    conservées

    PostgreSQL les garde telles quelles.

  • NaN and Infinity in numeric, real and double precision

    conservées

    PostgreSQL les garde telles quelles.

  • generated columns

    les mêmes colonnes générées

    La même formule, calculée par la cible.

  • generated columns with functions IntoSQL doesn't write

    une colonne simple avec les valeurs

    Une formule qu'IntoSQL ne sait pas écrire laisse une colonne simple avec les valeurs du dump et une ligne dans le rapport.

    Ligne du rapport: generated_not_translated

  • defaults with functions IntoSQL doesn't write

    aucune valeur par défaut

    Une valeur par défaut qu'IntoSQL ne sait pas écrire est omise et signalée.

    Ligne du rapport: default_not_translated

  • CHECK constraints with functions IntoSQL doesn't write

    non créée

    Une contrainte CHECK qu'IntoSQL ne sait pas écrire est omise et signalée.

    Ligne du rapport: check_skipped

  • CHECK ... NOT VALID

    ajoutée NOT VALID après les lignes

    Les lignes déjà présentes n'ont jamais été vérifiées ; la contrainte est donc ajoutée après elles, toujours non validée.

  • gin, gist, brin and hash indexes, partial and expression indexes

    non créé

    IntoSQL écrit des index b-tree sur des colonnes ; recréez les autres après le chargement.

    Ligne du rapport: index_skipped

  • foreign keys to tables the dump doesn't create

    non créée

    Une clé ne peut pas désigner une table absente.

    Ligne du rapport: foreign_key_skipped

  • NOT NULL columns with values that become NULL

    NOT NULL retiré

    Une colonne dont des valeurs ont dû devenir NULL ne peut pas garder NOT NULL, sinon le chargement s'arrêterait.

    Ligne du rapport: not_null_relaxed

  • partitioned tables

    une seule table avec les lignes de chaque partition

    Les lignes sont les mêmes ; partitionnez à nouveau la table si besoin.

    Ligne du rapport: partitions_dropped

  • views, functions, procedures, triggers, rules, policies, extensions and types other than enums

    listés dans le rapport

    IntoSQL convertit les tables et leurs lignes ; le reste est listé pour que vous le recréiez.

    Ligne du rapport: not_converted_objects

  • dumps without CREATE TABLE (--data-only)

    types déduits des valeurs

    Un dump de données seules ne contient que des lignes, donc les types viennent des valeurs.

    Ligne du rapport: no_schema

  • expressions in INSERT values

    NULL

    Un convertisseur qui n'exécute pas de base de données ne peut pas les évaluer.

    Ligne du rapport: expression_value

  • types IntoSQL doesn't know

    text

    Le texte accepte toute valeur ; changez le type après le chargement.

    Ligne du rapport: unknown_type

  • text that isn't valid in its encoding

    les octets invalides deviennent le caractère de remplacement

    Le texte PostgreSQL doit être de l'UTF-8 valide.

    Ligne du rapport: invalid_utf8_replaced

  • text decoded twice (ñ)

    copié tel quel

    Le dump contient exactement ces caractères, ils sont donc copiés ; le rapport les signale.

    Ligne du rapport: mojibake_suspected

Dans le fichierDans le scriptLigne du rapport
varchar(n), char(n), textles mêmes typesLes mêmes types, avec les mêmes longueurs.
numeric(p,s), numeric without a precision, NaN and Infinityles mêmes types et valeursLe même type : chaque chiffre est copié tel que le dump l'a écrit.
moneynumeric(19,2)L'écriture de money dépend du lc_monetary du serveur ; le montant est donc gardé comme nombre sans symbole monétaire, et il se charge quelle que soit la locale de la cible.type_replaced
enum typesles mêmes types enum, créés avant les tablesLes libellés gardent leur ordre.
enum columns holding values outside their labelstext sans CHECKLe type rejetterait ces valeurs ; la colonne est donc en text et les garde toutes.enum_check_skipped
composite and range types the dump defines, extension types (citext, hstore, ltree, PostGIS) and multirangestext avec le texte de PostgreSQLLe script ne crée ni extensions ni types composites ; chaque valeur garde donc le texte écrit par PostgreSQL. Créez le type et modifiez la colonne après le chargement.type_replaced
citexttext, comparé exactementLe script ne crée pas l'extension citext ; ces colonnes comparent donc le texte exactement. Créez-la et rétablissez les colonnes après le chargement.case_insensitive_collation
json, jsonbles mêmes typesjson garde le texte tel qu'écrit ; jsonb garde les valeurs telles que le serveur les a normalisées.
timestamp with time zonetimestamptz, les mêmes instantsChaque valeur garde le décalage écrit par le dump, donc l'instant est le même dans tout fuseau horaire.
time, time with time zoneles mêmes typesLes mêmes types, 24:00:00 compris.
infinity, -infinity and BC datesconservéesPostgreSQL les garde telles quelles.
NaN and Infinity in numeric, real and double precisionconservéesPostgreSQL les garde telles quelles.
generated columnsles mêmes colonnes généréesLa même formule, calculée par la cible.
generated columns with functions IntoSQL doesn't writeune colonne simple avec les valeursUne formule qu'IntoSQL ne sait pas écrire laisse une colonne simple avec les valeurs du dump et une ligne dans le rapport.generated_not_translated
defaults with functions IntoSQL doesn't writeaucune valeur par défautUne valeur par défaut qu'IntoSQL ne sait pas écrire est omise et signalée.default_not_translated
CHECK constraints with functions IntoSQL doesn't writenon crééeUne contrainte CHECK qu'IntoSQL ne sait pas écrire est omise et signalée.check_skipped
CHECK ... NOT VALIDajoutée NOT VALID après les lignesLes lignes déjà présentes n'ont jamais été vérifiées ; la contrainte est donc ajoutée après elles, toujours non validée.
gin, gist, brin and hash indexes, partial and expression indexesnon crééIntoSQL écrit des index b-tree sur des colonnes ; recréez les autres après le chargement.index_skipped
foreign keys to tables the dump doesn't createnon crééeUne clé ne peut pas désigner une table absente.foreign_key_skipped
NOT NULL columns with values that become NULLNOT NULL retiréUne colonne dont des valeurs ont dû devenir NULL ne peut pas garder NOT NULL, sinon le chargement s'arrêterait.not_null_relaxed
partitioned tablesune seule table avec les lignes de chaque partitionLes lignes sont les mêmes ; partitionnez à nouveau la table si besoin.partitions_dropped
views, functions, procedures, triggers, rules, policies, extensions and types other than enumslistés dans le rapportIntoSQL convertit les tables et leurs lignes ; le reste est listé pour que vous le recréiez.not_converted_objects
dumps without CREATE TABLE (--data-only)types déduits des valeursUn dump de données seules ne contient que des lignes, donc les types viennent des valeurs.no_schema
expressions in INSERT valuesNULLUn convertisseur qui n'exécute pas de base de données ne peut pas les évaluer.expression_value
types IntoSQL doesn't knowtextLe texte accepte toute valeur ; changez le type après le chargement.unknown_type
text that isn't valid in its encodingles octets invalides deviennent le caractère de remplacementLe texte PostgreSQL doit être de l'UTF-8 valide.invalid_utf8_replaced
text decoded twice (ñ)copié tel quelLe dump contient exactement ces caractères, ils sont donc copiés ; le rapport les signale.mojibake_suspected

Charger le script dans PostgreSQL

Le script crée les tables, copie les lignes, puis ajoute les clés, les index et les clés étrangères ; il se charge donc vite et s'arrête à la première erreur.

psql -v ON_ERROR_STOP=1 -d mydb -f postgresql.postgresql.sql

Les clés étrangères sont ajoutées en NOT VALID, puis validées. Si une ligne pointe vers une ligne qui n'existe pas, le script vous indique quelle contrainte, au lieu d'échouer à mi-chemin.

Pour un gros dump, créez d'abord la base de données et exécutez le script avec psql depuis la machine du serveur.

IntoSQL Pro charge le fichier directement dans PostgreSQL depuis l'application de bureau ou la ligne de commande, sans écrire de script.

Faire le dump PostgreSQL pour un meilleur résultat

Le convertisseur lit ce que contient le dump. Ces options y gardent davantage de vos données :

  • --format=plain, le format par défaut de pg_dump, écrit du SQL. Une archive custom ou directory (-Fc, -Fd) devient du SQL avec pg_restore -f dump.sql, sans serveur de base de données.
  • --no-owner --no-privileges omettent les rôles et les droits, que le convertisseur ignore de toute façon ; le dump est donc plus petit.
  • pg_dumpall met toutes les bases de données dans un seul fichier ; les tables de chacune sont préfixées par son nom, donc rien n'entre en collision.

Ce qui n'est pas converti

Les vues, triggers, procédures, fonctions et autres objets écrits dans le propre langage de PostgreSQL sont listés par nom dans le rapport, jamais supprimés en silence, pour que vous vérifiiez chacun face à la version de PostgreSQL cible avant de le recréer.

Questions sur le passage de PostgreSQL d'une version à l'autre

Pas de réponse ici ? Écrivez-nous depuis la page de contact, une personne vous répond. Page de contact

Mon dump est-il envoyé ?

Non. Le convertisseur s'exécute dans votre navigateur et lit le dump depuis votre disque par morceaux ; il ne quitte donc jamais votre ordinateur. L'application de bureau et la ligne de commande convertissent aussi sur votre ordinateur.

Quelle taille peut avoir le dump ?

Le convertisseur ne garde jamais tout le dump en mémoire : il lit le fichier deux fois, par plages, et écrit le script au fur et à mesure. Les dumps de plusieurs gigaoctets se convertissent dans le navigateur, dans l'application de bureau et avec la ligne de commande.

Lit-il les archives pg_dump -Fc ?

Pas directement : une archive custom est un format binaire. pg_restore -f dump.sql dump.backup la transforme en SQL texte que le convertisseur lit, sans se connecter à un serveur. Le convertisseur le signale quand il reçoit une archive.

De quelles versions de PostgreSQL le dump peut-il venir ?

Les dumps écrits par pg_dump et pg_dumpall depuis PostgreSQL 10, avec des lignes COPY ou INSERT. Chaque dump de test vient de PostgreSQL 13 et 18 et est comparé à sa source cellule par cellule.

Les valeurs serial et identity sont-elles conservées ?

Oui. Les colonnes serial et identity restent des colonnes d'identité, chaque ligne garde son identifiant, et chaque compteur reprend à la valeur qu'avait atteinte la séquence du dump.

Que deviennent les tableaux, les enums et les autres types PostgreSQL ?

Ils restent tels quels : tableaux, plages, json et jsonb, chaînes de bits, sauf money. Les types enum sont recréés avec leurs libellés. Les types apportés par une extension (citext, hstore, PostGIS) et les types composites deviennent text, et le rapport indique quelles colonnes.

Et les fonctions, les déclencheurs et les vues ?

Ils sont listés par nom dans le rapport et ne sont pas convertis, pour que vous puissiez les recréer une fois les tables chargées. Les contraintes CHECK NOT VALID sont ajoutées après les lignes, toujours non validées.

Sur quelles versions de PostgreSQL le script se charge-t-il ?

PostgreSQL 13 à 18, quelle que soit la version qui a écrit le dump. Le même script se charge sur chacune, et s'arrête à la première erreur en cas de problème.