2011-11-26 86 views
3

直到現在,我們的應用程序一直使用一個SQLObject數據庫作爲ORM。很顯然,在某些時候,我們知道我們必須面對SQLite併發問題,所以我們做到了。使用SQLObject將數據從一個sqlite數據庫遷移到多個SQLite數據庫

我們最終將當前數據庫拆分爲多個數據庫。這意味着每個表格架構保持不變,但我們將不同的表格分佈到多個數據庫中,並將表格緊密結合在一起

現在這個工程相當不錯,在一個乾淨的我們的應用程序的新版本安裝,但升級到我們的應用程序的早期版本中這個新版本需要我們的應用程序就可以開始工作前,一個特殊的數據遷移。在這種情況下,數據庫遷移很簡單,將表單從這個單一數據庫移動到適當的不同數據庫中。

爲了舉例說明,認爲這是舊的結構:

single_db.db ---單個數據庫

* A -- Table A 
* B -- Table B 
* C -- Table C 
* D -- Table D 
* E -- Table E 
* F -- Table F 

新的結構:

db1.db ---數據庫1

- A -- Table A 
- B -- Table B 
- C -- Table C 
- D -- Table D 

db2.db ---數據庫2

- E -- Table E 

db3.db ---數據庫3

- F -- Table F 

當升級會發生,我們的應用程序將與上述3個數據庫,並與他們空表創建新的結構。此外,舊數據庫single_db.db包含所有表和實際數據。現在,在我們的應用程序可以開始工作之前,它應該移動表格,或者我應該說將表格中的數據從舊數據庫複製到相應新數據庫中的相應表格。

我需要編寫的代碼爲這個數據庫遷移。我知道我可以使用舊數據庫連接來查詢表,並使用較新的數據庫連接將返回的行插入到相應的表中。我應該提到的一個警告是這些表中的一些可以包含大量的行。在2/3表格中,行數可以達到2 - 250萬。

所以想問一下,如果我能,因爲我在SQLite的頂部使用的SQLObject使用任何其他SLQObject技巧,也有沒有人這樣做過?

感謝您的幫助。

回答

1

我意識到你現在可能已經解決了這個問題,但是對於任何使用Google的人來說,我必須做的與OP幾乎完全一樣,這是我使用的代碼的核心部分(它是從我發現的東西中修改的,但我可以「T再次找到它歸功於原作者道歉!)

def _iterdump(connection, table_name): 
    """ 
    Returns an iterator to dump a database table in SQL text format. 
    """ 

    cu = connection.cursor() 

    yield('BEGIN TRANSACTION;') 

    # sqlite_master table contains the SQL CREATE statements for the database. 
    q = """ 
     SELECT name, type, sql 
     FROM sqlite_master 
      WHERE sql NOT NULL AND 
      type == 'table' AND 
      name == :table_name 
     """ 
    schema_res = cu.execute(q, {'table_name': table_name}) 
    for table_name, type, sql in schema_res.fetchall(): 
     if table_name == 'sqlite_sequence': 
      yield('DELETE FROM sqlite_sequence;') 
     elif table_name == 'sqlite_stat1': 
      yield('ANALYZE sqlite_master;') 
     elif table_name.startswith('sqlite_'): 
      continue 
     else: 
      yield('%s;' % sql) 

     # Build the insert statement for each row of the current table 
     res = cu.execute("PRAGMA table_info('%s')" % table_name) 
     column_names = [str(table_info[1]) for table_info in res.fetchall()] 
     q = "SELECT 'INSERT INTO \"%(tbl_name)s\" VALUES(" 
     q += ",".join(["'||quote(" + col + ")||'" for col in column_names]) 
     q += ")' FROM '%(tbl_name)s'" 
     query_res = cu.execute(q % {'tbl_name': table_name}) 
     for row in query_res: 
      yield("%s;" % row[0]) 

如果您通過原始數據庫SQLite的連接,並在原表的名稱DB這個發生器將歸還命令,你可以傳遞到新數據庫SQLite的對象上執行。

當我這樣做時,我還對所有表格首先進行了一些行計數,並在執行INSERT行時增加了一個計數器,以便我可以顯示遷移進度。