猿问

mysql 抱怨来自 go driver 的语法

我正在使用 github.com/go-sql-driver/mysql 和 mysql 5.7.10。我有一个功能:


bulkSetStatus := func(docVers []*_documentVersion) error {

    if len(docVers) > 0 {

        query := strings.Repeat("CALL documentVersionSetStatus(?, ?); ", len(docVers))

        args := make([]interface{}, 0, len(docVers)*2)

        for _, docVer := range docVers {

            args = append(args, docVer.Id, docVer.Status)

        }

        _, err := db.Exec(query, args...)

        return err

    }

    return nil

}

如果len(docVers) == 1但当有更多时,这会起作用,导致CALL存储过程中有多个s,它会出错:


错误 1064:您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,了解在第 1 行的“CALL documentVersionSetStatus(?, ?)”附近使用的正确语法


我也在每次调用之间尝试了一个换行符,但我得到了同样的错误。如果我在 mysql 工作台中运行它,并CALL在此过程中使用多个s,它可以正常工作,我不确定这里的语法有什么问题。


我已经用参数注销了确切的全文,正如预期的那样:


CALL documentVersionSetStatus("9c71cac14a134e7abbc4725997d90d2b", "inprogress"); CALL documentVersionSetStatus("beb65318da96406fa92990426a279efa", "inprogress");


慕姐8265434
浏览 174回答 2
2回答

暮色呼如

go-sql-driver,默认情况下,CALL如果攻击者设法执行 SQL 注入(例如,通过注入0 OR 0; DROP TABLE foo),由于安全隐患,不允许您在一个查询中包含多个语句(就像您通过将多个语句链接在一起所做的那样)。为此,您必须multiStatements在连接到数据库时通过传递参数来显式启用它,例如db, err := sql.Open("mysql", "user:password@/dbname?multiStatements=True")来源:https : //github.com/go-sql-driver/mysql#multistatements

慕森卡

我通过对参数进行一些手动字符串插值而不是使用正确的?方法来修复 proc 调用:bulkSetStatus := func(docVers []*_documentVersion) error {    if len(docVers) > 0 {        query := strings.Repeat("CALL documentVersionSetStatus(%q, %q); ", len(docVers))        args := make([]interface{}, 0, len(docVers)*2)        for _, docVer := range docVers {            args = append(args, docVer.Id, docVer.Status)        }        _, err := db.Exec(fmt.Sprintf(query, args...))        return err    }    return nil}所以我交换了?for%q和 usfmt.Sprintf来注入参数,我应该注意到 slugonamission 的答案是部分正确的,我确实需要添加连接字符串参数multiStatements=true,以便让它与我的其他更改一起使用。我将在 github repo 上记录一个问题,当有多个语句时,它看起来可能存在一些参数插值问题,我认为发生错误是因为 mysql db 试图运行包含?文字的脚本。
随时随地看视频慕课网APP

相关分类

Go
我要回答