gosqlite中的奇怪的sqlite错误(golang)

时间:2012-05-09 08:18:37

标签: sqlite go

我遇到了一个奇怪的错误,无法找出问题所在。 我使用此函数来保存传入消息:

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查询。

有人看到什么出错了吗? 请帮忙!

1 个答案:

答案 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,但我认为你应该尝试对此进行调查。