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

2014-12-01 20:48:44 +08:00
 kobe1941
如题,不适用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语句后,返回的应该是执行的状态,是否成功或者有错误,而不是我们所要的数据中该表的数量,那我怎么才能知道数据中该表的数量呢?
15655 次点击
所在节点    iDev
18 条回复
iluhcm
2014-12-01 20:52:11 +08:00
你会查表中的数据,难道还不能查表的名字么?我觉得是方法用错了。你查询数据的时候是怎么返回数据格式的?
Fedor
2014-12-01 21:42:05 +08:00
select * from sqlite_master
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
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
2014-12-01 22:45:13 +08:00
try {} 23333333333
kobe1941
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
2014-12-02 09:33:31 +08:00
@Fedor 你好,SQL语句是这样子的,不过我不确定用哪种方式执行,我用 sqlite3_exec的方式执行后,该函数返回的应该是语句执行的状态吧?比如执行成功或者失败,但是怎么获取我想要的结果呢?我执行语句后怎么判断表是否已经存在?谢谢!
kobe1941
2014-12-02 09:35:45 +08:00
@lldld 感谢,不过这个是另一个平台的查询方式,Cursor看不懂是什么东西,我真的是数据库的新手啊亲,请见谅。请问能再详细些么?
Fedor
2014-12-02 09:47:05 +08:00
@kobe1941
sqlite_exec 只是执行不会返回结果。
应该先 sqlite_query 查询, 然后 sqlite_fetch_object/fetch_array 获取查询的结果。
kobe1941
2014-12-02 09:50:56 +08:00
@Fedor 谢谢,我试试看
kobe1941
2014-12-02 09:52:53 +08:00
@Fedor 亲,目测没有这两个函数呀
Fedor
2014-12-02 10:12:30 +08:00
sqlite_fetch_object 是php里的, 对应的你找下文档呗。
iluhcm
2014-12-02 11:07:27 +08:00
@kobe1941 查询返回的结果肯定不是int啊。。。看你用的是什么语言了,上边的Cursor是在Android里用的,Java用ResultSet~
kobe1941
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
2014-12-02 11:57:52 +08:00
V2EX的编辑功能真是蛋疼,代码不能缩进,连接跟文字混淆。
railgun
2014-12-02 12:33:33 +08:00
为什么不用FMDB?都封装好了
@kobe1941 可以在gits上把代码编辑好了发链接过来
kobe1941
2014-12-02 14:30:36 +08:00
@railgun FMDB我之前用来测试过,把表名字抽出来有点问题,另因为是初学,不打算用封装的太上层的库,了解一下底层还是不错的。另外,代码上传到gitHub这个我还要再研究下,之前没上传过。
railgun
2014-12-02 16:27:22 +08:00
@kobe1941 不好意思,记错了,应该是gist,https://gist.github.com/ 专门贴代码片段的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/150748

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX