0

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

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

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

4

1 回答 1

2

我认为您的问题是"用于分隔字符串文字,而这不是标准的 SQL 语法,并且 sqlite 也不支持。引用其手册

通过将字符串括在单引号 (') 中形成字符串常量。字符串中的单引号可以通过将两个单引号放在一行中来编码 - 就像在 Pascal 中一样。不支持使用反斜杠字符的 C 样式转义,因为它们不是标准 SQL

所以明显的修复应该是使用

insertsql := fmt.Sprintf(`INSERT INTO mails (sender,subject,text,time) VALUES ('%v', '%v', '%v', %v) ;`, ...)

另请注意,像您这样构建 SQL 语句是幼稚的,并且容易受到SQL 注入攻击。正确的方法是首先创建一个准备好的语句,然后将其参数绑定到实际值,然后执行它。我没有将 Go 绑定到 sqlite 的经验,所以我不知道它们是否支持我提到的 API,但我认为您应该尝试对此进行调查。

于 2012-05-09T10:21:24.553 回答