iOS FMDB 的使用

1. 创建数据库

1) 使用 FMDatabase创建

objectivec 复制代码
// 获取数据库路径
NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];

_dbPath = [docsDir stringByAppendingPathComponent:@"TestFMDB.sqlite"];

FMDatabase *db = [FMDatabase databaseWithPath:_dbPath];

2) 使用FMDatabaseQueue 创建 FMDatabaseQueue // 线程安全的数据库队列

objectivec 复制代码
_dbQueue = [FMDatabaseQueue databaseQueueWithPath:_dbPath];

2 .创建表

1) 创建一个设置自动递增主键的表

objectivec 复制代码
NSString *createTableSQL = @"CREATE TABLE IF NOT EXISTS myTable (" @"id INTEGER PRIMARY KEY AUTOINCREMENT, " @"name TEXT, " @"age INTEGER");"

// 执行创建表操作
BOOL success = [db executeUpdate:createTableSQL]; 
if (success) 
{ 
    NSLog(@"表创建成功"); 
} 
else 
{ 
    NSLog(@"表创建失败: %@", [db lastErrorMessage]); 
}

2) 创建一个复合唯一约束的表

objectivec 复制代码
        NSString *createTableSQL = @"CREATE TABLE IF NOT EXISTS AFDBTable ("
        "deviceMac TEXT NOT NULL,"
        "userId TEXT NOT NULL,"
        "timestamp INTEGER,"  // 时间戳(整型)
        "detailData TEXT,"
        "CONSTRAINT unique_dev_user UNIQUE (dev_code, user_id) ON CONFLICT REPLACE"  
// 复合唯一约束 复合约束的名称为 unique_dev_user  ON CONFLICT REPLACE 当发生唯一约束冲突时,用新数据替换现有数据
        ")";

        BOOL success = [db executeUpdate:createTableSQL];
        if (!success) {
            NSLog(@"创建表失败: %@", [db lastError]);
            return;
        }

3.插入数据

1) 普通的插入数据

objectivec 复制代码
    //遇到冲突时替换
    NSString* insertSql = @"INSERT OR REPLACE AFDBTable (deviceMac, userId, timestamp, detailData) VALUES (?, ?, ?, ?)";
    
//    //遇到冲突时忽略
//    insertSql = @"INSERT OR IGNORE AFDBTable (deviceMac, userId, timestamp, detailData) VALUES (?, ?, ?, ?)";
//    
//    //遇到冲突时终止
//    insertSql = @"INSERT OR ABORT AFDBTable (deviceMac, userId, timestamp, detailData) VALUES (?, ?, ?, ?)";
    
    // 在队列中执行操作
    [_dbQueue inDatabase:^(FMDatabase *db) {
        BOOL success = [db executeUpdate:insertSql,
                   @"AFBSADGA-ADFDF", 
                   @"afdsfd",
                   @1768791520,
                   @"1,2,3,4,5"];
        
        if(!success)
        {
            NSLog(@"插入或更新失败");
        }
    }];

2) 通过事务插入,如果其中一条插入失败,可以回滚到些事务执行之前的内容

objectivec 复制代码
    //遇到冲突时替换
    NSString* insertSql = @"INSERT OR REPLACE AFDBTable (deviceMac, userId, timestamp, detailData) VALUES (?, ?, ?, ?)";
    
    [_dbQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
        BOOL success1 = [db executeUpdate:insertSql,
                   @"AFBSADGA-ADFDF",
                   @"afdsfd",
                   @1768791520,
                   @"1,2,3,4,5"];
        
        BOOL success2 = [db executeUpdate:insertSql,
                   @"AFBSADGA-ADFDF",
                   @"gggggggg",
                   @1768791520,
                   @"1,2,3,4,5"];
        
        if(!(success1 && success2))
        {
            *rollback = YES; 
            NSLog(@"插入或更新失败");
        }
    }];

4.查询

