iOS Swift 插入 sqlite FMDB

Posted

技术标签:

【中文标题】iOS Swift 插入 sqlite FMDB【英文标题】:iOS Swift insert into sqlite FMDB 【发布时间】:2016-04-02 18:40:09 【问题描述】:

这是我的问题:我有这个葡萄酒应用程序,它以漂亮的表格视图向用户显示我的数据库内容。使用 FMDB executeQuery 函数,我可以很容易地从中获取数据,但是每当我尝试向 SQLite 表添加内容时,它就会失败。

这是我使用的代码。

do
 
     try sharedInstance.database!.executeUpdate("INSERT INTO wine VALUES (?, ?, ?)", values: [id, name, wineType])
 
 catch
 
     print("error \(error)")
 

我尝试将所有内容放在一个字符串中,然后将其作为第一个参数发送,并将 nil 作为第二个参数,但同样失败。此语法来自Data Sanitisation section in the FMDB README from github

我发现了一些类似的案例,但答案都是 Objective-C。请注意,我对 ios 完全陌生,对 Objective-C 一无所知,这是我的第一个 Swift 应用程序。

我做错了什么?

【问题讨论】:

您可以为 SQLite 使用 Swift 包装器。现在有好的,比如github.com/groue/GRDB.swift 【参考方案1】:

语法是正确的,可能你想检查一下:

你事先打电话给sharedInstance.database!.open() 您的表格仅包含 3 列

如果您在项目中包含FMDatabaseAdditionsVariadic.swiftFMDatabaseVariadic.swift,您可以像这样调用executeUpdate

do 
    try sharedInstance.database!.executeUpdate("INSERT INTO wine VALUES (?, ?, ?)", id, name, wineType)
 catch 
    print("error \(error)")

【讨论】:

【参考方案2】:

注意 :- 在这里,我将使用 FMDB 快速向您发送在数据库中插入记录的代码。

import UIKit

class FMDBDatabaseSignUpVC: UIViewController 

@IBOutlet weak var txtFirstNameOutlet: UITextField!
@IBOutlet weak var txtLastNameOutlet: UITextField!
@IBOutlet weak var txtEMailIDOutlet: UITextField!
@IBOutlet weak var txtPasswordOutlet: UITextField!

var databasePath = NSString()
override func viewDidLoad() 
    super.viewDidLoad()

    let filemgr = NSFileManager.defaultManager()
    let dirPaths =
        NSSearchPathForDirectoriesInDomains(.DocumentDirectory,
                                            .UserDomainMask, true).first as String!

    databasePath = (dirPaths as NSString).stringByAppendingPathComponent("swiftDemo.db")

    if !filemgr.fileExistsAtPath(databasePath as String)  
        let contactDB = FMDatabase (path: databasePath as String)
        if contactDB == nil 
            print(contactDB.lastErrorMessage())
        
    
    // Do any additional setup after loading the view.


@IBAction func btnSaveAction(sender: UIButton) 

    let contactDB = FMDatabase (path: databasePath as String)
    if contactDB.open() 
        let InsertQry = "insert into userInfo (userFirstName, userLastName,userEmailID,userPassword) values ('\(txtFirstNameOutlet.text!)','\(txtLastNameOutlet.text!)','\(txtEMailIDOutlet.text!)','\(txtPasswordOutlet.text!)')"
        let result = contactDB.executeUpdate(InsertQry, withArgumentsInArray: nil)
        if !result 
            print(contactDB.lastErrorMessage())
        
        else
        
            print("Success")
            txtFirstNameOutlet.text=""
            txtLastNameOutlet.text=""
            txtEMailIDOutlet.text=""
            txtPasswordOutlet.text=""
        
    


【讨论】:

【参考方案3】:

在某些情况下executeUpdate 会失败,所以首先尝试使用executeQueryexecuteStatments 来解决问题。

如果它不起作用,我认为打开数据库后执行sql语句的正确方法是:

executeUpdate("INSERT INTO wine VALUES ('\(id)', '\(name)', '\(wineType)')")

语句执行成功后关闭数据库。您在数据库中的 id 类型是什么?它是自动递增的吗?

您在控制台中遇到什么错误?尝试使用断点,看看发生了什么。

更新 之前的代码不适合在生产环境中使用,因为它会受到 SQL 注入 Reference 的影响,我认为在 iOS 上使用 FMDB,之前的代码可以使用。

【讨论】:

不要通过连接形成字符串。如果 wineType 等于 "); DROP TABLE wine;" 怎么办? 减一,因为答案推荐不安全代码,受 SQL 注入影响。检查***.com/questions/332365/… @Gwendal,您最好修改答案而不是投反对票。我们需要高质量的答案,为什么不通过编辑答案来提供帮助?! @Jeyhey,我已经用你的参考更新了答案。谢谢 除了 SQL 注入问题(取决于应用程序和上下文,可能会或可能不会对您产生影响)之外,还有在使用时包含撇号(单引号)的问题方法。我不得不想象,葡萄酒名称中包含撇号的情况并不少见。在这些情况下,这会中断。【参考方案4】:

这应该可行:

    do
 
     try sharedInstance.database!.executeUpdate("INSERT INTO wine(id, name, wineType) VALUES (?, ?, ?)", values: [id, name, wineType])
 
 catch
 
     print("error \(error)")
 

【讨论】:

以上是关于iOS Swift 插入 sqlite FMDB的主要内容,如果未能解决你的问题,请参考以下文章

Swift中SQLite使用2

如何使用 swift 在 iOS coredata sqlite 中启用 DELETE MODE

如何在 IOS Swift 中使用 SQLite 使用 FMDB 处理多个线程

使用 GRDB 在 Swift 中操作 SQLite 数据库 | 快读

Swift 3 sqlite/使用数据库?

如何在 swift 3 中使用现有的 SQLite? (FMDB)