SQLITE SQL döküm dosyasını POSTGRESQL'e dönüştürün


99

POSTGRESQL'de üretim ile SQLITE veritabanını kullanarak geliştirme yapıyorum. Yerel veritabanımı büyük miktarda veriyle güncelledim ve belirli bir tabloyu üretim veritabanına aktarmam gerekiyor.

Çalışan dayanarak sqlite database .dump > /the/path/to/sqlite-dumpfile.sql, SQLITE aşağıdaki biçimde bir tablo dökümü çıkarır:

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;

Yukarıdakileri, üretim sunucuma aktarabileceğim POSTGRESQL uyumlu bir döküm dosyasına nasıl dönüştürebilirim?


1
Değiştim kadar Eh, bu komut için beni işe yaramadı sqlite için sqlite3
Celal Ergün

Yanıtlar:


104

Bu döküm dosyasını doğrudan şuraya besleyebilmelisiniz psql:

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

idSütunun "otomatik artış" yapmasını istiyorsanız , tablo oluşturma satırında türünü "int" yerine "seri" olarak değiştirin. PostgreSQL daha sonra bu sütuna bir sıra ekleyecektir, böylece NULL kimlikli INSERT'lere bir sonraki kullanılabilir değer otomatik olarak atanır. PostgreSQL de AUTOINCREMENTkomutları tanımayacağından bunların kaldırılması gerekir.

