我有一个名为VegQuantity的视图控制器,它执行totalcost =(数量*盘子的成本)并将itemname,quantity,totalcost插入名为FINALORDER的表中,数据库名称为FinalOrder
sqlite3_stmt *statement;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &FinalOrder) == SQLITE_OK)
{
NSString *insertSQL = [NSString stringWithFormat: @"INSERT INTO FINALORDER (itemname, quantity, totalcost) VALUES (\"%@\", \"%@\", \"%@\")", itemName.text, input.text, output.text];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(FinalOrder, insert_stmt, -1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
// status.text = @"Contact added";
// name.text = @"";
// address.text = @"";
// phone.text = @"";
NSLog(@"added");
} else {
NSLog(@"Couldnt add");
}
sqlite3_finalize(statement);
sqlite3_close(FinalOrder);
}
Final View Controller viewdidload方法
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &FinalOrder) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat: @"SELECT * FROM FINALORDER"];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(FinalOrder, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *itemname = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
item.text = itemname;
NSString *qua = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)];
quantity.text = qua;
NSString *total = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)];
totalcost.text=total;
}
sqlite3_finalize(statement);
}
sqlite3_close(FinalOrder);
}
但是我在FinalOrder之前一直得到这个名为expected expression的错误,我在viewdidload中编写这段代码是否正确?我在最终视图控制器中没有任何按钮我在一个名为Restaurant的视图控制器中有一个名为order的按钮,它实际上显示了我最终视图控制器..我应该在Final viewcontroller中再次搜索db文件,我很抱歉问题看起来有点模糊,但简而言之,我只是想知道如何检索和显示我在VegQuantity视图控制器中插入到最终视图控制器中的数据,谢谢
答案 0 :(得分:0)
我认为问题必须放在FinalOrder
的定义中,在{1}}的定义中,基于错误消息,看起来已被定义为类,而不是sqlite3 *
变量。鉴于您使用数据库的范围仅限于这两种方法,我建议在该范围内定义sqlite3 *
,并使用它,例如:
- (void)saveRecord
{
sqlite3 *database;
sqlite3_stmt *statement;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
[self purgeTable:database];
NSString *insertSQL = @"INSERT INTO FINALORDER (itemname, quantity, totalcost) VALUES (?, ?, ?)";
if (sqlite3_prepare_v2(database, [insertSQL UTF8String], -1, &statement, NULL) == SQLITE_OK)
{
sqlite3_bind_text(statement, 1, [itemName.text UTF8String], -1, NULL);
sqlite3_bind_int(statement, 2, [input.text intValue]);
sqlite3_bind_double(statement, 3, [output.text doubleValue]);
if (sqlite3_step(statement) == SQLITE_DONE)
{
// status.text = @"Contact added";
// name.text = @"";
// address.text = @"";
// phone.text = @"";
NSLog(@"added");
} else {
NSLog(@"%s Couldn't add; errmsg='%s'", __FUNCTION__, sqlite3_errmsg(database));
}
sqlite3_finalize(statement);
} else {
NSLog(@"%s Couldn't prepare; errmsg='%s'", __FUNCTION__, sqlite3_errmsg(database));
}
sqlite3_close(database);
}
}
注意,除了为数据库使用sqlite3 *
变量之外,还要使其更加健壮:
我已使用stringWithFormat
语句替换了构建SQL insert语句的INSERT
语句,该语句使用?
占位符,然后使用sqlite3_bind_text
绑定值那个声明。这样,如果有人输入了包含引号的值,则insert语句仍然有效(原始实现会崩溃和/或容易受到SQL注入攻击)。
我还添加了sqlite3_errmsg
语句,如果出现问题,我知道问题所在。
我不是将这三个字段视为文本字段,而是假设您的表定义为CREATE TABLE IF NOT EXISTS FINALORDER (itemname TEXT, quantity INT, totalcost REAL);
,因此使用text,int和double绑定语句。
顺便提一下,这会调用purgeTable
方法,所以如果你运行两次,它会删除那里的旧记录:
- (void)purgeTable:(sqlite3 *)database
{
if (sqlite3_exec(database, "DELETE FROM FINALORDER;", NULL, NULL, NULL) != SQLITE_OK)
NSLog(@"%s Couldn't purge table %s", __FUNCTION__, sqlite3_errmsg(database));
}
无论如何,您可以通过以下方式阅读此数据:
- (void)loadRecord
{
sqlite3 *database;
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *querySQL = @"SELECT * FROM FINALORDER";
if (sqlite3_prepare_v2(database, [querySQL UTF8String], -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *itemname = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
item.text = itemname;
//[itemname release]; // if not ARC, uncomment this line
int qua = sqlite3_column_int(statement, 1);
quantity.text = [NSString stringWithFormat:@"%1d", qua];
double total = sqlite3_column_double(statement, 2);
totalcost.text = [NSString stringWithFormat:@"%1.2f", total];
}
sqlite3_finalize(statement);
} else {
NSLog(@"%s Couldn't prepare; errmsg='%s'", __FUNCTION__, sqlite3_errmsg(database));
}
sqlite3_close(database);
}
}
注意,
如果sqlite3_errmsg
失败,我已添加了sqlite3_prepare
日志语句,并且我已经退出stringWithFormat
(因为您没有格式化任何内容)。
鉴于quantity
为INT
且total
为REAL
,我正在使用sqlite3_column_text
的适当变体检索值,{ {1}}或sqlite3_column_int
,视情况而定。
我推断您没有使用ARC,因此sqlite3_column_double
必须有关联的[NSString alloc]
或release
。
最后,在我们的聊天中,您说您收到了一条错误消息(可能是“Undefined Symbols”消息),上面写着:
autorelease
这意味着您正在尝试使用OBJC_CLASS_$"_FinalOrder"
的对象类,但您没有在任何地方定义该类。看看它报告此错误的.o文件,并查看相应的.m文件,并在那里查找您对FinalOrder
类的使用情况。您显然在某处定义了FinalOrder
类接口,但从未定义类实现,或者,如果您有一个,由于某种原因它没有包含在目标的“编译源”列表中,所以仔细检查它在这里:< / p>
顺便说一下,确保您的数据库位于FinalOrder
文件夹中,而不是尝试在项目的包中打开数据库的副本(因为这是只读的)。如果您的数据库中包含数据库的副本,只需检查您是否已将其存储在Documents
文件夹中,如果没有,请将其从包中复制到Documents
文件夹。