[英]sqlite iphone best practice for reading data
I'm trying to make an app, that reads from an SQLite3 database. 我正在尝试制作一个从SQLite3数据库读取的应用程序。 I plan to pre-load data during development, so the app does not need to modify anything in the database, only read from it, make queries, etc.
我计划在开发过程中预加载数据,因此该应用程序无需修改数据库中的任何内容,只需从数据库中读取内容,进行查询等即可。
What is the best practice for solely reading data? 仅读取数据的最佳实践是什么? Should I open the database, read the data, and close it, with each query?
我应该在每次查询时打开数据库,读取数据并关闭数据吗? The app will be making many small queries and a few large ones.
该应用程序将进行许多小查询和一些大查询。 Is it better to have the database open for the duration of the app, or open/close it with each fetch?
在应用程序运行期间打开数据库还是在每次获取时打开/关闭数据库,这样更好吗?
Reading: 读:
1. For queries, it's important to re-use compiled statements. 1.对于查询,重用已编译的语句很重要。
2. Make sure you use parameters so you can re-use those compiled queries 2.确保使用参数,以便可以重新使用那些已编译的查询
When you call sqlite3_prepare_v2, it compiles the statement and gives you a reference to the statement back. 当您调用sqlite3_prepare_v2时,它将编译该语句并为您提供对该语句的引用。 Find a way to save that off and re-use it.
找到一种方法可以节省下来并重新使用它。 See the code below for *statement.
请参阅下面的代码以查看* statement。 You pass &statement into prepare.
您通过&statement进行准备。
Also, note the use of ? 另外,请注意使用? for parameters.
用于参数。 If you're going to re-use the statement, it's important to call sqlite3_reset() againt the statement, rebind the inputs from the program (parameters) and execute it again.
如果要重用该语句,请再次调用sqlite3_reset()语句,重新绑定程序(参数)的输入并再次执行,这一点很重要。
sqlite3_stmt *statement;
NSString *querySQL = @"update contacts set name=?,address=?,phone=? where id=?";
NSLog(@"query: %@", querySQL);
const char *query_stmt = [querySQL UTF8String];
// preparing a query compiles the query so it can be re-used.
// find a way to save off the *statement so you can re-use it.
sqlite3_prepare_v2(_contactDb, query_stmt, -1, &statement, NULL);
// use sqlite3_bind_xxx functions to bind in order values to the params
sqlite3_bind_text(statement, 1, [[contact name] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 2, [[contact address] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_text(statement, 3, [[contact phone] UTF8String], -1, SQLITE_STATIC);
sqlite3_bind_int64(statement, 4, [[contact id] longLongValue]);
Always check the return codes! 务必检查返回码! and log or handle the errors.
并记录或处理错误。
rc = sqlite3_step(stmt);
switch (rc)
{
case SQLITE_ROW:
// ...
break;
case SQLITE_OK:
case SQLITE_DONE:
break;
default:
// ....
}
return NO;
}
if you get an error, log or get the eror message to provide more info: 如果出现错误,请登录或获取错误消息以提供更多信息:
- (NSString*)errorMessage
{
return [NSString stringWithCString:sqlite3_errmsg(_sqlite3) encoding:NSUTF8StringEncoding];
}
As per you question you want to read data from database. 按照您的疑问,您想从数据库中读取数据。 So following are the answer of you questions.
因此,以下是您的问题的答案。
- (NSMutableArray *)runSelecteQueryForColumns: (NSArray *)p_columns ontableName: (NSString *)p_tableName withWhereClause: (NSString *)p_whereClause withOrderByClause: (NSString *)p_orederByCalause withGroupByClause: (NSString *)p_groupByClause
{
NSMutableArray *l_resultArray = [[NSMutableArray alloc] init];
if(!self.m_database)
{
if(![self openDatabase])
{
sqlite3_close(self.m_database);
//NSLog(@"error in select : DB creating : %@",p_whereClause);
return nil;
}
}
NSMutableString *l_simpleQuery =[[NSMutableString alloc] initWithString:@"Select"] ;
if(p_columns)
{
for(int l_row = 0 ; l_row < [p_columns count] ; l_row++)
{
if(l_row != [p_columns count]-1)
{
[l_simpleQuery appendString:[NSString stringWithFormat:@" %@,", [p_columns objectAtIndex:l_row]]];
}
else
{
[l_simpleQuery appendString:[NSString stringWithFormat:@" %@", [p_columns objectAtIndex:l_row]]];
}
}
}
else
{
[l_simpleQuery appendString:@" *"];
}
[l_simpleQuery appendString:[NSString stringWithFormat:@" From %@",p_tableName]];
if(p_whereClause)
{
[l_simpleQuery appendString:[NSString stringWithFormat:@" %@",p_whereClause]];
}
if(p_groupByCaluase)
{
[l_simpleQuery appendString:[NSString stringWithFormat:@" %@",p_groupByCaluase]];
}
if(p_orederByCalause)
{
[l_simpleQuery appendString:[NSString stringWithFormat:@" %@",p_orederByCalause]];
}
//NSLog(@"Select Query: - %@",l_simpleQuery);
const char *l_query_stmt = [l_simpleQuery UTF8String];
sqlite3_stmt *l_statement = nil;
int i = sqlite3_prepare_v2(self.m_database,
l_query_stmt, -1, &l_statement, NULL);
if (i == SQLITE_OK)
{
while(sqlite3_step(l_statement) == SQLITE_ROW)
{
[l_resultArray addObject:[self createDictionary:l_statement]];
}
sqlite3_finalize(l_statement);
}
else
{
sqlite3_finalize(l_statement);
//sqlite3_close(l_database);
DDLogError(@"%@ - error in SQL :%@",THIS_FILE,l_simpleQuery);
return nil;
}
//NSLog(@"RESULT %@",l_resultArray);
return l_resultArray;
}
Use sqlite_open_v2
with the SQLITE_OPEN_READONLY
flag. 将
sqlite_open_v2
与SQLITE_OPEN_READONLY
标志一起使用。 For example, I use the following method to open a database for reading only. 例如,我使用以下方法打开一个数据库以供只读。
// Open for reading only.
- (int) openDatabaseAtPath:(NSString *) path
{
if (database != nil)
{
sqlite3_close(self.database);
[self setDatabase:nil];
}
int errorCode = SQLITE_OK;
errorCode = sqlite3_open_v2([path UTF8String],
&database,
SQLITE_OPEN_READONLY,
NULL);
return errorCode;
}
除非将数据库复制到Documents目录,否则将通过资源目录使用DB,并且该目录是只读的。
When you open the database using sqlite_open_v2
and the SQLITE_OPEN_READONLY
flag, SQLite opens the file itself in read-only mode, so even if your application, due to a bug, corrupts memory belonging to SQLite, the database will stay untouched. 当您使用
sqlite_open_v2
和SQLITE_OPEN_READONLY
标志打开数据库时,SQLite会以只读模式打开文件本身,因此,即使您的应用程序由于错误而损坏了属于SQLite的内存,数据库也将保持不变。
With this in mind, I'd keep the database open until the application quits. 考虑到这一点,我将保持数据库打开状态直到应用程序退出。 (You may wish to close it if you receive a low-memory notification and reopen it on demand, but opening and closing it for every query would be wasteful.)
(如果收到内存不足的通知,请关闭它,然后按需重新打开它,但是为每个查询打开和关闭它都是浪费时间。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.