Ayrıca datetimeSQLite şemasındaki sütunları kontrol etmek ve bunları timestampPostgreSQL için değiştirmek isteyeceksiniz . ( Bunu işaret ettiği için Clay'e teşekkürler .)

Eğer SQLite'ta Boolean varsa o zaman dönüştürebilirsiniz 1ve 0karşı 1::booleanve 0::boolean(sırasıyla) veya dökümü şema bölümünde bir tam sayıya boole sütun değiştirin ve sonra aktarılmasından sonra PostgreSQL içindeki elle onları düzeltmek.

SQLite'ınızda BLOB'lar varsa, kullanılacak şemayı ayarlamak isteyeceksiniz bytea. Muhtemelen bazı decodearamaları da karıştırmanız gerekecek . En sevdiğiniz dilde bir quick'n'dirty kopyalayıcı yazmak, uğraşmanız gereken çok sayıda BLOB varsa, SQL'i karıştırmaktan daha kolay olabilir.

Her zaman olduğu gibi, yabancı anahtarlarınız varsa, muhtemelen set constraints all deferredBEGIN / COMMIT çiftinin içine komutu yerleştirerek sipariş sorunları eklemekten kaçınmak isteyeceksiniz .

Boolean, blob ve kısıtlama notları için Nicolas Riley'ye teşekkürler .

Eğer varsa `kodunuzda bazı SQLite3 istemcileri tarafından oluşturulan, bunları kaldırmak gerekir.

PostGRESQL ayrıca unsignedsütunları da tanımaz , bu nedenle bunu kaldırmak veya şunun gibi özel yapılmış bir kısıtlama eklemek isteyebilirsiniz:

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

SQLite varsayılan olarak null değerleri ''olarak ayarlasa da, PostgreSQL bunların NULL.

SQLite döküm dosyasındaki sözdizimi çoğunlukla PostgreSQL ile uyumlu görünmektedir, bu nedenle birkaç şeyi yamalayıp onu besleyebilirsiniz psql. SQL INSERT'ler aracılığıyla büyük miktarda veriyi içe aktarmak biraz zaman alabilir ama işe yarayacaktır.


4
Hayır, ek yükü önlemek için işlemi devam ettirmek istiyorsunuz.
Peter Eisentraut

3
Bu harika çalışıyor. Ayrıca sqlite datetimesütunlarını taşımanız gerekiyorsa , bunları timestamppostgres için değiştirmeniz gerektiğini de not etmek isterim .
Clay

4
Değişen: Bir kaç sorunları ben karşılaştım BLOBiçine BYTEA( stackoverflow.com/questions/3103242 ) için 0/1 değişen BOOLEANsütun '0' / '1' ve (kısıtlamaları ertelemek DEFERRABLE/ SET CONSTRAINTS ALL DEFERRED).
Nicholas Riley

2
@NicholasRiley: Bunun için teşekkürler. Bunu bir topluluk wiki'sine verdim çünkü grup çabasına dönüştü, adil.
mu çok kısa

2
Bir zaman damgasını progreSQL zaman damgasına dönüştürmek için postgreSQL'de to_timestamp () kullanabilirsiniz
r03

63

pgloader

Bir SQLite dökümünü PostgreSQL'e dönüştürmenin bir yolunu ararken bu gönderiye rastladım. Bu gönderinin kabul edilmiş bir cevabı (ve bu + 1'de iyi bir cevabı) olmasına rağmen, bunu eklemenin önemli olduğunu düşünüyorum.

Buradaki çözümlere bakmaya başladım ve daha otomatik bir yöntem aradığımı fark ettim. Wiki belgelerine baktım:

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

ve keşfedildi pgloader. Oldukça havalı bir uygulama ve kullanımı nispeten kolay. Düz SQLite dosyasını kullanılabilir bir PostgreSQL veritabanına dönüştürebilirsiniz. Den yükledim *.debve commandbir test dizininde şöyle bir dosya oluşturdum :

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

Docs durumu gibi . Daha sonra testdbşununla bir oluşturdum createdb:

createdb testdb

pgloaderKomutu şu şekilde çalıştırdım :

pgloader command

ve sonra yeni veritabanına bağlanıldı:

psql testdb

Verileri kontrol etmek için yapılan bazı sorgulardan sonra, oldukça iyi çalıştığı görülüyor. Bu komut dosyalarından birini çalıştırmayı deneseydim veya burada bahsedilen aşamalı dönüşümü yapsaydım, çok daha fazla zaman harcardım.

Konsepti kanıtlamak için, bunu testdbbir üretim sunucusundaki bir geliştirme ortamına aktardım ve verileri güzelce aktardım.


2
Ubuntu dağıtımlarının (hala desteklenmektedir) eski sürüme sahip olabileceğine dikkat edin - v2.xy zaten kullanımdan kaldırılmıştır ve gerçekte çalışmaz. v3.2.x çalışabilir ancak v3.2.3 önerilir. Kanayan kenardan v3.2.3'ü aldım ve sudo dpkg -i <.deb dosya adı> ile yükledim , bağımlılıklarla ilgili bir sorunu yoktu.
silpol

@Silpol ile aynı fikirdeyim - en son kararlı sürümü indirdiğinizden ve favori paket yöneticinizi kullanarak kurduğunuzdan emin olun; "komut" dosyası için bu, uzantı adı olmayan (yani dosya adının sonunda .txt'ye gerek olmayan) yalnızca "command" adlı bir metin dosyasıdır; dosya adını köşeli parantez içine koymanıza gerek yoktur; verilerimi görmek için psql veritabanının search_parth değerini değiştirmem gerekiyordu; pgloader iyi çalışıyor ve beni büyük bir güçlükten kurtardı
BKSpurgeon

bu benim günümü kurtardı.
Yakob Ubaidi

1
Evet, bu sorunla karşılaştığımda mücadele ediyordum ve bu araç bunu çok kolaylaştırdı ... Bazen işler iyi gidiyor, değil mi?
nicorellius

Sağ ol, kanka. Bu cevabın kabul edilen cevap olmaya değer olduğunu görüyorum! çok iyi bir araç.
mohamed_18


14

Netice mücevher (Ruby kütüphanesi) farklı veritabanları arasında kopyalama verileri sunmaktadır: http://sequel.jeremyevans.net/rdoc/files/doc/bin_sequel_rdoc.html#label-Copy+Databases

Önce Ruby'yi kurun, ardından gem'i çalıştırarak kurun gem install sequel.

Sqlite olması durumunda şöyle olur: sequel -C sqlite://db/production.sqlite3 postgres://user@localhost/db


1
Harika çözüm. Oyalanmaktan çok daha kolay pgloader.
michaeldever

Kesinlikle, pgloader dağınık, GC devasa veritabanlarında çöküyor gibi görünüyor: github.com/dimitri/pgloader/issues/962
hasufell

Cevabınızı, cevabınızı kopyaladığım stackoverflow.com/questions/6148421/… adresine göndermekten çekinmeyin . Sonra bana ping atın ve tekrarları istiyorsanız cevabımı iptal edeceğim.
Felix

@Felix teşekkürler! Krediyi alabilirsin. DB referanslarının sırasını değiştirebilir misiniz (PG'den SQLite'a istediğinden dolayı), oh ve kimliğime bir "la" daha ekleyebilir misiniz? Cevap, geliştirici makineye PG yüklemelerini gerektirdiğinden daha az yardımcı olabilir ve bu noktada geliştirme için sadece PG kullanırlar.
lulalala

@lulalala Teşekkürler. Bunu yaptım. Ama mantık konusunda katılmıyorum. Örneğin linux makinesindeki db'yi dönüştürebilir ve sonra onu dev makineye kopyalayabilir (sqlite db dosyası olarak). Ama her neyse, sonuçta kötü bir fikir :) Ama devam filmi burada kıçımı kötü bir durumda kurtardı.
Felix

7

Bir satır kullanabilirsiniz, işte sed komutunun yardımıyla bir örnek:

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 

UZUN tipin yerini
almaz

1
bir öğe daha eklenebilirsed -e 's/DATETIME/TIMESTAMP/g'
silpol

sed -e 's/TINYINT(1)/SMALLINT/g' - ve tüm veri türlerinin karşılaştırması için bkz. stackoverflow.com/questions/1942586/…
Purplejacket

Ayrıca, sqlite'da 't' veya 'f' olarak varsayılan SMALLINT ile ilgili bir sorun yaşadım. Açıkçası bir boole, ancak her iki db sistemine de güvenli bir düzeltme önerecek kadar aşina değil.
labirent

1
Değiştir ' | sed -e 'ile ; :)
AstraSerg

0

Sqlite dökümünü düzenlemeyi / yeniden ifade etmeyi denedim, böylece PostgreSQL bunu kabul eder, sıkıcı ve hataya meyillidir.

Gerçekten hızlı çalışmam gereken şey:

İlk önce PostgreSQL üzerinde herhangi bir veri olmadan şemayı yeniden oluşturun, ya dökümü düzenleyin ya da bir ORM kullanıyorsanız, şanslı olabilirsiniz ve her iki arka uçla da konuşur (sqlalchemy, peewee, ...).

Ardından, pandaları kullanarak verileri taşıyın. Bool alanına sahip bir tablonuz olduğunu varsayalım (sqlite cinsinden 0/1, ancak PostgreSQL'de t / f olmalıdır)

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)

Bu bir cazibe gibi çalışır, normal ifadelerin aksine (benim için) her işlevi yazması, okuması ve hata ayıklaması kolaydır.

Artık csv'yi PostgreSQL ile yüklemeyi deneyebilirsiniz (yönetici aracıyla grafiksel olarak bile), tabloları ilgili kaynak anahtarlarıyla yükledikten sonra tabloları yabancı anahtarlarla yüklemeniz gereken tek uyarı ile. Döngüsel bir bağımlılık durumum olmadı, sanırım bu durumda anahtar kontrolünü geçici olarak askıya alabilirsiniz.


0

Bu adımları deneyin ...

Adım 01: sqlite db'yi json'a boşaltın

python3 manage.py dumpdata > data.json

Adım 02: Geçiş yapmadan tablolar oluşturun

python3 manage.py migrate --run-syncdb

Adım 03: django kabuğunu açın. Ardından, içerik türü verilerini hariç tutun

python3 manage.py shell
from django.contrib.contenttypes.models import ContentType
ContentType.objects.all().delete()
quit()

4. Adım: Verileri Yükleyin

python3 manage.py loaddata data.json

büyük GB JSON dosyaları için büyük ram gereklidir
giveJob

-2

pgloader, sqlite'daki veritabanını postgresql'ye dönüştürme konusunda harikalar yaratıyor.

Yerel bir sqlitedb'yi uzak bir PostgreSQL veritabanına dönüştürmeye ilişkin bir örnek:

pgloader sqlite.db postgresql: // kullanıcı adı : şifre @ ana bilgisayar adı / dbname


1
Pgloader son derece hatalı ve güvenilmezdir. Hata ile hemen çöküyorKABOOM! Control stack exhausted (no more space for function call frames).
Cerin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.