2016-01-17 5 views
6

Ho circa 200 copie di un database SQLite. Tutti presi in tempi diversi con dati diversi in loro. Alcune righe vengono eliminate e alcune vengono aggiunte. Sono tutti in un'unica directory.Unire più backup dello stesso schema tabella in 1 tabella principale

Voglio unire tutte le righe nella tabella my_table, utilizzando tutti i file .db nella directory. Voglio che le righe duplicate siano cancellate, mostrando tutte le entrate da tutti i database, solo una volta.

Mi piacerebbe farlo in puro SQL, ma non credo sia possibile, quindi possiamo usare anche Python.

definizione Tabella:

CREATE TABLE my_table (
    ROWID INTEGER PRIMARY KEY AUTOINCREMENT, 
    guid TEXT UNIQUE NOT NULL, 
    text TEXT, 
    replace INTEGER DEFAULT 0, 
    service_center TEXT, 
    handle_id INTEGER DEFAULT 0, 
    subject TEXT, 
    country TEXT, 
    attributedBody BLOB, 
    version INTEGER DEFAULT 0, 
    type INTEGER DEFAULT 0, 
    service TEXT, 
    account TEXT, 
    account_guid TEXT, 
    error INTEGER DEFAULT 0, 
    date INTEGER, 
    date_read INTEGER, 
    date_delivered INTEGER, 
    is_delivered INTEGER DEFAULT 0, 
    is_finished INTEGER DEFAULT 0, 
    is_emote INTEGER DEFAULT 0, 
    is_from_me INTEGER DEFAULT 0, 
    is_empty INTEGER DEFAULT 0, 
    is_delayed INTEGER DEFAULT 0, 
    is_auto_reply INTEGER DEFAULT 0, 
    is_prepared INTEGER DEFAULT 0, 
    is_read INTEGER DEFAULT 0, 
    is_system_message INTEGER DEFAULT 0, 
    is_sent INTEGER DEFAULT 0, 
    has_dd_results INTEGER DEFAULT 0, 
    is_service_message INTEGER DEFAULT 0, 
    is_forward INTEGER DEFAULT 0, 
    was_downgraded INTEGER DEFAULT 0, 
    is_archive INTEGER DEFAULT 0, 
    cache_has_attachments INTEGER DEFAULT 0, 
    cache_roomnames TEXT, 
    was_data_detected INTEGER DEFAULT 0, 
    was_deduplicated INTEGER DEFAULT 0, 
    is_audio_message INTEGER DEFAULT 0, 
    is_played INTEGER DEFAULT 0, 
    date_played INTEGER, 
    item_type INTEGER DEFAULT 0, 
    other_handle INTEGER DEFAULT -1, 
    group_title TEXT, 
    group_action_type INTEGER DEFAULT 0, 
    share_status INTEGER, 
    share_direction INTEGER, 
    is_expirable INTEGER DEFAULT 0, 
    expire_state INTEGER DEFAULT 0, 
    message_action_type INTEGER DEFAULT 0, 
    message_source INTEGER DEFAULT 0 
) 
+0

Mostra la definizione della tabella. –

+0

@CL. aggiunto a quanto sopra. – User

+0

Come vengono identificate le voci? Di 'rowid' o di' guid'? –

risposta

7

Per poter accedere sia il database master e uno snapshot al tempo stesso, utilizzare ATTACH. cancellare e vecchia versione di una riga, utilizzare INSERT OR REPLACE:

ATTACH 'snapshot123.db' AS snapshot; 
INSERT OR REPLACE INTO main.my_table SELECT * FROM snapshot.my_table; 
DETACH snapshot; 

fare questo con tutti i database, in ordine dal più vecchio al più recente. (SQLite non ha alcun meccanismo di controllo ad anello per questo, fare questo ciclo in Python.)

In alternativa, si può andare a ritroso, dal più recente e il più antico, e inserire solo le righe che ancora non esistono:

ATTACH 'snapshot123.db' AS snapshot; 
INSERT OR IGNORE INTO main.my_table SELECT * FROM snapshot.my_table; 
DETACH snapshot; 
+0

Ci sono centinaia di database, quindi non può essere fatto manualmente in questo modo. – User

+0

