web-dev-qa-db-fra.com

Convertir un fichier de vidage SQLITE SQL en POSTGRESQL

Je fais du développement en utilisant la base de données SQLITE avec la production dans POSTGRESQL. Je viens de mettre à jour ma base de données locale avec une énorme quantité de données et j'ai besoin de transférer une table spécifique vers la base de données de production.

Basé sur sqlite database .dump > /the/path/to/sqlite-dumpfile.sql, SQLITE génère un vidage de table au format suivant:

BEGIN TRANSACTION;
CREATE TABLE "courses_school" ("id" integer PRIMARY KEY, "department_count" integer NOT NULL DEFAULT 0, "the_id" integer UNIQUE, "school_name" varchar(150), "slug" varchar(50));
INSERT INTO "courses_school" VALUES(1,168,213,'TEST Name A',NULL);
INSERT INTO "courses_school" VALUES(2,0,656,'TEST Name B',NULL);
....
COMMIT;

Comment convertir ce qui précède en un fichier de vidage compatible POSTGRESQL que je peux importer dans mon serveur de production?

85
DevX

Vous devriez pouvoir alimenter ce fichier de vidage directement dans psql:

/path/to/psql -d database -U username -W < /the/path/to/sqlite-dumpfile.sql

Si vous voulez que la colonne id soit "incrémentée automatiquement", changez son type de "int" à "série" dans la ligne de création du tableau. PostgreSQL va alors attacher une séquence à cette colonne afin que les INSERT avec des identifiants NULL se voient automatiquement attribuer la prochaine valeur disponible. PostgreSQL ™ ne reconnaîtra pas non plus les commandes AUTOINCREMENT, elles doivent donc être supprimées.

