SQLite 爬坑記
- 2019 年 11 月 30 日
- 筆記
作為從零開始的Web開發人員,在項目開發中總是遇到這樣那樣的坑,其中資料庫的坑最多。由於在功能完善過程中需要變換頻繁,不可避免地要更改DB Schema,不過我都是能不改盡量不改。逃不過時,只能硬著頭皮剛。
故事是這樣的,我要把兩個表中的某兩列的類型由字元型改成列表。在資料庫值類型中就是BLOB,ORM中叫做PickleType。資料庫使用SQLite,ORM使用SQLAlchemy,並使用基於Alembic的自動化遷移工具,於是就開始了。
Round 1
直接開搞
migrate。。。咦?怎麼腳本沒生成?Google之,Alembic不能探測類型變化。
OK,我手動寫個好了吧,upgrade。。。報錯!ALTER TABLE 不支援改變類型。
Round 2
好在這兩列也是新加不久,並不十分重要,於是我想到了,我刪了再加可以了吧?
downgrade。。。報錯!drop column也不支援。
Round 3
看來只能放棄自動化遷移了,Google一番,找到一個drop column的workaround:複製一個去掉該列的新表,並覆蓋原表。
create table temp as select col1,col2... from old_table; drop table old_table; alter table temp rename to old_table;
這時候再migrate,正確生成了腳本:
add_column ...... add_column ...... create_foreign_key ...
嗯。。看上去不錯,最後一行是。。新表沒有帶上外鍵資訊。
upgrade。。。報錯!create_foreign_key失敗!SQLite也不支援,無語了,不愧是Lite,怎麼不去屎?
進資料庫看看,新的列已經加上了,查了一下已有的關聯列,沒啥問題啊?
LEAVE IT ALONE!管它了,跑起來,新增一行數據,Beng shaka laka!原來缺少外鍵資訊已有數據沒問題,新增就出問題,還加了一行死數據,刪不掉還(沒有生成主鍵)。
Round 4
從備份恢復資料庫。Google外鍵問題,得到答案是別無他法,只能重新建表再複製數據。
alter table old_table rename to temp; create table old_table (...); insert into old_table select col1,col2,... from temp; drop table temp;
重新建立migration文件夾,運行測試,一切正常。
總結:
備份備份備份,折騰資料庫之前一定要備份!不然就等著哭吧。程式碼用版本控制管理,資料庫備份,我才有底氣胡搞一通。
特別感謝Google以及StackOverflow提供的幫助。
珍愛生命,請用MySQL。