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];
相关推荐
for_ever_love__7 小时前
UI学习:UICollectionView瀑布流
学习·ui·ios·objective-c·cocoa
大熊猫侯佩11 小时前
WWDC26 全网首发:SwiftUI 8 “可重排序“操作符深度解析
ios·swiftui·swift
邓小乐12 小时前
Workaround: Xcode27 下载iOS 27.0 Simulator
ios·xcode
韩曙亮13 小时前
【Flutter】Flutter 中的 Android / iOS 特殊配置 ① ( 网络权限配置 | HTTP 明文传输配置 | 应用名称配置 )
android·网络·flutter·http·ios·网络权限
人月神话-Lee15 小时前
【图像处理】颜色空间——RGB之外的世界
图像处理·人工智能·ios·ai编程·swift·rgb·颜色空间
CocoaKier15 小时前
苹果后台年龄分级填写错误,可能导致审核被拒!
ios·apple
月诸清酒15 小时前
Codex 现在能在浏览器里跑 iOS 模拟器了
ios
武子康17 小时前
调查研究-159 Apple WWDC 2026 定档 6/8-12:Siri 与 AI 升级,可能是苹果最关键的一次
人工智能·深度学习·ios·ai·chatgpt·apple·wwdc
2601_9611940217 小时前
27考研资料|百度网盘|夸克网盘
android·xml·考研·ios·iphone·xcode·webview