Vous voudrez aussi vérifier les colonnes datetime dans le schéma SQLite et les changer en timestamp pour PostgreSQL (merci à Clay pour l'avoir signalé).

Si vous avez des booléens dans votre SQLite, vous pouvez convertir 1 et 0 et 1::boolean et 0::boolean (respectivement) ou vous pouvez changer la colonne booléenne en un entier dans la section de schéma du dump, puis les corriger manuellement dans PostgreSQL après l'importation.

Si vous avez des BLOBs dans votre SQLite, vous devrez alors ajuster le schéma pour utiliser bytea. Vous aurez probablement besoin de mélanger quelques decode appels également . Écrire un copieur quick'n'dirty dans votre langue préférée peut être plus facile que de manipuler le code SQL si vous avez beaucoup de BLOB à gérer.

Comme d’habitude, si vous avez des clés étrangères, vous voudrez probablement vous pencher sur set constraints all deferred pour éviter les problèmes de commande d'insertion, placez la commande dans la paire BEGIN/COMMIT.

Merci à Nicolas Riley pour les notes booléennes, blob et contraintes.

Si tu as ` sur votre code, tel que généré par certains clients SQLite3, vous devez les supprimer.

PostGRESQL ne reconnaît pas non plus les colonnes unsigned, vous pouvez le supprimer ou ajouter une contrainte personnalisée, telle que celle-ci:

CREATE TABLE tablename (
    ...
    unsigned_column_name integer CHECK (unsigned_column_name > 0)
);

Bien que SQLite utilise par défaut les valeurs nulles pour '', PostgreSQL ™ exige qu’ils soient définis comme NULL.

La syntaxe dans le fichier de vidage SQLite semble être principalement compatible avec PostgreSQL. Vous pouvez donc corriger quelques points et les transférer à psql. Importer une grosse pile de données via des INSERT SQL peut prendre un certain temps, mais cela fonctionnera.

90
mu is too short

pgloader

Je suis tombé sur cet article en cherchant un moyen de convertir un dump SQLite en PostgreSQL. Même si ce message a une réponse acceptée (et une bonne à +1), je pense que l'ajout est important.

J'ai commencé à chercher des solutions ici et me suis rendu compte que je cherchais une méthode plus automatisée. J'ai regardé les documents wiki:

https://wiki.postgresql.org/wiki/Converting_from_other_Databases_to_PostgreSQL

et découvert pgloader. Application plutôt cool et relativement facile à utiliser. Vous pouvez convertir le fichier SQLite à plat en une base de données PostgreSQL utilisable. J'ai installé à partir du *.deb et créé un fichier command comme celui-ci dans un répertoire de test:

load database  
    from 'db.sqlite3'  
    into postgresql:///testdb 

with include drop, create tables, create indexes, reset sequences  

set work_mem to '16MB', maintenance_work_mem to '512 MB';

comme l'état docs . J'ai ensuite créé un testdb avec createdb:

createdb testdb

J'ai lancé la commande pgloader comme ceci:

pgloader command

puis connecté à la nouvelle base de données:

psql testdb

Après quelques requêtes pour vérifier les données, il semble que cela a très bien fonctionné. Je sais que si j'avais essayé de lancer l'un de ces scripts ou d'effectuer la conversion pas à pas mentionnée dans le présent document, j'aurais passé beaucoup plus de temps.

Pour prouver le concept, j'ai vidé ce testdb et l'ai importé dans un environnement de développement sur un serveur de production et les données transférées correctement.

55
nicorellius

J'ai écrit un script pour faire le sqlite3 à postgres migration. Il ne gère pas toutes les traductions de schéma/données mentionnées dans https://stackoverflow.com/a/4581921/1303625 , mais il fait ce dont j'avais besoin. J'espère que ce sera un bon point de départ pour les autres.

https://Gist.github.com/2253099

15
Earle Clubb

La suite gem (a Ruby) permet la copie de données dans différentes bases de données: http://sequel.jeremyevans.net/rdoc/files/doc /bin_sequel_rdoc.html#label-Copy+Databases

En cas de sqlite, ce serait comme ceci: sequel -C sqlite://db/production.sqlite3 postgres://user@localhost/db

11
lulalala

Vous pouvez utiliser une ligne, voici un exemple à l'aide de la commande sed:

sqlite3 mjsqlite.db .dump | sed -e 's/INTEGER PRIMARY KEY AUTOINCREMENT/SERIAL PRIMARY KEY/' | sed -e 's/PRAGMA foreign_keys=OFF;//' | sed -e 's/unsigned big int/BIGINT/g' | sed -e 's/UNSIGNED BIG INT/BIGINT/g' | sed -e 's/BIG INT/BIGINT/g' | sed -e 's/UNSIGNED INT(10)/BIGINT/' | sed -e 's/BOOLEAN/SMALLINT/g' | sed -e 's/boolean/SMALLINT/g' | sed -e 's/UNSIGNED BIG INT/INTEGER/g' | sed -e 's/INT(3)/INT2/g' | sed -e 's/DATETIME/TIMESTAMP/g' | psql mypqdb mypguser 
7
develCuy

J'ai essayé d'éditer/regexping le dump sqlite pour que PostgreSQL l'accepte, c'est fastidieux et sujet aux erreurs.

Qu'est-ce que je dois travailler très vite:

Commencez par recréer le schéma sur PostgreSQL sans aucune donnée, que ce soit en modifiant le dump ou en utilisant un ORM, vous aurez peut-être de la chance et celui-ci s'adressera aux deux serveurs (sqlalchemy, peewee, ...).

Puis migrez les données en utilisant des pandas. Supposons que vous ayez une table avec un champ bool (qui vaut 0/1 dans sqlite, mais doit être t/f dans PostgreSQL)

def int_to_strbool(df, column):
    df = df.replace({column: 0}, 'f')
    df = df.replace({column: 1}, 't')
    return df

#def other_transform(df, column):
#...

conn = sqlite3.connect(db)
df = pd.read_sql(f'select * from {table_name}', conn)

df = int_to_strbool(df, bool_column_name)
#df = other_transform(df, other_column_name)

df.to_csv(table_name + '.csv'), sep=',', header=False, index=False)

Cela fonctionne comme un charme, il est facile d’écrire, de lire et de déboguer chaque fonction, contrairement (pour moi) aux expressions régulières.

Vous pouvez maintenant essayer de charger le fichier csv résultant avec PostgreSQL (même graphiquement avec l'outil d'administration), avec la seule réserve que vous devez charger les tables avec des clés étrangères après les avoir chargées avec les clés sources correspondantes. Je n'ai pas eu le cas d'une dépendance circulaire, je suppose que vous pouvez suspendre temporairement la vérification de la clé si tel est le cas.

0
agomcas