Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 是不是;“错误”;要发出不带';不要调用sqlite3\u绑定?_Swift_Sqlite - Fatal编程技术网

Swift 是不是;“错误”;要发出不带';不要调用sqlite3\u绑定?

Swift 是不是;“错误”;要发出不带';不要调用sqlite3\u绑定?,swift,sqlite,Swift,Sqlite,我正在为MacOS游戏编写一个定制的SQLite包装器,这只是为了好玩。我已经学习了一个非常好的教程,它概述了一种使用绑定调用构造INSERT语句的费力方法,如下所示: let insertStatementString = "INSERT INTO Contact (Id, Name) VALUES (?, ?);" insert(id:4, name:"Chris") func insert(id: Int32, name: NSString) { var insertState

我正在为MacOS游戏编写一个定制的SQLite包装器,这只是为了好玩。我已经学习了一个非常好的教程,它概述了一种使用绑定调用构造INSERT语句的费力方法,如下所示:

let insertStatementString = "INSERT INTO Contact (Id, Name) VALUES (?, ?);"
insert(id:4, name:"Chris")

func insert(id: Int32, name: NSString) {

    var insertStatement: OpaquePointer? = nil

    if sqlite3_prepare_v2(db, insertStatementString, -1, &insertStatement, nil) == SQLITE_OK {

        sqlite3_bind_int(insertStatement, 1, id)
        sqlite3_bind_text(insertStatement, 2, name.utf8String, -1, nil)

        if sqlite3_step(insertStatement) == SQLITE_DONE {
            print("Successfully inserted row.")
        } else {
            print("Could not insert row.")
        }

    } else {
        print("INSERT statement could not be prepared.")
    }

    sqlite3_finalize(insertStatement)
}
相反,我发现以下方法同样有效,不必将数据绑定到语句。这样写有风险吗?我意识到准备好的陈述更快/更有效,但我不需要速度来达到我的目的。我没有看到像下面这样的例子。谢谢你的建议——我刚刚开始学习Swift,并不断发现事情比我想象的要难一些

let insertItemSql : String = "INSERT INTO item (itemid, characterClass, 
itemtype, itemtypeid,  mincharges, maxcharges, name) VALUES (%d,%d,%d,%d,%d,%d,'%@');"

let sqlHelper = SQLHelper(databasePath: Globals.SharedInstance.databaseUrl)
let command = String(format: insertItemSql, item.id, 0, 0, 0, 0, 0, item.name)
let success = sqlHelper.nonQuery(sqlCommand: command)


func nonQuery(sqlCommand cmd: String) -> Bool {

        var success : Bool = false

        if let db = openDatabase() {

            var nonQueryStatement: OpaquePointer? = nil
            if sqlite3_prepare_v2(db, cmd, -1, &nonQueryStatement, nil) == SQLITE_OK {
                if sqlite3_step(nonQueryStatement) == SQLITE_DONE {
                    success = true
                } else {
                    print("Could not execute nonQuery statement.")
                    if let errorPointer = sqlite3_errmsg(db) {
                        let message = String.init(cString: errorPointer)
                        print("Error message was " + message)
                    }
                }
            } else {
                print("nonQuery statement could not be prepared")
                if let errorPointer = sqlite3_errmsg(db) {
                    let message = String.init(cString: errorPointer)
                    print("Error message was " + message)
                }
            }
            sqlite3_finalize(nonQueryStatement)

        }

        return success

    }

说它是“错误的”未免言过其实,但它可能是脆弱的,通常不被认为是最佳实践。那个教程的建议是一个很好的技巧

例如,如果与
name
列关联的值中有一个
,该怎么办?例如“奥康纳”。此字符串中的单引号将提前终止SQL字符串,例如

