简体   繁体   中英

In Swift, use a SQL query with an apostrophe

I have a user who is breaking my otherwise-working code, and I assume it's because his name has an apostrophe. I've tried escaping it using a double apostrophe and a backslash but I keep getting fatal error: unexpectedly found nil while unwrapping an Optional value .

    let querySQL = "SELECT name from member_data ORDER BY RANDOM() LIMIT 1" 
    rightAnswer = memberDatabase!.executeQuery(querySQL, withArgumentsInArray: nil)
    rightAnswer!.next()
    correctName = rightAnswer!.stringForColumn("name")!
    println("Correct answer is \(correctName)") 
      //prints as Optional("Sam O\'Neal")
    let sanitizedName = correctName?.stringByReplacingOccurrencesOfString("'", withString: "\'")   
      //tried many combinations of this
    let wrongAnswerSQLQuery = "SELECT name from member_data where name is not '\(sanitizedName)' LIMIT 3"
    let wrongAnswersResultSet:FMResultSet = memberDatabase!.executeQuery(wrongAnswerSQLQuery, withArgumentsInArray: nil)

There are three issues:

  1. You are using C-style escapes in your SQL. The SQLite documentation says

    A string constant is formed by enclosing the string in single quotes ('). A single quote within the string can be encoded by putting two single quotes in a row - as in Pascal. C-style escapes using the backslash character are not supported because they are not standard SQL.

    So replace ' characters with '' :

     let sanitizedName = correctName?.stringByReplacingOccurrencesOfString("'", withString: "''")
  2. Your sanitizedName is optional, so you have to unwrap it or else it will appear as Optional(...) :

     let wrongAnswerSQLQuery = "SELECT name from member_data where name is not '\\(sanitizedName!)' LIMIT 3"
  3. Even better, you should cut the Gordian knot, and not build SQL statement with string values like this at all.

    Instead, you should use the ? placeholders in your SQL and then pass the correctName in the withArgumentsInArray . Then you don't have to worry about doing any of this "sanitizing" at all:

     let wrongAnswerSQLQuery = "SELECT name from member_data where name is not ? LIMIT 3" let wrongAnswersResultSet = memberDatabase!.executeQuery(wrongAnswerSQLQuery, withArgumentsInArray: [correctName!])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM