Sqlite 删除指定的列
最近由于APP数据库的升级错误,需要写修复代码, 由于Sqlite并没有提供直接删除列的函数,需要自己做实现,这里简单记录下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* 准备数据 */
drop table if exists YYTest;
drop table if exists YYTest_old;
/* 创建测试表,test_remove是我们要删除的 */
create table YYTest (id int, test_remove int);
/* 插入两个测试数据 */
insert into YYTest values (1, 1);
insert into YYTest values (2, 2);
/* stpe 1,重命名旧表 */
alter table YYTest rename to YYTest_old;
/* stpe 2,创建新表 */
create table YYTest (id int);
/* stpe 3,从旧表导数据到新表 */
insert into YYTest (id) select id from YYTest_old;
/* stpe 4,删除旧表 */
drop table YYTest_old;
上面是需要一个建表语句,可以写在一个 fix.sql 里面直接执行。但是有个坏处是需要多维护一份建表脚本(stpe 2)。
如果不想多维护这个建表脚本,可以在上层逻辑实现,而建表语句(scheme)可以通过 sqlite_master 导出。
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
@implementation FMDatabase (Yoyo)
- (NSString *)yoyo_schemeOfTable:(NSString *)table {
NSString* sql = [NSString stringWithFormat:@"select sql from sqlite_master where name=?"];
NSString* scheme = nil;
FMResultSet* rs = [self executeQuery:sql, table];
if ([rs next]) {
scheme = [rs stringForColumn:@"sql"];
}
[rs close];
return scheme;
}
- (NSString *)yoyo_schemeByRemoveColumns:(NSArray *)columns scheme:(NSString *)scheme {
NSRange beginRange = [scheme rangeOfString:@"("];
NSRange endRange = [scheme rangeOfString:@")"];
NSRange columnRange = NSMakeRange(beginRange.location + 1, endRange.location - beginRange.location - 1);
NSString* columnsString = [scheme substringWithRange:columnRange];
NSArray* columnComponents = [columnsString componentsSeparatedByString:@","];
columnComponents = [columnComponents yoyo_copyIf:^BOOL(NSString* element) {
for (NSString* column in columns) {
if ([element rangeOfString:column].location != NSNotFound) {
return NO;
}
}
return YES;
}];
columnsString = [columnComponents componentsJoinedByString:@","];
NSMutableString* result = [scheme mutableCopy];
[result replaceCharactersInRange:columnRange withString:columnsString];
return result;
}
- (BOOL)yoyo_removeColumns:(NSArray *)columns table:(NSString *)table {
BOOL result = NO;
NSArray* allColumns = [self yoyo_columnsOfTable:table];
NSArray* removedColumns = [allColumns yoyo_arrayByRemoveElements:columns];
// 1. dump 出表的 scheme
NSString* tableScheme = [self yoyo_schemeOfTable:table];
if (tableScheme.length <= 0) {
return NO;
}
// 2. 删除对应列的语句
tableScheme = [self yoyo_schemeByRemoveColumns:columns scheme:tableScheme];
if (tableScheme.length <= 0) {
return NO;
}
// 3. 改名成 table_old
NSString* sql = [NSString stringWithFormat:@"alter table %@ rename to %@_old;", table, table];
result = [self executeUpdate:sql];
if (!result) {
return NO;
}
// 4. 创建新表
result = [self executeUpdate:tableScheme];
if (!result) {
return NO;
}
// 6. 将旧表数据导回去
NSString* columnsString = [removedColumns componentsJoinedByString:@","];
sql = [NSString stringWithFormat:@"insert into %@(%@) select %@ from %@_old;",
table, columnsString, columnsString, table];
result = [self executeUpdate:sql];
if (!result) {
return NO;
}
sql = [NSString stringWithFormat:@"drop table %@_old;", table];
result = [self executeUpdate:sql];
return result;
}
@end