Перетворити файл дампа SQLITE SQL на POSTGRESQL


96

Я займався розробкою з використанням бази даних SQLITE з виробництвом у POSTGRESQL. Я щойно оновив свою локальну базу даних величезною кількістю даних, і мені потрібно перенести певну таблицю у виробничу базу даних.

На основі запущеного sqlite database .dump > /the/path/to/sqlite-dumpfile.sqlSQLITE видає дамп таблиці у наступному форматі:

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;

Як перетворити вищевказане у файл дампа, сумісний з POSTGRESQL, який я можу імпортувати на свій робочий сервер?


1
Ну, ця команда для мене не спрацювала, поки я не змінив sqlite на sqlite3
Celal Ergün

Відповіді:


101

Ви повинні мати можливість подати цей файл дампа прямо в psql:

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

Якщо ви хочете, щоб idстовпець "автоматично збільшувався", змініть його тип з "int" на "serial" у рядку створення таблиці. Потім PostgreSQL приєднає послідовність до цього стовпця, так що ВСТАВКАМ із ідентифікаторами NULL буде автоматично присвоєно наступне доступне значення. PostgreSQL також не розпізнає AUTOINCREMENTкоманди, тому їх потрібно видалити.

Ви також хочете перевірити наявність datetimeстовпців у схемі SQLite і змінити їх на timestampPostgreSQL (спасибі Clay за те, що це вказав).

Якщо у вас є логічні значення у вашому SQLite, тоді ви можете перетворити 1і та 0і 1::booleanта 0::boolean(відповідно), або ви можете змінити логічний стовпець на ціле число в розділі схеми дампа, а потім виправити їх вручну всередині PostgreSQL після імпорту.

Якщо у вашому SQLite є BLOB, тоді вам потрібно буде налаштувати схему для використання bytea. Ймовірно, вам також доведеться змішати деякі decodeдзвінки . Написати копіюючий копію на вашій улюбленій мові може бути простіше, ніж маніпулювати SQL, якщо у вас багато BLOB-файлів.

Як завжди, якщо у вас є зовнішні ключі, ви, мабуть, захочете вивчити, set constraints all deferredщоб уникнути проблем із упорядкуванням вставки, розмістивши команду всередині пари BEGIN / COMMIT.

Дякую Ніколасу Райлі за примітки щодо логіки, краплі та обмежень.

