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];
相关推荐
游戏开发爱好者86 小时前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview
黑码哥6 小时前
ViewHolder设计模式深度剖析:iOS开发者掌握Android列表性能优化的实战指南
android·ios·性能优化·跨平台开发·viewholder
2501_915106328 小时前
app 上架过程,安装包准备、证书与描述文件管理、安装测试、上传
android·ios·小程序·https·uni-app·iphone·webview
2501_915106328 小时前
使用 Sniffmaster TCP 抓包和 Wireshark 网络分析
网络协议·tcp/ip·ios·小程序·uni-app·wireshark·iphone
熊猫钓鱼>_>8 小时前
移动端开发技术选型报告:三足鼎立时代的开发者指南(2026年2月)
android·人工智能·ios·app·鸿蒙·cpu·移动端
徐同保1 天前
通过ip访问nginx的服务时,被第一个server重定向了,通过设置default_server解决这个问题
ios·iphone
2501_915918411 天前
在 iOS 环境下查看 App 详细信息与文件目录
android·ios·小程序·https·uni-app·iphone·webview
2501_916007471 天前
没有 Mac 用户如何上架 App Store,IPA生成、证书与描述文件管理、跨平台上传
android·macos·ios·小程序·uni-app·iphone·webview
夏幻灵2 天前
HTTPS全面解析:原理、加密机制与证书体
ios·iphone
TheNextByte12 天前
如何在iPhone上恢复已删除的笔记的综合指南
笔记·ios·iphone