新手问题 sql插入数据string类型字段为空

chenqinghe · 2017年07月14日 · 最后由 abin 回复于 2017年07月14日 · 342 次阅读

批量插入假数据的时候,int 类型数据都可以插入成功,但是 varchar 类型的均为空,望大神解答是什么原因。

代码:

func main() {
    db, err := sql.Open("mysql", "chenchao:Aglacad123@tcp(localhost:3306)/test")
    if err != nil {
        logrus.Fatal("can not connect to database:", err)
    }
    if err := db.Ping(); err != nil {
        logrus.Fatal(err)
    }
    logrus.Info("successful.")

    stmt, err := db.Prepare(`insert into user(uid,user_name,password,ctime) VALUE (?,?,?,?)`)
    if err != nil {
        logrus.Fatal(err)
    }
    for i := 3; i < 1000000; i++ {
        name := randomStr(10)
        pwd := randomStr(20)
        fmt.Println(name, pwd)
        rs, err := stmt.Query(i, name, pwd, time.Now().Unix())
        if err != nil {
            logrus.Fatal(err)
            return
        }
        logrus.Debug(rs)
    }

}

func randomStr(length int) string {
    var baseStr = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPLKJHGFDSAZXCVBNM0123456789"
    var bt []byte = make([]byte, length)
    for i := 0; i < length; i++ {
        k := rand.Intn(62)
        bt = append(bt, baseStr[k])
    }
    return string(bt)
}

打开 mysql 的 sql 日志,发现插入的数据有点问题,下面是截图: mysql日志

奇怪的是,像下面这样直接赋值,插入就没有问题(如上图第二条 sql):

name:= "hello"
pwd:= "world"
更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio

bt = append(bt, baseStr[k]) -> bt[i] = baseStr[k]

代码看上去没啥问题,我用你的代码跑了下,varchar 插入正常。有点意思。

fmt.Println(name, pwd) 这里打印出来的正确吗?

另外,这里是表结构:

CREATE TABLE `user` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `ctime` int(11) DEFAULT NULL,
  PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=457 DEFAULT CHARSET=utf8mb4;

按照 @plain 那样修改之后,插入正常了,不过求大神指导,为什么会这样?

stmt, err := db.Prepare(`insert into user(user_name,password,ctime) VALUE (?,?,?)`)
    if err != nil {
        logrus.Fatal(err)
    }
    name := "hello"
    //name = "    hello"
    //name = string(append([]byte{0}, []byte(name)...))
    //name = string(append([]byte{1}, []byte(name)...))
    pwd := "world"
    fmt.Println(name, pwd)
    rs, err := stmt.Query(name, pwd, time.Now().Unix())
    if err != nil {
        logrus.Fatal(err)
        return
    }
    logrus.Debug(rs)

最后经过上述测试,发现有可能是因为二进制安全的问题造成的。生成随即字符串的函数搞错了,前面加了很多 0,而 mysql 可能因为\0 判定字符串终止,所以插入的数据为空。

var bt []byte = make([]byte, length)创建 length 长度的 slice 并初始化,bt = append(bt, baseStr[k]) 会在原先的数据上添加数据,这样 bt 的数据就变成 length 长度的 0 加上你后面增加的数据了。

var bt [] byte for i := 0; i < length; i++ { k := rand.Intn(62) bt = append(bt, baseStr[k]) }

或者

var bt [] byte = make([] byte, length) for i := 0; i < length; i++ { k := rand.Intn(62) btp[i] = baseStr[k] }

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册