INSERT INTO item (itemid, characterClass, itemtype, itemtypeid,  mincharges, maxcharges, name)
    VALUES (1,2,3,4,5,6,'O'Connor');
在这种情况下(除其他外),手动构造的SQL语句的准备可能会失败。
sqlite3\u bind\u text
消除了此类问题,并且始终是安全的。正如上面所说:

然后使用函数将大字符串值绑定到SQL语句。使用绑定可以避免转义字符串中的引号字符,从而降低SQL注入攻击的风险。由于不需要对大字符串进行太多的解析或复制,因此它的运行速度也更快

当然,如果您知道您永远不会有任何有问题的输入(例如,您知道永远不会有任何这些有问题的值的只是数字或内部字符串值),那么您就不必使用
sqlite3\u bind\u xxx
函数,但这种假设在以后会影响我们

一般来说,绑定值更安全。如果您担心
sqlite3\u bind\u text
这类语法太麻烦,那么我可能会建议使用一个SQLite包装类为您进行绑定,但它会将您从这些细节中抽象出来



顺便说一句,绑定的另一个优点是用于
NULLABLE
列。如果只使用
占位符,则可以为该列绑定
NULL
或适当的值。如果您是手动构建SQL,正确处理
可为null的
列只会稍微复杂一些。

说它“错了”未免言过其实,但它可能很脆弱,通常不被视为最佳实践。那个教程的建议是一个很好的技巧

例如,如果与
name
列关联的值中有一个
,该怎么办?例如“奥康纳”。此字符串中的单引号将提前终止SQL字符串,例如

INSERT INTO item (itemid, characterClass, itemtype, itemtypeid,  mincharges, maxcharges, name)
    VALUES (1,2,3,4,5,6,'O'Connor');
在这种情况下(除其他外),手动构造的SQL语句的准备可能会失败。
sqlite3\u bind\u text
消除了此类问题,并且始终是安全的。正如上面所说:

然后使用函数将大字符串值绑定到SQL语句。使用绑定可以避免转义字符串中的引号字符,从而降低SQL注入攻击的风险。由于不需要对大字符串进行太多的解析或复制,因此它的运行速度也更快

当然,如果您知道您永远不会有任何有问题的输入(例如,您知道永远不会有任何这些有问题的值的只是数字或内部字符串值),那么您就不必使用
sqlite3\u bind\u xxx
函数,但这种假设在以后会影响我们

一般来说,绑定值更安全。如果您担心
sqlite3\u bind\u text
这类语法太麻烦,那么我可能会建议使用一个SQLite包装类为您进行绑定,但它会将您从这些细节中抽象出来



顺便说一句,绑定的另一个优点是用于
NULLABLE
列。如果只使用
占位符,则可以为该列绑定
NULL
或适当的值。如果您是手动构建SQL,正确处理
NULLABLE
列只会稍微复杂一些。

我不同意。安全性很重要,但不是在涉及游戏的本地化环境中,也不是在应用程序域运行在一台机器上的情况下,我确实明确指出了这一点,希望防止像您这样的评论。感谢你阅读我的问题,但这不是我想要的。你没有抓住重点。问题不是SQL注入攻击,而是包含
字符的用户输入将破坏代码。SQL注入是更广泛问题的恶意示例。但我会删除那个链接,因为你已经生气了。我不同意。安全性很重要,但不是在涉及游戏的本地化环境中,也不是在应用程序域运行在一台机器上的情况下,我确实明确指出了这一点,希望防止像您这样的评论。感谢你阅读我的问题,但这不是我想要的。你没有抓住重点。问题不是SQL注入攻击,而是包含
字符的用户输入将破坏代码。SQL注入是更广泛问题的恶意示例。但我会删除那个链接,因为你已经生气了。没有一个是有意的。很容易对输入进行消毒。令我惊讶的是,我在SQLite文献中没有看到关于执行SAN绑定的可能性的示例。如果我在真实场景中使用SQL引擎,我会使用一个支持存储过程的引擎,该引擎的接口比这个低级C风格的API更健壮。关于可空性的观点很好。我没有考虑过这一点。哦,我不愿意