问题:如图,字段值的设置
今天在看一篇文章,设计数据库的时候所有字段都设置为 not null ,并且给默认值 default null/0 ,我感觉这是不符合实际场景的
我回想我入门的时候也看到过这样子的文章,但是我工作了两三年后发现,我都是根据业务实际来做的,业务允许为空那就是 null ,业务不允许为空我就给 not null ,这个是否必填由产品说了算。
至于 default 属性,是只有选择框,下拉框才需要做的事情。否则都没有 default
==========================隔断线=======
null 还是 not null:根据产品要求来设计
default:根据实际场景,一般只在下拉框等场景使用
如上,请各位指教,我这样应该是对的吧,这类似的文章都是不符合实际的吗?
1
akira 2022-09-04 19:05:39 +08:00 1
看实际情况来,尽信书不如无书
|
2
GTim 2022-09-04 19:58:02 +08:00 1
这几年的经验来看,能 `not null` 的都 `not null`,默认值能不 `null` 的就不要 `null`
|
3
fengpan567 2022-09-04 20:02:02 +08:00 1
待过一家公司也是按这个规范来的,真的蠢。审核人员把我提交的 sql 脚本打回来,说里的所有字段必须有默认值并且不准为 null ,可我时间字段怎么给你默认值,这个时间是用户自己去填的,争论了几句还是让我改,说自己不管业务只管审核
|
4
PendingOni 2022-09-04 20:05:15 +08:00 1
主要看那些字段是不是出现在建立的索引上或者在视图上比较常用
|
5
XiLingHost 2022-09-04 20:05:33 +08:00 2
@fengpan567 时间如果非要有个默认值,我觉得可以用`1970-01-01T00:00:00.000Z`
|
6
GTim 2022-09-04 20:06:50 +08:00
@fengpan567 做过国际化的基本都有一个共识:能用 bigint 来保存时间,都不要用 timestamp 或者 datetime ,不然后期可能是个超级大工程
|
7
fengpan567 2022-09-04 20:11:57 +08:00
@XiLingHost 我直接用字符串存时间了,反正已经跑路。。。
|
10
zjp 2022-09-04 21:53:45 +08:00 1
#2 一样的情况。要存的是金额,null 值、负数和零都是实际场景下存在的。那就只能用字符串了
|
12
lolizeppelin 2022-09-04 22:55:23 +08:00 1
@zpf124
linux 时间就是 utc 的 一般情况下字段都应该 not null,尽量用空字符串或者 0 来表达空,避免索引问题 当字段有是外键或唯一索引的时候,字段只能用到 null 占位,这时候就得允许 null |
13
Oktfolio 2022-09-04 22:57:21 +08:00 1
@iseki 我们就是这么干的,返回给前端,前端传的都是 yyyy-MM-dd HH:mm:ss ,刚看到的时候我人都惊呆了
|
14
ilylx2008 2022-09-04 23:14:47 +08:00 1
所有字段 not null+默认值
|
15
RedBeanIce OP |
16
oneisall8955 2022-09-04 23:42:58 +08:00 1
@ilylx2008 #14
@GTim #6 层遇到个业务场景,客户支付时间,MySQL 字段类型是 datetime ,对应 Java 是 java.util.Date ,如果 db 要 not null ,在程序上兼容? |
17
dobelee 2022-09-04 23:46:05 +08:00 1
避免空指针问题。
|
18
RedBeanIce OP |
21
dobelee 2022-09-05 01:03:27 +08:00
@RedBeanIce 你可以能搞错了,显示的问题应该由外层处理的。大多数情况可以用零值作为默认值的。
难道你想通过判断空指针来检查是否保存?这样是不靠谱的,结果可能随着不同语言的特性而变化。 |
23
iseki 2022-09-05 02:05:56 +08:00 via Android 1
@Oktfolio 我这边的做法都是代码中只出现时间类型,Java 里用 Instant Go 里用 time.Time ,系统边界尽量用 RFC3339 字符串传递
|
24
iseki 2022-09-05 02:09:14 +08:00 via Android
我倾向于是否允许 null 跟着业务走,尽量不用零值做特殊值,null 就是 null ,0 就是 0
|
25
kiwi95 2022-09-05 07:15:34 +08:00 via Android 1
@RedBeanIce 一般都能接受。其实说白了都是为了自己方便,减少出问题的点,dba 不想要 null 值是为了防止 MySQL 莫名其妙的问题,研发为了 SQL 能过审核并且能少一些空指针判断 /避免指定义针类型也想自己方便就都 not null 。
产品不同意就去说服他们。 |
26
ksc010 2022-09-05 08:04:45 +08:00 1
国际化 用 ISO 啊
|
27
GTim 2022-09-05 09:18:35 +08:00 1
|
28
lolizeppelin 2022-09-05 10:12:26 +08:00 1
|
29
RedBeanIce OP @dobelee
@lolizeppelin @ilylx2008 那么问题来了,用户输入了一个 0 ,后端返回给前端,怎么知道是用户输入的 0 ,还是 mysql 默认值的 0 用户说,我明明输入了。为啥没了。 |
30
RedBeanIce OP @kiwi95 请看上一条
|
31
meiyoumingzi6 2022-09-05 10:35:51 +08:00 via iPhone
看到归类到 java
我想站在其他语言角度来看, python 想搞这个事情也是 so easy , golang 就略蛋疼了,如果是 null ,就不得不在创建 struct 的时候把字段设置成指针类型,害,要不他就是零值,即:字符串类型是空串,数字类型是 0 |
32
morty0 2022-09-05 10:46:42 +08:00
@RedBeanIce 用户输入需要避开默认值
|
33
pastor 2022-09-05 12:24:22 +08:00
@RedBeanIce #29
对于用户是否应该必填字段,产品规则是可控的,即使不需要用户输入; 默认值也是产品规则可控的,比如字符串类型,一般默认就"",用户如果可以不输入,""也没问题。数值类型 0 值同样道理。 但是数据库 null 对于不同语言处理起来可能会遇到不同的麻烦。而对于默认值。 不喜欢 not null default 的各位,建议还是反思下自己吧 支持 not null default +1 支持 bigint 时间戳 +1 |
34
iseki 2022-09-05 12:46:21 +08:00 via Android
@RedBeanIce 用 Unix 时间戳也不是不行,这个问题和时区也没什么关系,就是 RFC3339 是明确的标准,时间戳就稍差点。
我的重点是不管用哪种,前端都需要处理,不是说用时间戳前端就省多少事 |
36
lovelylain 2022-09-05 13:12:13 +08:00 via Android
@GTim db 用 datetime 存,db 访问模块转换为时间戳,国际化会有什么问题吗?
|
37
RedBeanIce OP @pastor
请问一下,一个非必填字段。如何判断用户输入 0 ,还是 default 0 ,, 用户这个字段没有输入,回显的时候你给个 0 返回出去,不是扯淡了。。产品不知道是否可以接受这种处理方式。 请指教 |
38
lovelylain 2022-09-05 13:25:29 +08:00 via Android
@iseki 可以去了解下 protobuf3 ,尽量把零值作为缺省的特殊值,例如零值表示未设置。很多地方都是可以避免零值作为业务值的。
|
39
RedBeanIce OP @pastor 产品规则可控,感觉好麻烦。。。。
|
40
sunmoon1983 2022-09-05 13:26:35 +08:00
@fengpan567 那你修改了没有呀?我也碰到了这种情况!
|
41
ilylx2008 2022-09-05 13:37:16 +08:00 1
|
42
pastor 2022-09-05 13:37:28 +08:00 1
@RedBeanIce #37
"请问一下,一个非必填字段。如何判断用户输入 0 ,还是 default 0 ,," —— 你既然根据产品规则设置了默认是 0 ,也就是可以给用户端 0 用来展示,那不管是不是用户输入的 0 ,都是正确的作为前端展示的值。 搞清楚一点,提高产品思维,这个前提下,实现业务逻辑的重点是为了产品合理性,而不是为了去满足你区分到底是不是用户输入的强迫症需求 #39 "产品规则可控,感觉好麻烦。。。。" —— 我们程序员骂产品"狗"的时候,很多是因为产品不懂技术瓶颈压力、随便什么需求都敢提 —— 而产品骂程序员的时候也很多是因为程序员只考虑技术、不考虑产品 前阵子雷军不好举例子他亲自下场去当销售才体会到技术人员太执着于技术了做不好产品的嘛 嫌麻烦,其实就是咱没经历过好厂好项目好规范的训练,作坊式的生产、不规范习惯了导致了懒惰,然后反倒去以为别人这么做是多余、说人家麻烦。。 规范、严谨的工程,比如知名开源,或者硅谷那些知名厂的多数项目,规范化得多,提交、合并流程各种繁琐。说起来麻烦,但确实这很规范,大家都规范,也是对自己能力的提升 |
44
zpf124 2022-09-05 13:40:31 +08:00
@GTim 你说了半天我还是没懂,bigint 是如何存储时区信息的? 转 UTC 时间的 timestamp ?
那么用 datetime 还是用 bigint 有差别吗? 为了防止人肉眼看的时候能直接看出来这个是什么时间吗? bigint 和 timestamp 最大的差距仅仅是 2038 的长度问题, 除此之外他们在存储本质上没区别,只是后一个 mysql 可以自动处理给你显示成人类可读的时间。 |
45
xiangyuecn 2022-09-05 13:50:27 +08:00
统统用 varchar ,默认值 '' ,益寿延年,🐶🐶🐶🐶
|
46
zpf124 2022-09-05 13:52:23 +08:00 1
另外,这么多人聊了这么多 居然只有 @kiwi95 提到这个问题的重点,mysql 的 null 索引有性能问题,会慢非常多!
要求 not null + default 的规则制定者中能说明白的大拿都会和你明确的说,mysql 非 null 查询性能会差一个数量级。 这是 mysql 的问题,不知道 8.0 有没有解决,最起码 5.5 5.6 这些规则书写成那个年代的版本是真实存在的性能问题。 而且这只是 mysql 的问题,mysql 小毛病一大堆,所以你网上看到的许多数据库优化的点实际上并不通用,就是针对 mysql 的。 上学时候 学 sql server 还在天天教数据库三范式的年代,哪听说过这种要求。 |
47
zpf124 2022-09-05 13:58:29 +08:00
最后,所有支持 存在 null 才是符合大多数 程序员逻辑的想法, 除非你入门编程语言恰好是非 C 系那几个排斥引用类型有 null 值的语言。
因为数据不存在 null 和 数据存在值为 0 ,含义是不一致的。 让他们表达相同的含义就和前端页面父子组件样式有问题导致挤压错位,然后用绝对定位或者 margin 负数移动回来一样。 在外在表现上看起来是没问题了,但实际上从根本逻辑上讲他就不应该这么处理。 |
49
optional 2022-09-05 14:55:30 +08:00 via iPhone
默认值是业务控制的,不是数据库控制的。数据库尽量不用默认值,空与非空,除非必要,不然可空,业务不可空交给业务控制。
|
50
kiwi95 2022-09-05 14:57:56 +08:00 via Android 1
@RedBeanIce 好,现在给你这个场景做面试题,你真的没有方案吗?
方案肯定有的,就看愿不愿意用。主要还是考虑统一和方便性。前后端通信有意义的值为什么一定要定义 0 呢,0 只是抽象的符号,用什么都可以。 |
51
fournoas 2022-09-05 14:58:02 +08:00
@fengpan567 对。时间戳不允许 NULL 就是___🖊
|
52
lolizeppelin 2022-09-05 15:05:51 +08:00 1
|
53
vishun 2022-09-06 08:43:29 +08:00
主要是 mysql 中如果设置 null 会有很多坑,例如在条件判定需要 is not null ,或者 sum 、groupby 这些函数结果,再有就是部分情况下索引失效,这些都是一不留神会出错的,就算你不出错,你也不能保证团队其他人不出错,所以如果能用空值或者是 0 标识且没有疑义的化还是不要用 null 来比较好。
|