我遇到了一个奇怪的错误,无法找出问题所在。 我使用此函数来保存传入消息:
func (mdb *MailDB) SaveMail(mail *Mail){
conn, err := sqlite.Open("maildb.db")
if err != nil {
log.Print("Unable to open the database: ", err)
return
}
defer conn.Close()
insertsql := fmt.Sprintf(`INSERT INTO mails (sender,subject,text,time) VALUES ("%v", "%v", "%v", %v) ;`,
mail.Sender,mail.Subject,mail.Text,time.Now().Unix())
err = conn.Exec(insertsql)
if err!=nil {
log.Print("maildb insert fail @exec: ",err)
log.Print(insertsql)
return
}
}
我收到此错误:
2012/05/09 10:10:20 maildb insert fail @exec: SQL error or missing database: unrecognized token: """
2012/05/09 10:10:20 INSERT INTO mails (sender,subject,text,time) VALUES ("wLrOBizTcmS1MlqeXydUK9U6YJQ=", "abc", "321
", 1336551020) ;
(在321之后是'\ n'我不知道为什么在这里有所遗漏)
奇怪的是,我可以毫无问题地在sqlite控制台中发送copy'n'pasted查询。
有人看到什么出错了吗? 请帮忙!
答案 0 :(得分:2)
我认为你的问题是使用"
来分隔字符串文字,而这不是标准的SQL语法,也不是sqlite支持的。
引用its manual:
通过将字符串括在单引号(')中形成字符串常量。字符串中的单引号可以通过在行中放入两个单引号来编码 - 如Pascal中所示。不支持使用反斜杠字符的C样式转义,因为它们不是标准SQL
所以明显的解决方法应该是使用
insertsql := fmt.Sprintf(`INSERT INTO mails (sender,subject,text,time) VALUES ('%v', '%v', '%v', %v) ;`, ...)
另请注意,像您一样构造SQL语句是天真的,并且受SQL injection attacks的约束。正确的方法是先create a prepared statement,然后bind its parameters to actual values,然后执行它。我没有使用Go绑定到sqlite的经验,所以我不知道他们是否支持我提到的API,但我认为你应该尝试对此进行调查。