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];
相关推荐
用户223586218201 天前
WebKit WebPage API 的引入尝试与自研实现
ios
啦啦啦!1 天前
ChatGPT和Gemini的接入和封装
人工智能·ios·chatgpt
报错小能手1 天前
ios开发方向——swift并发进阶核心 async/await 详解
开发语言·ios·swift
开心就好20251 天前
HTTPS超文本传输安全协议全面解析与工作原理
后端·ios
牛马1111 天前
Flutter iOS 权限配置完整指南(定位权限)
flutter·ios
A_QXBlms1 天前
多账号轮询架构 — 利用企销宝iPad协议突破单账号群发次数限制
ios·架构·ipad
HH思️️无邪1 天前
Flutter + iOS 实战指南:教程视频 PiP + 退桌面(可复用模板)
flutter·ios
亘元有量-流量变现1 天前
深度技术对比:Android、iOS、鸿蒙(HarmonyOS)权限管理全解析
android·ios·harmonyos·方糖试玩
sunz_dragon1 天前
iPhone_签到App_自动化实战
ios·自动化·iphone
Digitally1 天前
如何轻松地使用隔空投送将iPhone内容传输到Android
android·ios·iphone