Vapor Fluent PostgreSQL如何为已有表添加必填字段并解决空值报错
问题原因
你的报错判断完全正确。PostgreSQL 为已有数据的表新增带NOT NULL约束的字段时,会自动给所有旧行的新增字段赋值为NULL,直接违反非空约束,因此抛出该错误。
解决方案
根据你的业务需求可以选择以下两种方案:
方案1:旧数据可使用统一默认值
如果所有已有数据的new_field都可以设置为同一个固定默认值,直接在字段定义中添加.default()约束即可,迁移代码修改如下:
struct AddNewFieldToSchema: Migration { func prepare(on database: Database) -> EventLoopFuture<Void> { database.schema("schema_name") // 新增字段时同时指定默认值,填充已有旧数据 .field("new_field", .string, .required, .default("你的默认值")) .update() } func revert(on database: Database) -> EventLoopFuture<Void> { database.schema("schema_name") .deleteField("new_field") .update() } }
该方案操作最简单,适合默认值符合业务逻辑的场景。
方案2:旧数据需要自定义不同取值
如果不同行的new_field需要设置不同的值,需要拆分迁移逻辑为三步:
- 先新增可空的
new_field字段(不带.required约束) - 批量更新所有已有数据,为每一行的
new_field赋值 - 修改
new_field的约束为必填(.required)
对应迁移代码如下:
struct AddNewFieldToSchema: Migration { func prepare(on database: Database) -> EventLoopFuture<Void> { // 第一步:新增可空字段 database.schema("schema_name") .field("new_field", .string) .update() .flatMap { _ in // 第二步:批量更新所有旧数据,此处可以根据业务逻辑自定义赋值规则 SchemaNameModel.query(on: database) .set(\.$newField, to: "自定义默认值") // 可配合filter实现不同行不同赋值 .update() } .flatMap { _ in // 第三步:修改字段为必填约束 database.schema("schema_name") .updateField("new_field", .string, .required) .update() } } func revert(on database: Database) -> EventLoopFuture<Void> { database.schema("schema_name") .deleteField("new_field") .update() } }
注意:代码中的SchemaNameModel需要替换为你对应表的实际Fluent模型类名。
内容的提问来源于stack exchange,提问作者Wendell
相关产品推荐
相关产品推荐