Якщо у вас є `код, створений деякими клієнтами SQLite3, їх потрібно видалити.

PostGRESQL також не розпізнає unsignedстовпці, можливо, ви захочете скинути це або додати спеціальне обмеження, наприклад, таке:

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

Поки SQLite за замовчуванням має значення NULL '', PostgreSQL вимагає, щоб вони були встановлені як NULL.

Синтаксис у файлі дампа SQLite, схоже, здебільшого сумісний з PostgreSQL, тому ви можете виправити кілька речей і подати його psql. Імпорт великої купи даних через SQL INSERT може зайняти деякий час, але це буде працювати.


4
Ні, ви хочете зберегти транзакцію, щоб уникнути накладних витрат.
Peter Eisentraut

3
Це чудово працює. Я також зазначу, що якщо вам потрібно перенести datetimeстовпці sqlite , вам доведеться змінити їх на timestamppostgres.
Клей

4
Ще кілька проблем, з якими я зіткнувся: зміна BLOBна BYTEA( stackoverflow.com/questions/3103242 ), зміна 0/1 для BOOLEANстовпців на '0' / '1' та відкладання обмежень ( DEFERRABLE/ SET CONSTRAINTS ALL DEFERRED).
Ніколас Райлі,

1
@NicholasRiley: Дякую за це. Я віддав це на спільноту wiki, оскільки це перетворилося на групову роботу, справедливий справедливий.
му занадто коротке ,

2
Ви можете використовувати to_timestamp () у postgreSQL, щоб перетворити мітку часу у мітку часу
progreSQL

61

pgloader

Я натрапив на цю публікацію, коли шукав спосіб перетворити дамп SQLite на PostgreSQL. Незважаючи на те, що ця публікація має прийняту відповідь (і хорошу на +1), я думаю, що додавання цього є важливим.

Я почав вивчати рішення тут і зрозумів, що шукаю більш автоматизований метод. Я шукав вікі-документи:

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

і виявив pgloader. Досить крутий додаток, і він відносно простий у використанні. Ви можете перетворити плоский файл SQLite у корисну базу даних PostgreSQL. Я встановив із *.debі створив такий commandфайл у тестовому каталозі:

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';

як у документі . Потім я створив за testdbдопомогою createdb:

createdb testdb

Я виконав pgloaderкоманду так:

pgloader command

а потім підключити до нової бази даних:

psql testdb

Після деяких запитів щодо перевірки даних, здається, це спрацювало досить добре. Я знаю, якби я спробував запустити один із цих сценаріїв або здійснити згадане тут покрокове перетворення, я витратив би набагато більше часу.

Щоб довести концепцію, я скинув це testdbі імпортував у середовище розробки на виробничому сервері, а дані передали красиво.


2
Пам'ятайте, що (як і раніше підтримується) дистрибутиви Ubuntu можуть мати застарілу версію - v2.xy вже застаріла і насправді не працює. v3.2.x може працювати, але рекомендується v3.2.3. Я витягнув v3.2.3 з кровотоку і встановив із sudo dpkg -i <ім'я файлу .deb> , у нього не було проблем із залежностями.
silpol

Я погоджуюсь з @silpol - не забудьте завантажити останній стабільний випуск і встановити за допомогою менеджера пакунків улюбленого файлу; для "командного" файлу це просто текстовий файл, що називається "команда" без імені розширення (тобто немає необхідності в .txt в кінці імені файлу), вам не потрібно вводити ім'я файлу в кутові дужки; мені довелося змінити search_parth бази даних psql, щоб побачити свої дані; pgloader працює добре і врятував мені багато клопоту
BKSpurgeon

це врятує мій день.
Якоб Убайді

1
Так, я боровся, коли зіткнувся з цією проблемою, і цей інструмент зробив це настільки простим ... Іноді все просто виходить чудово, чи не так?
nicorellius

Дякую, брате. Я бачу, що ця відповідь варта бути прийнятою відповіддю! дуже хороший інструмент.
mohamed_18

16

Я написав сценарій sqlite3для postgresпереходу на міграцію. Він не обробляє всі схеми / переклади даних, згадані в https://stackoverflow.com/a/4581921/1303625 , але робить те, що мені потрібно було зробити. Сподіваємось, це буде хорошою відправною точкою для інших.

https://gist.github.com/2253099


2
Це добре працює! Я роздвоївся "Суть" і додав деякі ідеї як коментар: gist.github.com/bittner/7368128
Петеріно,

12

Сиквел камінь (бібліотека Ruby) пропонує копіювання даних в різних базах даних: http://sequel.jeremyevans.net/rdoc/files/doc/bin_sequel_rdoc.html#label-Copy+Databases

Спочатку встановіть Ruby, а потім встановіть самоцвіт, запустивши gem install sequel.

У випадку sqlite це було б так: sequel -C sqlite://db/production.sqlite3 postgres://user@localhost/db


1
Чудове рішення. Набагато простіше, ніж возитися pgloader.
michaeldever

Абсолютно, pgloader безладний, GC, здається, аварійно розбивається на величезних базах даних: github.com/dimitri/pgloader/issues/962
hasufell

7

Ви можете використовувати один лайнер, ось приклад за допомогою команди 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 

немає заміни типу LONG, наприклад
yetanothercoder

1
можна було додати ще один предметsed -e 's/DATETIME/TIMESTAMP/g'
silpol

sed -e 's/TINYINT(1)/SMALLINT/g' - і для порівняння всіх типів даних см stackoverflow.com/questions/1942586 / ...
Purplejacket

У мене також була проблема з СМАЛЛІНТОМ, який за замовчуванням став значенням "t" або "f" у sqlite. Очевидно, що це логічне значення, але недостатньо знайоме з жодною системою баз даних, щоб рекомендувати безпечне виправлення.
лабіринт

1
Замінити ' | sed -e 'на ; :)
AstraSerg

0

Я пробував редагувати / регулярно експедувати дамп sqlite, тому PostgreSQL приймає його, він нудний і схильний до помилок.

Що я мав працювати дуже швидко:

Спочатку відтворіть схему на PostgreSQL без будь-яких даних, або редагуючи дамп, або якщо ви використовували ORM, можливо, вам пощастить, і вона розмовляє з обома серверними кінцями (sqlalchemy, peewee, ...).

Потім перенесіть дані за допомогою панд. Припустимо, у вас є таблиця з полем bool (яке в sqlite становить 0/1, але в PostgreSQL має бути t / f)

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)

Це працює як шарм, легко писати, читати та налагоджувати кожну функцію, на відміну від (для мене) регулярних виразів.

Тепер ви можете спробувати завантажити отриманий файл csv за допомогою PostgreSQL (навіть графічно за допомогою інструмента адміністратора), з єдиним застереженням, що ви повинні завантажувати таблиці із зовнішніми ключами після того, як ви завантажили таблиці відповідними ключами-джерелами. У мене не було випадку кругової залежності, я думаю, ви можете тимчасово призупинити перевірку ключа, якщо це так.


-1

pgloader творить чудеса щодо перетворення бази даних у sqlite у postgresql.

Ось приклад перетворення локального sqlitedb у віддалений db PostgreSQL:

pgloader sqlite.db postgresql: // ім’я користувача : пароль @ ім’я хосту / dbname


1
Pgloader страшенно глючить і ненадійний. Це одразу ж падає з помилкоюKABOOM! Control stack exhausted (no more space for function call frames).
Черін,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.