Mysql 如何为sqlite中的每个会话(对于iOS)向同一行插入所有新值

Mysql 如何为sqlite中的每个会话(对于iOS)向同一行插入所有新值,mysql,ios,sql,objective-c,sqlite,Mysql,Ios,Sql,Objective C,Sqlite,我似乎不能完全理解这个数据库问题 首先,我应该从一开始就打开我的db连接并保持它一直打开直到应用程序进入后台吗?还是应该每次插入新的db连接时打开并关闭它 我的开放连接方法 NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDir = [docPaths objectAtIndex:0];

我似乎不能完全理解这个数据库问题

首先,我应该从一开始就打开我的db连接并保持它一直打开直到应用程序进入后台吗?还是应该每次插入新的db连接时打开并关闭它

我的开放连接方法

    NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDir = [docPaths objectAtIndex:0];
    NSString *dbPath = [documentsDir   stringByAppendingPathComponent:@"insider.sqlite"];

    FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
    [database open];
    [database executeUpdate:@"create table if not exists userInfo (device_token text primary key, device_type text, carrier text, app_version text,os_version text, first_name text, last_name text,last_viewed_item text, last_added_item text, last_item_price_tag text, name_entered integer, login_screen integer, item_detailed_screen integer,item_selected integer )"];
   // [database close];
我使用此方法启动应用程序(在appDelegate ApplicationIDFinishLauch中),但在会话期间,我希望将所有新数据保存到同一行

但是我用的这个方法

-(void)getUserFirstName:(NSString *)firstName {

    NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDir = [docPaths objectAtIndex:0];
    NSString *dbPath = [documentsDir   stringByAppendingPathComponent:@"insider.sqlite"];

    FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
    [database open];
    [database executeUpdate:@"INSERT INTO userInfo (first_name) VALUES (?)",firstName];
    [database close];   

}
还有我的另一种方法

-(void)getUserLastName:(NSString *)lastname {
     NSLog(@"soyisim giriliyo");

    NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDir = [docPaths objectAtIndex:0];
    NSString *dbPath = [documentsDir   stringByAppendingPathComponent:@"insider.sqlite"];

    FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
    [database open];
    [database executeUpdate:@"INSERT INTO userInfo (last_name) VALUES (?)",lastname];
    [database close];


}
但是当我保存这些并试图收集它们时,我得到了这个

2014-09-07 20:26:08.522 PushChat[2974:60b] first Name: Frank
 lastname: (null)
2014-09-07 20:26:08.522 PushChat[2974:60b] first Name:: (null)
 lastname: Jemmyson
2014-09-07 20:26:08.522 PushChat[2974:60b] first Name: george
 lastname: (null)
2014-09-07 20:26:08.522 PushChat[2974:60b] first Name: (null)
 lastname: herose
我得到每行的字段值

我试图更改我的create table方法并添加了
id integer主键,
,但在另一次插入过程中,我无法跟踪此会话id,我认为这对性能没有好处

我总共得到了13个字段,其中一些字段可能为空,但在一个会话中,所有字段必须在同一行中


提前感谢

如果我正确理解了您的问题,您希望在每次新会话时在数据库中创建一个新条目。所以只需给你的会话一个ID(即一个随机数),并将其存储在你的应用程序中。如果数据库中已存在该ID,请选择一个新ID。如果没有,请插入新行。您的ID应该是主键

因此,现在除了ID之外,所有值都为null。如果要添加/更改此特定ID的值,只需执行如下操作:

NSString *sql = [NSString stringWithFormat:@"UPDATE userInfo SET last_name = \"%@\" WHERE id = %@", lastname, uniqueSessionID];
PS:是的,您应该在每次使用时打开和关闭连接,而不是一直保持打开状态。开放式连接占用了可以在其他地方使用的资源。

一些想法:

  • 为什么有两种方法插入名字和姓氏?你需要吗?为什么不在一条SQL语句中执行此操作

  • 假设您必须在像这样的单独语句中执行第二个SQL语句,第一个语句应该是
    INSERT
    ,第二个SQL语句应该是
    UPDATE

  • 如果需要,SQLite可以为您跟踪行的唯一标识符。因此,添加一个名为
    user\u info\u id integer primary key autoincrement
    的列。然后,在插入数据后,立即查看
    [database lastInsertRowId]
    ,这将返回为
    用户信息id
    列自动生成的值

    因此,回到前一点,您将插入一个名为的行,立即检索
    lastInsertRowId
    ,然后将其作为
    UPDATE
    语句中设置姓氏的
    WHERE
    子句的参数,例如

    success = [database executeUpdate:@"UPDATE userInfo SET last_name = ? WHERE user_info_id = ?", lastName, @(rowIdValue)];
    
    请注意,
    user\u info\u id
    的值可能存储在
    sqlite\u int64
    变量中(例如,
    lastInsertRowId
    方法返回的值),因此当您在
    executeUpdate
    调用中使用该值时,请将其包装为
    NSNumber

  • 虽然FMDB在将值绑定到列等方面为您节省了很多麻烦,但您仍然应该检查返回值(通常是FMDB中的
    BOOL
    值)。如果失败,请记录
    [database lastErrorMessage]

  • 不要为每个SQL语句打开和关闭数据库。打开数据库一次并保持其打开状态。它会在执行时自动提交
    INSERT
    /
    UPDATE
    语句,因此非常健壮


  • 不要使用
    stringWithFormat
    构建SQL语句!OP使用
    占位符是一种更好的做法!我想你永远也学不会。你能解释一下为什么它好得多吗?因为如果用户碰巧键入了带有双引号的内容,你的SQL就会失败。您还容易受到SQL注入攻击。始终使用
    占位符,然后使用
    sqlite3_bind_XXX
    函数(或者使用FMDB,它可以为您完成所有这些)。我在存储和检索uniqSessionID时遇到问题,正如我在问题中解释的,这是我尝试的第一件事,@Rob我已经在使用FMDB了,谢谢你,它更简单、更干净。我不必每次都插入,但这取决于我应用程序的用户,你认为我是否应该将所有值保存在一个nsUserDefauts中,然后将它们全部获取并插入到一个查询中?第一次插入而不是更新的问题在于此;我不知道哪一个将被插入。除此之外,我会尝试一下lastinsertRowId。我不知道你的应用程序正在做什么,但通常你会有一些模型对象,在用户输入数据时保存数据,只有当用户单击“完成”/“保存”时,你才会将其提交到持久存储(即,将其插入SQLite数据库),它将一次性完成这项工作。