Oracle单列存储逗号分隔值、查询及字段类型选择方法
personal_info表手机号存储问题解答
提示:在关系型数据库里单列存逗号分隔的多值是违反第一范式的反范式操作,后续查起来慢、校验数据麻烦、改起来也容易出问题,能不用就不用,优先用关联表的规范设计。
逗号分隔格式数据的存储方法
如果确定要使用单字段存储逗号分隔的多手机号,直接将多个手机号按要求用, (英文逗号+空格)拼接为完整字符串后写入字段即可。
示例插入语句:
INSERT INTO personal_info (id, name, phone_number) VALUES (1, 'ali', '03434444, 03454544, 0234334');
推荐规范化方案:不要在单列存多值,新增一张关联表person_phone,表结构包含id、person_id(关联personal_info表的id字段)、phone_number三个字段,一个手机号单独存一行,后续所有操作都会更简单高效。
逗号分隔列的WHERE筛选写法
存逗号分隔值的字段不能直接用=做等值匹配,因为字段存储的是拼接后的完整长字符串,等值匹配只会返回整个字符串和查询值完全一致的结果,无法命中其中某一个手机号。
根据使用的数据库不同,可选择对应写法:
- 通用兼容写法(所有关系型数据库都支持,注意加前后分隔符避免子串误匹配,比如查
123不会误命中1234):
SELECT * FROM personal_info WHERE CONCAT(', ', phone_number, ', ') LIKE '%, 03454544, %';
- MySQL环境可以用内置
FIND_IN_SET函数,因为你的分隔符带空格,需要先替换掉空格再匹配:
SELECT * FROM personal_info WHERE FIND_IN_SET('03454544', REPLACE(phone_number, ' ', ''));
如果使用关联表的规范化设计,查询逻辑非常简单,还可以给手机号字段加索引大幅提升查询速度:
SELECT pi.* FROM personal_info pi INNER JOIN person_phone pp ON pi.id = pp.person_id WHERE pp.phone_number = '03454544';
phone_number字段的类型选择
- 若坚持用单字段存逗号分隔多值:选择
VARCHAR类型即可,长度根据你预估的单条记录最多存储的手机号数量计算,比如单条最多存5个8位手机号,算上逗号和空格的占位,设置为VARCHAR(100)就能满足需求。 - 若使用单字段存单个手机号的规范化设计:禁止使用数值类型,因为手机号以0开头,数值类型会自动丢弃开头的0导致数据错误;如果手机号长度固定,选
CHAR类型(比如固定8位就设为CHAR(8)),如果长度不固定选VARCHAR类型,长度设置为比最长手机号多3-5位留冗余即可。
内容的提问来源于stack exchange,提问作者Arifullah
相关产品推荐
相关产品推荐

