2015-06-16 38 views
1

我有一個用戶打破了我的其他工作代碼,並且我認爲這是因爲他的名字有一個撇號。我嘗試使用雙撇號和反斜槓轉義它,但我一直得到fatal error: unexpectedly found nil while unwrapping an Optional value在Swift中,使用帶有撇號的SQL查詢

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) 

回答

2

有三個問題:

  1. 您正在使用C風格在你的SQL逃逸。 SQLite documentation表示

    字符串常量是通過將字符串括在單引號(')中形成的。字符串中的單引號可以通過將兩個單引號放在一行中進行編碼 - 就像在Pascal中一樣。不支持使用反斜槓字符的C樣式轉義,因爲它們不是標準的SQL。

    因此,與''替換'字符:

    let sanitizedName = correctName?.stringByReplacingOccurrencesOfString("'", withString: "''") 
    
  2. sanitizedName是可選的,所以你要解開它,否則它會出現Optional(...)

    let wrongAnswerSQLQuery = "SELECT name from member_data where name is not '\(sanitizedName!)' LIMIT 3" 
    
  3. 更妙,你應該削減Gordian結,而不是用這樣的字符串值構建SQL語句。

    相反,您應該在SQL中使用?佔位符,然後在withArgumentsInArray中傳遞correctName。然後,你不必擔心做任何這種「消毒」的所有:

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

嗯,完美!對於它的價值,我嘗試了將撇號加倍並且不成功(在其他人嘗試的情況下)。第三種解決方案顯然是最好的 - 謝謝! – thumbtackthief

+0

是的,如果你走這條路線,你必須做兩個選項的加倍和解開。但正如你所說,使用'?'佔位符的方法是最好的。 – Rob