objectivec 复制代码
    NSMutableArray<NSDictionary *> *resultArray = [NSMutableArray array];
    NSString *deviceMac = @"AFBSADGA-ADFDF";
    NSString *userId = @"gggggggg";
    if (!deviceMac || !userId) {
        NSLog(@"deviceMac或userId不能为空");

    [_dbQueue inDatabase:^(FMDatabase *db) {
        NSString *querySQL = @"SELECT * FROM AFDBTable "
        "WHERE deviceMac = ? AND userId = ? ;";
        
        FMResultSet *rs = [db executeQuery:querySQL,
                           deviceMac,
                           userId];
        
        while ([rs next]) {
            NSMutableDictionary* dic = [NSMutableDictionary dictionary];
            
            NSString* tmpStr = [rs stringForColumn:@"deviceMac"];
            [dic setValue:tmpStr forKey:@"deviceMac"];
            
            tmpStr = [rs stringForColumn:@"userId"];
            [dic setValue:tmpStr forKey:@"userId"];
            
            long timestamp = [rs longForColumn:@"timestamp"];
            [dic setValue:@(timestamp) forKey:@"timestamp"];
            
            tmpStr = [rs stringForColumn:@"detailData"];
            [dic setValue:tmpStr forKey:@"detailData"];
 
            [resultArray addObject:dic];
        }
        
        [rs close];
    }];

5.常用的查询帮助方法

objectivec 复制代码
// 获取记录总数
int count = [database intForQuery:@"SELECT COUNT(*) FROM users"];
NSLog(@"用户总数: %d", count);

// 获取最大值
int maxAge = [database intForQuery:@"SELECT MAX(age) FROM users"];
NSLog(@"最大年龄: %d", maxAge);

// 获取平均值
double avgAge = [database doubleForQuery:@"SELECT AVG(age) FROM users"];
NSLog(@"平均年龄: %.1f", avgAge);

6.索引的使用

1.创建索引

objectivec 复制代码
if ([self.db beginTransaction]) {
        @try {
            // 创建用户名索引
            [self.db executeUpdate:@"CREATE INDEX IF NOT EXISTS idx_users_name ON users(name)"];
            
            // 创建邮箱唯一索引
            [self.db executeUpdate:@"CREATE UNIQUE INDEX IF NOT EXISTS idx_users_email ON users(email)"];
            
            // 创建复合索引(姓名+年龄)
            [self.db executeUpdate:@"CREATE INDEX IF NOT EXISTS idx_users_name_age ON users(name, age)"];
            
            // 创建条件索引
            [self.db executeUpdate:@"CREATE INDEX IF NOT EXISTS idx_active_users ON users(last_login) WHERE is_active = 1"];
            
            [self.db commit];
            return YES;
        } @catch (NSException *exception) {
            [self.db rollback];
            NSLog(@"创建用户索引失败: %@", exception);
            return NO;
        }
    }

2. 查看所有索相

objectivec 复制代码
    NSMutableArray *indexes = [NSMutableArray array];

    FMResultSet *result = [self.db executeQuery:@"SELECT name, tbl_name, sql FROM sqlite_master WHERE type = 'index'"];

    while ([result next]) {
        NSMutableDictionary *indexInfo = [NSMutableDictionary dictionary];
        indexInfo[@"name"] = [result stringForColumn:@"name"];
        indexInfo[@"table"] = [result stringForColumn:@"tbl_name"];
        indexInfo[@"sql"] = [result stringForColumn:@"sql"];
        [indexes addObject:indexInfo];
    }
    [result close];

3.删除索引

objectivec 复制代码
[self.db executeUpdate:@"DROP INDEX IF EXISTS ?", indexName];
相关推荐
末代iOS程序员华仔13 小时前
Cursor + GitOps:自动化运维新姿势
flutter·ios·swift
世界尽头与你16 小时前
iOS 越狱检测原理
安全·网络安全·ios·信息安全·渗透测试
_瑞2 天前
AI Coding 那么快,为什么还需要 SDD?
人工智能·ios·ai编程
轩辕十四leo2 天前
Astrolabe(星盘):让 AI 看见自己写出的 UI
ios·ai编程
白玉cfc2 天前
熟悉Objective-C
开发语言·ios·objective-c
星辰即远方2 天前
字符串合法性检验
macos·ios·cocoa
末代iOS程序员华仔2 天前
KMP全栈开发:从Android到AI Agent的技术演进与实践
flutter·ios·figma
2501_916008892 天前
苹果上架工具怎么选 不用 Mac 上架 App Store 的几种方案
android·macos·ios·小程序·uni-app·iphone·webview
鹤卿1232 天前
谓词与正则表达式(OC)
ios·正则表达式·objective-c·xcode
秋雨梧桐叶落莳3 天前
iOS——3GShare项目总结
学习·macos·ios·objective-c·cocoa