Phoenix迁移时Postgres插入数据遇inserted_at约束及子查询报错求助
解决Postgrex的非空约束错误与子查询列数不匹配问题
我来帮你梳理下问题所在,以及对应的解决办法:
首先看第一个错误:null value in column "inserted_at" violates not-null constraint,原因很直接——你的contract_groups表要求inserted_at字段不能为null,但你最初的INSERT语句只插入了contract_id和group_id,完全没给inserted_at赋值,PostgreSQL自然会触发非空约束报错。
然后你修改后的SQL出现了subquery must return only one column错误,是因为你把返回两列的子查询塞进了VALUES的单个位置里。VALUES里每个逗号分隔的项只能对应单列值,而你(SELECT c.id, fg.group_id ...)返回了两列,这就和语法要求冲突了,这种写法根本不适合批量插入多列数据的场景。
正确的写法应该是这样
直接在原来的INSERT ... SELECT语法里补上inserted_at的取值就行,不用绕去VALUES:
execute "INSERT INTO contract_groups (contract_id, group_id, inserted_at) SELECT c.id, fg.group_id, NOW() FROM contracts c, folder_groups fg WHERE c.folder_id = fg.folder_id"
如果你的表还有updated_at这类同样非空的字段,也一起加上:
execute "INSERT INTO contract_groups (contract_id, group_id, inserted_at, updated_at) SELECT c.id, fg.group_id, NOW(), NOW() FROM contracts c, folder_groups fg WHERE c.folder_id = fg.folder_id"
为什么这个写法能解决问题?
- 保持了
INSERT ... SELECT批量插入的优势,适合从关联表中一次性取数插入 - 显式指定了要插入的列名,避免因为表字段顺序变化导致的错误
- 在SELECT语句里直接用
NOW()(或者CURRENT_TIMESTAMP,效果一致)给inserted_at(和updated_at)赋值,满足非空约束的要求
内容的提问来源于stack exchange,提问作者Bargain23
相关产品推荐
相关产品推荐

