1
oneisall8955 2022-09-12 13:56:05 +08:00 via Android
读出来那还要算一下?查找时候呢
|
2
imicksoft 2022-09-12 13:59:58 +08:00
按身份证算法,知道前面的,最后一位可以算出来
|
3
IvanLi127 2022-09-12 14:01:25 +08:00 via Android
数字的话,模糊匹配会不会很蛋疼。还有就是,怕领导哪天想着去掉校验,允许存错的可咋整
|
4
wxf666 2022-09-12 14:03:25 +08:00 5
其实 int64 可以完全存下,包括校检位在内的,完整身份证号:
1. 用 ⌈ log2(10^17) ⌉ = 57 位来存前 17 位数字 2. 用 ⌈ log2(11) ⌉ = 4 位来存校检位 还剩 64 - 57 - 4 = 3 位空闲 或者,校检位视为两位数(那么身份证就是 19 位),刚好可用 ⌈ log2(10^19) ⌉ = 64 位存下 |
5
eason1874 2022-09-12 14:04:21 +08:00 3
别整花里胡哨的,CPU 比硬盘内存贵多了,用空间换时间是最有性价比的
|
6
janus77 2022-09-12 14:20:38 +08:00
可以但没必要
少一位数字能省多少磁盘啊 |
7
Kinnice 2022-09-12 14:22:53 +08:00 via Android
有没有可能用户输得是错的
|
8
iseki OP @oneisall8955 @IvanLi127 如果是字符串正则查找,那确实是不行了,不过我没见过这种场景;允许存错误的身份证号这就没办法了🤣除非在一开始明确提出我不会考虑这种需求
@wxf666 可以是可以,主要会不直观,如果只是简单去掉最后一位,不影响以十进制方式阅读 @janus77 主要是便于用数值而非字符串类型存储,19+字节变成定长 8 字节吧,我觉得对于某些量大的场景还是很划算的。 @eason1874 只有在系统边界将身份证号类型装换成字符串类型传输的时候才需要计算和补足最后一个校验码,校验算法非常简单,所以应该不会消耗过多的 CPU |
9
iseki OP 话说大家真的有遇到过身份证号模糊匹配的需求吗,这点有些好奇,我确实没见过…
|
10
wxf666 2022-09-12 14:37:57 +08:00 1
@iseki
> 可以是可以,主要会不直观,如果只是简单去掉最后一位,不影响以十进制方式阅读 那『校检位视为两位数(那么身份证就是 19 位)』适合你啊。比如: - 123456789012345678 会存储为:1234567890123456708 - 12345678901234567X 会存储为:1234567890123456710 |
12
iseki OP @wxf666 还是不行,很多地方不便于使用 无符号数,那么实际上可用的值最大只有 2^63 ,溢出了
|
13
GuuJiang 2022-09-12 14:47:22 +08:00
强烈反对这样做,并不是所有看起来由 0-9 组成的东西都是数字,身份证号、银行卡号、学号等本质是“数码”而不是“数字”,对这类“数字”进行数学运算是没有任何意义的,可能存在的运算是作为字符串运算(因为现实当中制定数码时通常会让某一段具备某种含义),讽刺的是,哪怕微软都在犯这种低级错误
|
14
wxf666 2022-09-12 14:54:20 +08:00 1
@iseki 那就正负号代表校检位是否不为 X 呗。。比如:
- 123456789012345678 会存储为:123456789012345678 - 12345678901234567X 会存储为:-123456789012345670 需要使用 1 位符号位 + ⌈ log2(10^18) ⌉ = 1 + 60 = 61 位 |
15
iseki OP @GuuJiang 换一个思考方式会不会好一点:我只是借用了一个 64bit 的数据类型(这个类型很常见)并没有把它当作数值进行计算,实际上这也没有意义;
而所谓的字符串也好,我这种做法也好,实际上都是身份证号的一种编码方式,相对于 144bit 更加节省而已~ |
16
janus77 2022-09-12 15:05:35 +08:00
@iseki #8 没那么多吧……按你这样算,就算我每个身份证号可以减少 10 个字节,15 亿个也就减少十几个 G ,不知道算对了没?
|
17
iseki OP 当然,程序内部往往不存在借用类型的需要,这种情况应该创建一个正常的「身份证号」数据类型,我所谓的「借用」更多时候指在 SQL 数据库中,有些数据库不能方便的创建类型别名或者增加自定义类型
|
19
iseki OP 得···打错了···的是 -> 是的
|
20
dcsuibian 2022-09-12 15:24:33 +08:00 via Android
身份证号存数字。。。来个模糊搜索看看
|
21
agagega 2022-09-12 15:45:53 +08:00 via iPhone
身份证号分段存 int 里,不到 50 位也能解决。所以就算存校验位你也可以单独拿出来。
|
22
ClarkAbe 2022-09-12 15:54:37 +08:00 via Android
你们身份证存明文?不过等保不怕泄漏嘛
|
23
wxf666 2022-09-12 16:14:14 +08:00
|
24
wxf666 2022-09-12 16:19:20 +08:00
|
25
dcsuibian 2022-09-12 16:59:56 +08:00
@wxf666 对啊,就这种用字符串做的话就很方便啊。
更一般点,最最普通的模糊搜索,就是写身份证片段,然后列出所有相关的吧。字符串 like 一下就很简单,但换成数字就很难做的。 |
26
jim9606 2022-09-12 17:17:35 +08:00 via Android
不是为了极限缩减数据库存储的没必要这么搞。
要知道存证件号的字段有可能扩展为存任意证件号,难道你们会为每一种证件类型开一列? |
27
wxf666 2022-09-12 18:11:58 +08:00
@dcsuibian 假设用『校检位视为两位数(那么身份证就是 19 位)』方法:
(`SQL` 大意,具体写要改成 `DIV`、`CAST(1e13 AS UNSIGNED)` 等) 1. 查找所有 x 省 y 市 z 区 /县 的人 - 不用索引:`身份证号 / 1e13 = 123456` - 要用索引:`身份证号 BETWEEN 1234560000000000000 AND 1234569999999999999` 2. 查找所有 35 岁以上的人 - 不用索引:`身份证号 / 1e5 % 1e8 < 19870912` 3. 查找所有 x 省 y 市 z 区 /县 20 岁 ~ 35 岁 的人 - 要用索引:`身份证号 BETWEEN 1234561987091200000 AND 1234562002091299999` |
28
agagega 2022-09-12 18:14:03 +08:00 via iPhone
@wxf666
前六位所在地用 20 位整数可以表示(如果熟悉相关国家标准还可以进一步压缩) 出生年存 8 位整数,表示 1900 年以来的年数 出生月存 4 位整数 出生日存 5 位整数 最后 3 位存 10 位整数 虽然这样挺无聊的… |
29
NXzCH8fP20468ML5 2022-09-12 18:21:58 +08:00
你们这些人好勇啊。
用大量身份证进行遍历,准不准另说,合规就是大问题吧。 |
30
wxf666 2022-09-12 18:24:22 +08:00
@dcsuibian
修改一下: `身份证号 / 1e5 % 1e8 < 19870912` 应该可以改成 `身份证号 % 1e13 < 1987091200000` > 写身份证片段,然后列出所有相关的 这个需求,是不是要一直扫表了。。 实在不行,就实时转换成原身份证号再 LIKE 呗: CONCAT(身份证号 DIV 100, MID('0123456789X', 身份证号 % 100 + 1, 1)) LIKE ... |
31
wxf666 2022-09-12 18:39:37 +08:00
|
32
iyaozhen 2022-09-12 19:17:34 +08:00
|
34
cxk0 2022-09-12 19:32:16 +08:00 1
你就是想身份证存数字.那就把最后一位 X 的话,去掉一位,其他照常存,这样遇到 X 结尾的数据自然会比其他数据小一位。
非 X 直接数字可存。 |
35
mythabc 2022-09-12 19:35:21 +08:00
那护照另开一个表存吗?
奇葩的还有一堆证件号是带括号的,即使是英文字符,用户也会给你输一堆奇奇怪怪的东西进来。 |
36
dcsuibian 2022-09-12 20:22:27 +08:00
@wxf666 这么做是可以,但无论是对 DBA 和程序员来说都并不友好,增加了操作和代码的复杂度,同时在检索时还会增加数据库的计算量。
用数字存储减少磁盘占用。int64 算 8 字节,14 亿个是 10.43GB ,我这里 sizeof(身份证字符串)是 19 字节,直接算 3 倍好了。那也就是 31.2GB 。现在这个时代,省这点容量是真的划不来。 至于模糊查询,我觉得在公司、企业、学校 OA 系统中比较有可能出现。主要是这种查询多变没法提前写好。 |
37
kingjpa 2022-09-12 20:46:14 +08:00
都没做过业务层的 curd 吗?
除了金融类 哪个业务输入 18 位身份证号? 不都是后 6 位? |
38
wellerman 2022-09-12 21:02:00 +08:00
我在业务上遇到过。分 3 段存,X 直接替换成 10 。比较完美。
|
39
panerai 2022-09-12 23:33:19 +08:00
话说你们身份证存的时候不脱敏的吗?
|
40
dlsflh 2022-09-13 07:41:30 +08:00 via Android
我想知道要是有人存了一位伟人的身份证号这时候会怎么处理?
|
41
makun123 2022-09-13 10:13:11 +08:00
我想知道 你们数据库存的身份证号难道是明文存储么?
|
42
Yuunie 2022-09-13 10:14:09 +08:00
```javascript
function idCardLast(id = '') { if (id.length !== 17) return false const rules = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2] const lastSymbol = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'] const lastIndex = (Array.from(id).reduce((sum, value, index) => { return sum + (value * rules[index]) }, 0)) % 11 return lastSymbol[lastIndex] } ``` |
43
paouke 2022-09-13 10:30:31 +08:00
我也想问,直接就身份证号明文存库,这么勇的吗
|
44
stoluoyu 2022-09-13 10:57:47 +08:00
虽然但是,身份证号要加密存。
|