我遵循了一个关于创建SQLite数据库,存储东西并找到它的教程。 我没有做的是创建界面,因为控制台日志记录可以更快。 (这也不需要其他人建立interace,但不要忘记导入库!:))
这是重要的教程: http://www.techotopia.com/index.php/An_Example_SQLite_based_iOS_6_iPhone_Application
我在查找数据时遇到问题,有人知道它可能是什么吗?
- (void) findContact {
const char *dbpath = [_databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK) {
NSString *querySQL = [NSString stringWithFormat:
@"SELECT adress, phone FROM contacts WHERE name=\"%@\"", @"DoekeW"];
const char *query_stmt = [querySQL UTF8String];
if(sqlite3_prepare_v2(_contactDB, query_stmt, -1, &statement, NULL) == SQLITE_OK) {
if(sqlite3_step(statement) == SQLITE_ROW) {
NSString *adressField = [[NSString alloc] initWithUTF8String:
(const char*) sqlite3_column_text(statement, 0)];
NSString *phoneField = [[NSString alloc] initWithUTF8String:
(const char*) sqlite3_column_text(statement, 1)];
NSLog(@"adressField: %@ phoneField: %@", adressField, phoneField);
}
else {
NSLog(@"no match");
}
sqlite3_finalize(statement);
}
else {
// 1, whatever that is
NSLog(@"hmm %d", sqlite3_prepare_v2(_contactDB, query_stmt, -1, &statement, NULL));
}
sqlite3_close(_contactDB);
}
}
这是完整的代码:
.h文件:
#import <UIKit/UIKit.h>
#import <sqlite3.h>
@interface IGViewController : UIViewController
@property (strong, nonatomic) NSString *databasePath;
@property (nonatomic) sqlite3 *contactDB;
@end
.m文件
#import "IGViewController.h"
@interface IGViewController ()
@end
@implementation IGViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *docsDir;
NSArray *dirPaths;
// Get the documents directory
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = dirPaths[0];
// Build the path to the database file
_databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent:@"contacts.db"]];
NSLog(@"%@", _databasePath);
NSFileManager *filemgr = [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath: _databasePath] == NO) {
const char *dbpath = [_databasePath UTF8String];
if(sqlite3_open(dbpath, &_contactDB) == SQLITE_OK) {
char *errMsg;
const char *sql_stmt =
"CREATE TABLE IF NOT EXISTS CONTACTS (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, ADDRESS TEXT, PHONE TEXT)";
if (sqlite3_exec(_contactDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK)
{
//_status.text = @"Failed to create table";
NSLog(@"Failed to create table");
}
sqlite3_close(_contactDB);
} else {
// _status.text = @"Failed to open/create database";
NSLog(@"Failed to open/create database");
}
}
else {
NSLog(@"database allready existed");
}
[self saveData];
[self findContact];
}
- (void) saveData {
sqlite3_stmt *statement;
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK) {
NSString *insertSQL = [NSString stringWithFormat:
@"INSERT INTO CONTACTS (name, address, phone) VALUES (\"%@\", \"%@\", \"%@\")",
@"DoekeW", @"Molenstraat", @"483577"];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(_contactDB, insert_stmt, -1, &statement, NULL);
if(sqlite3_step(statement) == SQLITE_DONE) {
NSLog(@"saved data!");
}
else {
NSLog(@"something wrong, no data saved");
}
sqlite3_finalize(statement);
sqlite3_close(_contactDB);
}
}
- (void) findContact {
const char *dbpath = [_databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK) {
NSString *querySQL = [NSString stringWithFormat:
@"SELECT adress, phone FROM contacts WHERE name=\"%@\"", @"DoekeW"];
const char *query_stmt = [querySQL UTF8String];
if(sqlite3_prepare_v2(_contactDB, query_stmt, -1, &statement, NULL) == SQLITE_OK) {
if(sqlite3_step(statement) == SQLITE_ROW) {
NSString *adressField = [[NSString alloc] initWithUTF8String:
(const char*) sqlite3_column_text(statement, 0)];
NSString *phoneField = [[NSString alloc] initWithUTF8String:
(const char*) sqlite3_column_text(statement, 1)];
NSLog(@"adressField: %@ phoneField: %@", adressField, phoneField);
}
else {
NSLog(@"no match");
}
sqlite3_finalize(statement);
}
else {
// 1, whatever that is
NSLog(@"hmm %d", sqlite3_prepare_v2(_contactDB, query_stmt, -1, &statement, NULL));
}
sqlite3_close(_contactDB);
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
答案 0 :(得分:0)
NSLog
中有一条findContact
声明:
NSLog(@"hmm %d", sqlite3_prepare_v2(_contactDB, query_stmt, -1, &statement, NULL));
你绝对不想在失败时再次准备。您只想检索错误消息。因此它应该是:
NSLog(@"prepare failed: %s", sqlite3_errmsg(_contactDB));
如果您这样做,您将收到一条错误消息,指出SQL语句中address
的拼写错误。
坦率地说,几乎每个SQLite调用都应检查其结果,如果不是SQLITE_OK
(SQLITE_ROW
或SQLITE_DONE
sqlite3_step
),则应报告sqlite3_errmsg
。
采用sqlite3_errmsg
时,您会发现错误的速度更快。让SQLite准确地告诉你问题是什么!
顺便说一句,我也建议:
我还建议您不要使用stringWithFormat
构建SQL语句。如果个人姓名是Dwayne "The Rock" Johnson
,则会出现问题。相反,您应该使用?
占位符。 (你也容易受到SQL注入攻击。)底线,而不是:
NSString *insertSQL = [NSString stringWithFormat:
@"INSERT INTO CONTACTS (name, address, phone) VALUES (\"%@\", \"%@\", \"%@\")",
@"DoekeW", @"Molenstraat", @"483577"];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(_contactDB, insert_stmt, -1, &statement, NULL);
if(sqlite3_step(statement) == SQLITE_DONE) {
NSLog(@"saved data!");
}
else {
NSLog(@"something wrong, no data saved");
}
sqlite3_finalize(statement);
你应该使用:
const char *insert_stmt = "INSERT INTO CONTACTS (name, address, phone) VALUES (?, ?, ?)";
if (sqlite3_prepare_v2(_contactDB, insert_stmt, -1, &statement, NULL) != SQLITE_OK)
NSLog(@"%s: prepare error: %s", __FUNCTION__, sqlite3_errmsg(_contactDB));
if (sqlite3_bind_text(statement, 1, [@"DoekeW" UTF8String], -1, NULL) != SQLITE_OK)
NSLog(@"%s: bind 1 error: %s", __FUNCTION__, sqlite3_errmsg(_contactDB));
if (sqlite3_bind_text(statement, 2, [@"Molenstraat" UTF8String], -1, NULL) != SQLITE_OK)
NSLog(@"%s: bind 2 error: %s", __FUNCTION__, sqlite3_errmsg(_contactDB));
if (sqlite3_bind_text(statement, 3, [@"483577" UTF8String], -1, NULL) != SQLITE_OK)
NSLog(@"%s: bind 3 error: %s", __FUNCTION__, sqlite3_errmsg(_contactDB));
if(sqlite3_step(statement) == SQLITE_DONE) {
NSLog(@"saved data!");
}
else {
NSLog(@"%s: step error: %s", __FUNCTION__, sqlite3_errmsg(_contactDB));
}
sqlite3_finalize(statement);
基本上,使用sqlite3_bind_text
将值绑定到这些?
占位符,并完全取消stringWithFormat
。 WHERE
语句的SELECT
子句也是如此。
我是第二个Anupdas使用FMDB的建议。它使SQLite编码更容易。