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];
相关推荐
2501_915909062 小时前
原生与 H5 共存情况下的测试思路,混合开发 App 的实际测试场景
android·ios·小程序·https·uni-app·iphone·webview
app开发工程师V帅2 小时前
Xcode *****exited with status 0. The command had no output.
ios
游戏开发爱好者83 小时前
了解 Xcode 在 iOS 开发中的作用和功能有哪些
android·ios·小程序·https·uni-app·iphone·webview
Digitally8 小时前
如何将文件从 iPhone 传输到 Android
android·ios·iphone
2501_915106328 小时前
iOS 抓包工具实战实践指南,围绕代理抓包、数据流抓包和拦截器等常见工具
android·ios·小程序·https·uni-app·iphone·webview
TheNextByte18 小时前
如何从备份还原 iPhone?
ios·iphone
恋猫de小郭8 小时前
Flutter 又迎大坑修改?iOS 26 键盘变化可能带来大量底层改动
android·flutter·ios·kotlin
摘星编程9 小时前
React Native for OpenHarmony 实战:DatePickerIOS iOS日期选择器
react native·react.js·ios
2501_915106329 小时前
如何在 iOS 设备上理解和分析 CPU 使用率(windows环境)
android·ios·小程序·https·uni-app·iphone·webview