SQLite 數(shù)據(jù)庫升級——新增字段處理總結(jié)

一、場景

在工作中,由于新需求總是不斷漓穿,我們經(jīng)常會遇到項目中的一些表的結(jié)構(gòu)要改變,比如最常見的就是 新增字段 了注盈。這里我總結(jié)一下我遇到這種情況時的處理方法,SQLite 也有一些坑叙赚,希望能幫到有同樣需求的朋友們老客。下面我是用的 fmdb 進行的數(shù)據(jù)庫操作,用原生或者其他工具的升級思想也是一樣的震叮。

二胧砰、升級操作

用戶升級 app 時,當(dāng)我們判斷到舊項目的版本號(或者數(shù)據(jù)庫的單獨版本號)小于某個版本號時苇瓣,就進行我們的升級操作尉间。

1、新增普通字段

如果你要新增的是個普通字段,并不是個 主鍵(后面會介紹什么情況下會新增主鍵)哲嘲,那就好辦了贪薪,操作很簡單,直接執(zhí)行新增字段語句即可眠副。

先復(fù)習(xí)一下 SQL新增字段 語句:
alter table mydownload add column 'IsFree' varchar(100) default '1'
其中的 column 可以省略画切,同時也可以不給 default 默認(rèn)值。

下面是判斷升級并進行新增操作的具體代碼:

if (![dbPointer columnExists:@"LoginUserId" inTableWithName:@"mydownload"]) {
    // 如果不存在 LoginUserId 字段則執(zhí)行添加 LoginUserId 語句囱怕,默認(rèn)值是當(dāng)前登錄的用戶id
    NSString *addStr = [NSString stringWithFormat:@"alter table mydownload add column 'LoginUserId' varchar(100) default '%@'", [Global sharedGlobal].loginInfo.userId];
    if ([dbPointer executeUpdate:addStr]){
        DebugLog(@"添加 LoginUserId 字段成功霍弹!");
    } else {
        DebugLog(@"添加 LoginUserId 字段失敗娃弓!");
    }
}

?? 注意:
這里要說一下典格,我們的 SQLite 是個閹割的數(shù)據(jù)庫,有很多數(shù)據(jù)庫操作語句都是不支持的台丛,比如不支持 批量增加字段耍缴,所以如果你要新增多個字段,那也只能一個一個的加了齐佳。

2私恬、新增、修改主鍵或刪除某字段

如果你新增的是個 主鍵炼吴。比如你想在以前的文章 id 為主鍵的的基礎(chǔ)上本鸣,再新增一個用戶 id,把文章 id 和用戶 id 作為 聯(lián)合主鍵硅蹦,那此時就不能執(zhí)行新增字段方法了荣德,也是因為 SQLite 的限制,

?? 注意:
SQLite 限制了 ALTER TABLE 的部分功能童芹,只能將列添加到表的末尾或更改表的名稱涮瞻。 如果要在表的結(jié)構(gòu)中進行更復(fù)雜的更改,則必須 重新創(chuàng)建表假褪。 您可以將現(xiàn)有數(shù)據(jù)保存到臨時表署咽,刪除舊表,創(chuàng)建新表生音,然后從臨時表中復(fù)制數(shù)據(jù)宁否。

例如,假設(shè)您有一個名為“person”的表缀遍,其列名為“id”慕匠,“name”和“age”,并且您要從此表中刪除列“age”域醇。 以下 SQL 語句步驟說明了如何完成此操作:

BEGIN TRANSACTION;
CREATE TEMPORARY TABLE person_backup(id,name);
INSERT INTO person_backup SELECT id,name FROM person;
DROP TABLE person;
CREATE TABLE person(id,name);
INSERT INTO person SELECT id,name FROM person_backup;
DROP TABLE person_backup;
COMMIT;

具體例子

