Golang中解决Data too long for column错误 - 字符串转Varchar问题

Golang中解决Data too long for column错误 - 字符串转Varchar问题 你好,

我在网上尝试寻找答案但一无所获,所以在这里提问。

stmt.Exec(u.Name) 这行代码导致了 Error 1406: Data too long for column 'name' at row 1 错误。MySQL 数据库中的 name 字段设置为 Varchar 11。如果我在数据库里把它改成 text 类型,它就能工作,但这只是个临时解决办法。有什么方法可以解决这个问题吗?

谢谢

type User struct {
	ID uint16
	Name string
}
func Insert(u *User) (int64, error) {
	stmt, err := r.db.Prepare("INSERT INTO users (name) VALUES (?)")
	if err != nil {
		return 0, err
	}

	res, err := stmt.Exec(u.Name) // u.Name 被设置为 'Hello World',所以它很短!
	if err != nil {
		return 0, err
	}

	id, err := res.LastInsertId()
	if err != nil {
		return 0, err
	}

	// 顺便问一下,我需要在任何地方调用 `defer` 或 `close` 吗?

	return id, nil
}

更多关于Golang中解决Data too long for column错误 - 字符串转Varchar问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

如果将长度设为12,是否可行?我对MySQL不太熟悉,但Varchar 11是否包含空终止符?

更多关于Golang中解决Data too long for column错误 - 字符串转Varchar问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


// 顺便问一下,我应该在什么上调用 deferclose 吗?

你可以关闭你的语句

defer stmt.Close()

我假装没有问过这个问题。真是尴尬得灾难性!显然,字段被设置为11,这个值太短了,本应设置为例如255。

从这场灾难中继续前进,我应该在最后调用 defer 还是 close 吗?

注意:我是一个学习者,所以抱歉问了这些糟糕的问题。

这个错误是因为 VARCHAR(11) 只能存储最多11个字符(注意:对于多字节字符如中文,每个字符可能占用多个字节)。你需要确保插入的字符串长度不超过字段定义的限制。

以下是解决方案:

  1. 在插入前验证字符串长度
func Insert(u *User) (int64, error) {
    // 验证name长度不超过11个字符
    if len(u.Name) > 11 {
        // 可以选择截断或返回错误
        u.Name = u.Name[:11]
        // 或者:return 0, fmt.Errorf("name too long, max 11 characters")
    }
    
    stmt, err := r.db.Prepare("INSERT INTO users (name) VALUES (?)")
    if err != nil {
        return 0, err
    }
    
    res, err := stmt.Exec(u.Name)
    if err != nil {
        return 0, err
    }
    
    return res.LastInsertId()
}
  1. 使用UTF-8安全的长度检查(如果包含多字节字符):
import "unicode/utf8"

func Insert(u *User) (int64, error) {
    // 按字符数(而不是字节数)检查长度
    if utf8.RuneCountInString(u.Name) > 11 {
        // 按字符截断
        runes := []rune(u.Name)
        if len(runes) > 11 {
            u.Name = string(runes[:11])
        }
    }
    
    stmt, err := r.db.Prepare("INSERT INTO users (name) VALUES (?)")
    if err != nil {
        return 0, err
    }
    
    res, err := stmt.Exec(u.Name)
    if err != nil {
        return 0, err
    }
    
    return res.LastInsertId()
}
  1. 关于资源清理,确实需要关闭stmt:
func Insert(u *User) (int64, error) {
    stmt, err := r.db.Prepare("INSERT INTO users (name) VALUES (?)")
    if err != nil {
        return 0, err
    }
    defer stmt.Close() // 确保关闭
    
    // 长度验证...
    
    res, err := stmt.Exec(u.Name)
    if err != nil {
        return 0, err
    }
    
    return res.LastInsertId()
}

检查你的实际数据:Hello World 确实是11个字符,但如果包含空格、标点或不可见字符,可能会超过限制。建议在调试时打印实际长度:

fmt.Printf("Name length: %d, content: %q\n", len(u.Name), u.Name)

如果问题仍然存在,可能是数据库字符集导致的问题。MySQL的VARCHAR(11)在utf8mb4字符集下最多存储11个字符,但在utf8mb3下可能不同。

回到顶部