V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
kobe1941
V2EX  ›  iDev

sqlite3 如何判断一个表是否已经存在于数据库中?

  •  
  •   kobe1941 · 2014-12-01 20:48:44 +08:00 · 15637 次点击
    这是一个创建于 3622 天前的主题,其中的信息可能已经有所发展或是发生改变。
    如题,不适用fmdb,直接用原生的sqlite3函数,怎么才能知道一个表是否已经存在呢?
    目前sqlite3普通的增删查改没什么问题,但是为了进一步封装,我把表的名字抽出来了以供外部调用接口的时候自定义名字,现在纠结的地方在于,清除一个表的数据和删掉一个表,我打算加一个方法来判断传入的表名是否已经存在,如果不存在则给出提示。目前卡在了这一步,网上找到的方法基本都是用FMDB的,纯sqlite3有一个方法,我试了下不能用,特来请教各位,如何判断呢?

    我自己写的方法:
    - (BOOL)isTableExist:(NSString *)aTableName
    {
    char *err;

    NSString *judgeString = [NSString stringWithFormat:@"SELECT COUNT(*) FROM sqlite_master where type ='table' and name = '%@'",aTableName];

    const char *sql_stmt = [judgeString UTF8String];

    int result = sqlite3_exec(_database, sql_stmt, NULL, NULL, &err);

    if(result == SQLITE_OK)
    {
    // 怎么判断数量?


    return YES;
    }

    NSLog(@"sql执行错误:%s",err);

    return NO;
    }

    附上网上不能用的代码:
    http://blog.csdn.net/xxc88888/article/details/9495491
    该链接的第三个方法,感觉原博主还没有理解写的那条SQL语句的意思。

    个人认为,执行该SQL语句后,返回的应该是执行的状态,是否成功或者有错误,而不是我们所要的数据中该表的数量,那我怎么才能知道数据中该表的数量呢?
    18 条回复    2014-12-02 16:27:22 +08:00
    iluhcm
        1
    iluhcm  
       2014-12-01 20:52:11 +08:00
    你会查表中的数据,难道还不能查表的名字么?我觉得是方法用错了。你查询数据的时候是怎么返回数据格式的?
    Fedor
        2
    Fedor  
       2014-12-01 21:42:05 +08:00 via iPhone
    select * from sqlite_master
    lldld
        3
    lldld  
       2014-12-01 22:35:12 +08:00
    没试过你这种sql语句, 不过看起来应该是在callback里面操作:

    int sqlite3_exec(
    sqlite3*, /* An open database */
    const char *sql, /* SQL to be evaluated */
    int (*callback)(void*,int,char**,char**), /* Callback function */
    void *, /* 1st argument to callback */
    char **errmsg /* Error msg written here */
    );
    lldld
        4
    lldld  
       2014-12-01 22:44:12 +08:00
    google "sqlite3 check table exists" 有很多答案. 比如这个看起来应该是对的:

    源地址 : http://stackoverflow.com/questions/1601151/how-do-i-check-in-sqlite-whether-a-table-exists

    boolean isTableExists(SQLiteDatabase db, String tableName)
    {
    if (tableName == null || db == null || !db.isOpen())
    {
    return false;
    }
    Cursor cursor = db.rawQuery("SELECT COUNT(*) FROM sqlite_master WHERE type = ? AND name = ?", new String[] {"table", tableName});
    if (!cursor.moveToFirst())
    {
    return false;
    }
    int count = cursor.getInt(0);
    cursor.close();
    return count > 0;
    }
    kingme
        5
    kingme  
       2014-12-01 22:45:13 +08:00
    try {} 23333333333
    kobe1941
        6
    kobe1941  
    OP
       2014-12-02 09:30:37 +08:00
    @iluhcm 你好,我查询数据是用另一种方式,跟查询表名不一样,都是从网上学来的,sqlite3真心第一次玩,数据库也是第一次玩。代码在这里:
    - (NSArray *)getAllPersonsWithTableName:(NSString *)aTableName
    {
    [self openSqliteDatabase];


    if (![self isTableExist:aTableName])
    {
    NSLog(@"要查询的表不存在,请检查表名");
    return nil;
    }

    NSString *query = [NSString stringWithFormat:@"select * from '%@'",aTableName];

    sqlite3_stmt *stmt;

    NSMutableArray *mutable = [NSMutableArray array];

    int result = sqlite3_prepare_v2(_database, [query UTF8String], -1, &stmt, nil);

    if (result == SQLITE_OK)
    {
    while (sqlite3_step(stmt) == SQLITE_ROW)
    {
    unsigned int ID = (int)sqlite3_column_int(stmt, 0);


    char *name = (char *)sqlite3_column_text(stmt, 1);
    NSString *nameString = [[NSString alloc] initWithUTF8String:name];

    char *desc = (char *)sqlite3_column_text(stmt, 2);
    NSString *descString = [[NSString alloc] initWithUTF8String:desc];

    NSLog(@"id =%d,name = %s,desc = %s",ID,name,desc);

    Person *person = [[Person alloc] initWithName:nameString desc:descString];
    [mutable addObject:person];
    }

    sqlite3_finalize(stmt);

    } else
    {
    NSLog(@"result = %d,SQL error or missing database",result);
    }

    sqlite3_close(_database);

    return mutable;
    }
    kobe1941
        7
    kobe1941  
    OP
       2014-12-02 09:33:31 +08:00
    @Fedor 你好,SQL语句是这样子的,不过我不确定用哪种方式执行,我用 sqlite3_exec的方式执行后,该函数返回的应该是语句执行的状态吧?比如执行成功或者失败,但是怎么获取我想要的结果呢?我执行语句后怎么判断表是否已经存在?谢谢!
    kobe1941
        8
    kobe1941  
    OP
       2014-12-02 09:35:45 +08:00
    @lldld 感谢,不过这个是另一个平台的查询方式,Cursor看不懂是什么东西,我真的是数据库的新手啊亲,请见谅。请问能再详细些么?
    Fedor
        9
    Fedor  
       2014-12-02 09:47:05 +08:00   ❤️ 1
    @kobe1941
    sqlite_exec 只是执行不会返回结果。
    应该先 sqlite_query 查询, 然后 sqlite_fetch_object/fetch_array 获取查询的结果。
    kobe1941
        10
    kobe1941  
    OP
       2014-12-02 09:50:56 +08:00
    @Fedor 谢谢,我试试看
    kobe1941
        11
    kobe1941  
    OP
       2014-12-02 09:52:53 +08:00
    @Fedor 亲,目测没有这两个函数呀
    Fedor
        12
    Fedor  
       2014-12-02 10:12:30 +08:00
    sqlite_fetch_object 是php里的, 对应的你找下文档呗。
    iluhcm
        13
    iluhcm  
       2014-12-02 11:07:27 +08:00
    @kobe1941 查询返回的结果肯定不是int啊。。。看你用的是什么语言了,上边的Cursor是在Android里用的,Java用ResultSet~
    kobe1941
        14
    kobe1941  
    OP
       2014-12-02 11:56:28 +08:00
    @iluhcm
    @Fedor
    @lldld 感谢各位,我换了一种方式,已经解决。

    以下是代码:

    #pragma mark - 判断该表是否存在
    - (BOOL)isTableExist:(NSString *)aTableName
    {
    BOOL exist = NO;
    sqlite3_stmt *stmt;

    NSString *judgeString = [NSString stringWithFormat:@"SELECT name FROM sqlite_master where type ='table' and name = '%@';",aTableName];
    const char *sql_stmt = [judgeString UTF8String];

    if (sqlite3_prepare_v2(_database, sql_stmt, -1, &stmt, nil) == SQLITE_OK)
    {
    int temp = sqlite3_step(stmt);
    if (temp == SQLITE_ROW)
    {
    exist = YES;
    } else
    {
    NSLog(@"temp = %d",temp);
    }
    }

    sqlite3_finalize(stmt);

    return exist;
    }

    我改了SQL语句,我的理解是执行该语句,结果集里如果有数据,则证明这个表存在,否则不存在。测试通过。
    虽然解决了,但还是遗留下两个问题:
    1.sqlite_exec函数返回的是状态,如果用这个函数来解决本问题,要获取数据库中该表的数量,目测需要另外操作?比如回调函数什么的
    2.采用目前使用的sqlite3_prepare_v2函数,SQL用最初的@"SELECT COUNT(*) FROM sqlite_master where type ='table' and name = '%@'",aTableName.怎么获取这个数量呢(count)?

    贴一个连接: http://blog.csdn.net/ryantang03/article/details/7781930,这里的代码注释适合跟我一样的新手
    kobe1941
        15
    kobe1941  
    OP
       2014-12-02 11:57:52 +08:00
    V2EX的编辑功能真是蛋疼,代码不能缩进,连接跟文字混淆。
    railgun
        16
    railgun  
       2014-12-02 12:33:33 +08:00
    为什么不用FMDB?都封装好了
    @kobe1941 可以在gits上把代码编辑好了发链接过来
    kobe1941
        17
    kobe1941  
    OP
       2014-12-02 14:30:36 +08:00
    @railgun FMDB我之前用来测试过,把表名字抽出来有点问题,另因为是初学,不打算用封装的太上层的库,了解一下底层还是不错的。另外,代码上传到gitHub这个我还要再研究下,之前没上传过。
    railgun
        18
    railgun  
       2014-12-02 16:27:22 +08:00
    @kobe1941 不好意思,记错了,应该是gist,https://gist.github.com/ 专门贴代码片段的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5037 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 05:40 · PVG 13:40 · LAX 22:40 · JFK 01:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.