下面再把我項目中具體的一個簡略例子展示出來供大家參考:
原表狀態(tài):
原下載表 mydownload 只有兩個字段 EpisodeIdDownloaderFilePath台谊,主鍵是 EpisodeId 蓉媳。下載的東西不跟隨用戶。
新需求:
現(xiàn)在要求下載的東西跟隨用戶走锅铅,即下載列表只展示當(dāng)前用戶下載的東西酪呻。這就需要新增一個 LoginUserId 用戶 id 字段,把它和 EpisodeId 作為一個聯(lián)合主鍵狠角,這樣下載的東西就可以和用戶 id 綁定了号杠。
具體代碼操作:

 if (![dbPointer columnExists:@"LoginUserId" inTableWithName:@"mydownload"]) {
        // 如果不存在 LoginUserId 字段則將原來的表改名
        [dbPointer beginTransaction];
        BOOL isRollBack = NO;
        @try {
            if ([dbPointer executeUpdate:@"ALTER TABLE mydownload RENAME TO temp_mydownload"]) {
                
                NSString *executeStr = @"CREATE TABLE mydownload (EpisodeId varchar(100), LoginUserId varchar(100),  DownloaderFilePath varchar(100),CONSTRAINT PK_mydownload PRIMARY KEY(EpisodeId,LoginUserId) )";
                
                if ([dbPointer executeUpdate:executeStr]) {
                    // 從舊數(shù)據(jù)表把舊數(shù)據(jù)插入新的數(shù)據(jù)表中
                    NSString *insertSql = [NSString stringWithFormat:@"INSERT INTO mydownload (EpisodeId,LoginUserId,DownloaderFilePath) select EpisodeId,'%@','1','',DownloaderFilePath from temp_mydownload", [Global sharedGlobal].loginInfo.userId];// 復(fù)制改名后的表到新建的表(注意:一列對應(yīng)一列的進行復(fù)制,新增的字段可以用''來補)
                    if ([dbPointer executeUpdate:insertSql]) {
                        [dbPointer executeUpdate:@"drop table temp_mydownload"];// 刪除舊表
                        
                        [[NSUserDefaults standardUserDefaults] setObject:@"YES" forKey:@"hasModifyDownloadDatabase"];// 標(biāo)記已經(jīng)升級過下載表
                    };
                    
                }
            }
        } @catch (NSException *exception) {
            isRollBack = YES;
            // 事務(wù)回退
            [dbPointer rollback];
        } @finally {
            if (!isRollBack) {
                // 事務(wù)提交
                [dbPointer commit];
            }
        }
        
    }

以上的總結(jié)參考了并部分摘抄了以下文章,非常感謝以下作者的分享7岣琛:
1姨蟋、《sqlite alter table添加多列》
2、《sqlite并不支持建表后修改主鍵立帖,或刪除列眼溶,如果要修改,請參考如下做法》
3晓勇、《FMDB數(shù)據(jù)庫升級增加表字段》

轉(zhuǎn)載請備注原文出處堂飞,不得用于商業(yè)傳播——凡幾多

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市绑咱,隨后出現(xiàn)的幾起案子绰筛,更是在濱河造成了極大的恐慌,老刑警劉巖描融,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铝噩,死亡現(xiàn)場離奇詭異,居然都是意外死亡窿克,警方通過查閱死者的電腦和手機骏庸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來年叮,“玉大人具被,你說我怎么就攤上這事≈凰穑” “怎么了一姿?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長跃惫。 經(jīng)常有香客問我叮叹,道長,這世上最難降的妖魔是什么辈挂? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮裹粤,結(jié)果婚禮上终蒂,老公的妹妹穿的比我還像新娘蜂林。我一直安慰自己,他們只是感情好拇泣,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布噪叙。 她就那樣靜靜地躺著,像睡著了一般霉翔。 火紅的嫁衣襯著肌膚如雪睁蕾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天债朵,我揣著相機與錄音子眶,去河邊找鬼。 笑死序芦,一個胖子當(dāng)著我的面吹牛臭杰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谚中,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼渴杆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了宪塔?” 一聲冷哼從身側(cè)響起磁奖,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎某筐,沒想到半個月后比搭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡来吩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年敢辩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片弟疆。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡戚长,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出怠苔,到底是詐尸還是另有隱情同廉,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布柑司,位于F島的核電站迫肖,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏攒驰。R本人自食惡果不足惜蟆湖,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望玻粪。 院中可真熱鬧隅津,春花似錦诬垂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至充蓝,卻和暖如春隧枫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谓苟。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工官脓, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人娜谊。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓确买,卻偏偏與公主長得像,于是被迫代替她去往敵國和親纱皆。 傳聞我的和親對象是個殘疾皇子湾趾,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容