insert 时,字段为 nil 该不该拼入字段名的问题 #2101

Open
opened 2022-01-14 09:50:07 +00:00 by fanybook · 1 comment
Contributor

还有一个问题,insert 的时候,能不能通过类型的 Value() 看一下是否为 nil,如果为 nil 就不要拼 insert 的 sql 文了

现在的现象是,使用了类似 sql.NullSting 的类型,然后在定义 model 时直接使用了 sql.NullSting,而没用 *sql.NullSting

然后 new(Model),这个字段就必然不是 nil,但是它的 Value() 是 nil 啊,但是 insert sql 会把这个字段拼上,导致数据库如果不允许为 null,但是有默认值,也仍然无法 insert 成功

Originally posted by @fanybook in #2099 (comment)

还有一个问题,insert 的时候,能不能通过类型的 Value() 看一下是否为 nil,如果为 nil 就不要拼 insert 的 sql 文了 现在的现象是,使用了类似 sql.NullSting 的类型,然后在定义 model 时直接使用了 sql.NullSting,而没用 *sql.NullSting 然后 new(Model),这个字段就必然不是 nil,但是它的 Value() 是 nil 啊,但是 insert sql 会把这个字段拼上,导致数据库如果不允许为 null,但是有默认值,也仍然无法 insert 成功 _Originally posted by @fanybook in https://gitea.com/xorm/xorm/issues/2099#issuecomment-692404_
Author
Contributor

@Lunny Xiao 现在 insert 分为两种

  1. 单条 insert
  2. 多条 insert

1)单条 insert
如果字段为 nil 仍然拼入字段名,例如: 数据库中不允许为空,但默认值是0

insert into (name, parent_id) values ('测试1', null) 就会报错
insert into (name) values ('测试1'),不会报错 parent_id 是 0

如果模型
parent_id 为 sql.NullInt64,那么即使数据库里有默认值,也必须在 insert 时,手动给字段赋值,否则就报错,这是因为 sql.NullInt64 的初始值 Value() 是 nil

方案1:用 “类型.Value() 看一下是否为 nil”,如果是 nil 则不拼入 insert 的 sql 文中
方案2:用 “类型.Value() 看一下是否为 nil”,如果是 nil 则看字段有没有默认值,有就把 nil 改为默认值,比如模型里 parent_id default(0) 那么 insert into (name, parent_id) values ('测试1', null) -> insert into (name, parent_id) values ('测试1', 0)

2)多条 insert 不好处理
方案1:不可行
方案2:可行

方案2 session_insert.go genInsertColumns 和 insertMultipleStruct

		} else {
			arg, err := session.statement.Value2Interface(col, fieldValue)
			if err != nil {
				return colNames, args, err
			}
			args = append(args, arg)
		}

改成

		} else {
			arg, err := session.statement.Value2Interface(col, fieldValue)
			if err != nil {
				return colNames, args, err
			}

			if arg != nil {
				args = append(args, arg)
			} else {
				if !col.Nullable && !col.DefaultIsEmpty {
					args = append(args, col.Default)
				} else {
					// 如果可为空 || 没默认值,那就保持为 nil(notnull 时由数据库报错)
					args = append(args, arg)
				}
			}
		}
@Lunny Xiao 现在 insert 分为两种 1. 单条 insert 2. 多条 insert 1)单条 insert 如果字段为 nil 仍然拼入字段名,例如: 数据库中不允许为空,但默认值是0 insert into (name, parent_id) values ('测试1', null) 就会报错 insert into (name) values ('测试1'),不会报错 parent_id 是 0 如果模型 parent_id 为 sql.NullInt64,那么即使数据库里有默认值,也必须在 insert 时,手动给字段赋值,否则就报错,这是因为 sql.NullInt64 的初始值 Value() 是 nil 方案1:用 “类型.Value() 看一下是否为 nil”,如果是 nil 则不拼入 insert 的 sql 文中 方案2:用 “类型.Value() 看一下是否为 nil”,如果是 nil 则看字段有没有默认值,有就把 nil 改为默认值,比如模型里 parent_id default(0) 那么 insert into (name, parent_id) values ('测试1', null) -> insert into (name, parent_id) values ('测试1', 0) 2)多条 insert 不好处理 方案1:不可行 方案2:可行 方案2 session_insert.go genInsertColumns 和 insertMultipleStruct ```go } else { arg, err := session.statement.Value2Interface(col, fieldValue) if err != nil { return colNames, args, err } args = append(args, arg) } ``` 改成 ```go } else { arg, err := session.statement.Value2Interface(col, fieldValue) if err != nil { return colNames, args, err } if arg != nil { args = append(args, arg) } else { if !col.Nullable && !col.DefaultIsEmpty { args = append(args, col.Default) } else { // 如果可为空 || 没默认值,那就保持为 nil(notnull 时由数据库报错) args = append(args, arg) } } } ```
lunny added the
kind
proposal
label 2022-02-16 13:50:20 +00:00
Sign in to join this conversation.
No Milestone
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: xorm/xorm#2101
No description provided.