Golang操作PostgreSQL插入数据后出现Scan类型转换错误
问题原因分析
从错误信息来看,你的INSERT ... RETURNING id语句实际返回了多列(包含password_changed_at),但你只提供了一个int类型变量newID接收结果,导致驱动尝试将第8列(索引7)的time.Time类型值转换为int时失败。
可能的根源:
- 数据库触发器影响:
users表可能存在INSTEAD OF INSERT触发器,该触发器返回了完整行数据而非仅id列,覆盖了RETURNING id的结果。 - SQL语句意外修改:实际运行的代码中,SQL语句可能被改成了
RETURNING *而非RETURNING id(比如变量作用域冲突、字符串拼接错误)。 - 类型不匹配隐患:
id是bigserial(对应PostgreSQL的bigint类型),但你用int类型接收,虽不是当前错误的直接原因,但可能引发后续溢出问题。
解决步骤
1. 验证SQL语句的实际返回结果
在PostgreSQL客户端(如psql)中执行以下语句,确认返回列数:
INSERT INTO users (email, first_name, last_name, hashad_password, active, roll_id) VALUES ('test_trigger@example.com', 'Test', 'User', 'dummy_hash', 1, 3) RETURNING id;
如果仅返回id一列,说明问题出在代码层面;如果返回多列,说明数据库中存在触发器或其他逻辑修改了返回结果。
2. 检查并处理触发器
若上述SQL返回多列,执行以下语句查看users表的触发器:
SELECT tgname, pg_get_triggerdef(t.oid) FROM pg_trigger t JOIN pg_class c ON t.tgrelid = c.oid WHERE c.relname = 'users' AND t.tgisinternal = false;
- 如果存在
INSTEAD OF INSERT触发器,修改触发器函数使其仅返回id列,或调整INSERT语句的RETURNING子句匹配触发器返回结果。 - 若不需要该触发器,直接删除:
DROP TRIGGER trigger_name ON users;
3. 修正代码中的类型和语句问题
调整newID的类型为int64以匹配bigserial,同时确保SQL语句正确:
var newID int64 stmt := `INSERT INTO users (email, first_name, last_name, hashad_password, active, roll_id) values ($1, $2, $3, $4, $5, $6) returning id` err = db.QueryRow(stmt, user.Email, user.FirstName, user.LastName, hashedPassword, user.Active, user.RollId, ).Scan(&newID) if err != nil { return 0, err } return newID, nil
4. 确认代码逻辑正确性
检查代码中是否存在变量覆盖、字符串拼接错误等情况,确保实际执行的SQL确实是RETURNING id而非其他内容。
内容的提问来源于stack exchange,提问作者Girish Bhutiya
相关产品推荐
相关产品推荐