Anche se incompleto e un po 'approssimativo (non cancellando righe per esempio) questo è un ottimo inizio. Scrivi uno script python per automatizzarlo, aggiungi una query di eliminazione per le righe eliminate ... e sei praticamente pronto. –

+2

@FlipVernooij In base alla domanda, le righe eliminate devono essere conservate. Se le righe eliminate dovessero essere nascoste, l'ultima istantanea conterrebbe già esattamente i dati desiderati. –

1
import sqlite3 
conn_1 = sqlite3.connect('master.db') 
c = conn_1.cursor() 
import glob, os 
os.chdir("/Users/me/Downloads/Archives") 
for file in glob.glob("*.db"): 
    if file != "master.db": 
     print file 
     conn_2 = sqlite3.connect(file) 
      c2 = conn_2.cursor() 
      query = "ATTACH '%s' AS snapshot;" % file 
      query += "INSERT OR IGNORE INTO master.my_table SELECT * FROM snapshot.my_table;" 
      query += "DETACH snapshot;" 
      c.executescript(query) 

errore: sqlite3.OperationalError: no such table: master.my_table

+0

Il database principale (quello aperto senza 'ATTACH') viene sempre chiamato' main'. –

1

due cose:

è necessario avere my_table in master.db

dovrebbe essere my_table NON master.my_table nella query.

import sqlite3 
conn_1 = sqlite3.connect('master.db') 
c = conn_1.cursor() 

query = "CREATE TABLE IF NOT EXISTS my_table (ROWID INTEGER PRIMARY KEY AUTOINCREMENT, guid TEXT UNIQUE NOT NULL, text TEXT, replace INTEGER DEFAULT 0, service_center TEXT, handle_id INTEGER DEFAULT 0, subject TEXT, country TEXT, attributedBody BLOB, version INTEGER DEFAULT 0, type INTEGER DEFAULT 0, service TEXT, account TEXT, account_guid TEXT, error INTEGER DEFAULT 0, date INTEGER, date_read INTEGER, date_delivered INTEGER, is_delivered INTEGER DEFAULT 0, is_finished INTEGER DEFAULT 0, is_emote INTEGER DEFAULT 0, is_from_me INTEGER DEFAULT 0, is_empty INTEGER DEFAULT 0, is_delayed INTEGER DEFAULT 0, is_auto_reply INTEGER DEFAULT 0, is_prepared INTEGER DEFAULT 0, is_read INTEGER DEFAULT 0, is_system_message INTEGER DEFAULT 0, is_sent INTEGER DEFAULT 0, has_dd_results INTEGER DEFAULT 0, is_service_message INTEGER DEFAULT 0, is_forward INTEGER DEFAULT 0, was_downgraded INTEGER DEFAULT 0, is_archive INTEGER DEFAULT 0, cache_has_attachments INTEGER DEFAULT 0, cache_roomnames TEXT, was_data_detected INTEGER DEFAULT 0, was_deduplicated INTEGER DEFAULT 0, is_audio_message INTEGER DEFAULT 0, is_played INTEGER DEFAULT 0, date_played INTEGER, item_type INTEGER DEFAULT 0, other_handle INTEGER DEFAULT -1, group_title TEXT, group_action_type INTEGER DEFAULT 0, share_status INTEGER, share_direction INTEGER, is_expirable INTEGER DEFAULT 0, expire_state INTEGER DEFAULT 0, message_action_type INTEGER DEFAULT 0, message_source INTEGER DEFAULT 0)" 

c.executescript(query) 

import glob, os 
os.chdir("/Users/me/Downloads/Archives") 
for file in glob.glob("*.db"): 
    if file != "master.db": 
     print file 
     conn_2 = sqlite3.connect(file) 
     c2 = conn_2.cursor() 
     query = "ATTACH '%s' AS snapshot;" % file 
     query += "INSERT OR IGNORE INTO my_table SELECT * FROM snapshot.my_table;" 
     query += "DETACH snapshot;" 
     c.executescript(query) 
+0

Su un altro computer, viene visualizzato il file "sqlite3.DatabaseError: file crittografato o non è un database" – User

+0

danneggiato? – Allen

+0

Funzionava perfettamente con gli stessi dati e lo stesso script su un'altra macchina – User