大多数开发者应该都遇到过在mysql字段中存储逗号分割字符串的经历,无论这些被分割的字段代表的是id还是tag,这个字段都应该具有如下几个共性。被分割的字段一定是有限而且数量较少的,我们不可能在一个字符串中存储无限多个字符

这个字段所属的表与这个字段关联的表,一定是一对多的关系

比如下面这个表结构所代表的content与tag这两个对象mysql> SELECT * FROM content;

+----+------+

| id | tags |

+----+------+

| 1 | 1,2 |

| 2 | 2,3 |

+----+------+

2 rows in set (0.01 sec)

mysql> SELECT * FROM tag;

+----+-------+

| id | name |

+----+-------+

| 1 | php |

| 2 | mysql |

| 3 | java |

+----+-------+

3 rows in set (0.00 sec)

这些原则问题,相信大家在开发过程中已经很熟悉了。但是你在使用这种方法来处理实际问题时,内心一定还是有些许忐忑,因为这种方法或多或少看上去有点像野路子。在那本厚厚的《数据库》教材中,也没有提到这种设计方法,标准的方法似乎是应该使用一个关系映射表在这两个表之间插一杠子,尽管这样会使用效率低下的连接查询。

每个开发者都曾纠结于标准与效率,但我想我们的努力能使这种方法的使用看起来更加标准。注意,以下讨论的使用方法仅限于mysql,但其它数据库应该可以移植。

相关性检索

很多开发者还在使用古老的LIKE方法来实现相关性检索,比如上面那个数据库结构中,content表中的两条记录都有2这个tag,那么怎样在我取出记录1时,把与它tag相关的记录也显示出来呢。其实这也是CMS需要面对的一个基本问题,也就是相关内容的查询。

如果你是一个菜鸟,你可能只会想到LIKE方法,比如先把记录1取出来,然后再把tags字段按逗号分割,最后做一个循环用LIKE检索content表中所有tags字段中包含2的记录,类似这样SELECT * FROM content WHERE tag LIKE '%2%' AND id <> 1

但这种方法实在是太慢了,查询次数多不说,LIKE查询本来就是一个比较慢的方法。而且你还要处理前后逗号的问题,总之麻烦是一大堆。

所以让我们静下心来翻翻mysql手册,看看有没有什么惊喜。这个时候,一个名为FIND_IN_SET的函数,会闪着金光映入你的眼帘。让我们看看这个函数的定义

FIND_IN_SET(str,strlist)

Returns a value in the range of 1 to N if the string str is in the string list strlist consisting of N substrings. A string list is a string composed of substrings separated by “,” characters. If the first argument is a constant string and the second is a column of type SET, the FIND_IN_SET() function is optimized to use bit arithmetic. Returns 0 if str is not in strlist or if strlist is the empty string. Returns NULL if either argument is NULL. This function does not work properly if the first argument contains a comma (“,”) character.

哦,PERFECT! 简单说来就是寻找一个字符串是否在另一个以逗号分割的字符串中存在的函数,这简直是为我们量身定做的。那么我们的sql就变成SELECT * FROM content WHERE FIND_IN_SET('2', tags) AND id <> 1

在翻这些函数的过程中,你应该已经深深地体会到mysql的设计者对以逗号分割存储字段方法的肯定,因为有很多方法就是设计用来处理这种问题的。

这样看起来好多了,一切似乎完美了,是这样吗?其实还没有,如果你的tag比较多,你需要创建多个sql语句,而且有的记录关联的tag比较多,有的比较少,怎么能按照相关性进行排列呢。

这个时候,你可以关注mysql的全文检索功能。这个词你肯定看见过无数回了,但是这么使用的肯定很少,让我们直接看语句吧SELECT * FROM content WHERE MATCH(tags) AGAINST('1,2') AND id <> 1

这个语句的优势是显而易见的,你不需要对tags字段做再次分割。那么这种查询的原理是什么呢,稍微了解下MATCH AGAINST的用法就知道,全文检索的默认分隔符是标点符号和stopwords,其中前者正是我们需要的特性。全文检索按照逗号将MATCH和AGAINST里的字符串做分割,然后将它们匹配。

需要注意的是上面sql仅仅是个例子,如果你直接这么执行,是无法得到任何结果的。原因在以下

  1. 你需要对tags字段建立fulltext索引(如果仅仅是测试,可以不做,建索引只是提高性能,对结果没有影响)
  2. 每个被标点符号分割的word长度必须在3个字符以上,这才是关键,我们的tag id太短了,会被自动忽略掉,这个时候你可以考虑让id从一个比较大值开始自增,比如1000,这样它就够长了。
  3. 你撞到了stopwords,比如你的tags字段是这样的'hello,nobody',nobody是mysql的一个默认的stop words,它会被自动忽略。stop words是英文中的一些无意义词,搜索的时候不需要它们,类似汉语中的助词等等。但在我们的使用中显然不是用来做搜索的,因此可以在my.cnf文件里,加上ft_stopword_file=''来禁用它

随着WEB技术的发展,相关搜索走SQL的情况越来越少,很多时候只需要用搜索引擎就可以了。但本文的目的并不只是讨论这种方法,而是体现实现这一结果的过程。

mysql字段中有逗号隔开_在MySQL字段中使用逗号分隔符相关推荐

  1. java中如何在键盘中输入一串以逗号隔开数字然后存入数组中,并输出。

    /***项目:java中如何在键盘中输入一串以逗号隔开数字然后存入数组中,并输出.*时间:2019/8/16*作者:郑翰林*/ import java.util.Scanner; public cla ...

  2. mysql 中有什么命令_常用mysql命令大全

    常用的MySQL命令大全 连接MySQL格式: mysql -h主机地址 -u用户名 -p用户密码 1.例1:连接到本机上的MYSQL. 首先在打开DOS窗口,然后进入目录 mysqlbin,再键入命 ...

  3. mysql查看当前表字符集_查看mysql字符集及修改表结构--表字符集,字段字符集

    MySQL 乱码的根源是的 MySQL 字符集设置不当的问题,本文汇总了有关查看 MySQL 字符集的命令.包括查看 MySQL 数据库服务器字符集.查看 MySQL 数据库字符集,以及数据表和字段的 ...

  4. mysql表名怎么拼接_自学MySQL第九天

    接下来就要开始学习如何创建一个结构良好的数据库. 首先是DATA MODELLING,有四个过程. 1. Understand the requirements 要理解好工作需求才能做出好的数据库. ...

  5. mysql基础小测试三_数据库---MySQL(三)

    一.视图 视图是一个虚拟表,是sql的查询结果,其内容由查询定义.同真实的表一样,视图包含一系列带有名称的列和行数据,在使用视图时动态生成.视图的数据变化会影响到基表,基表的数据变化也会影响到视图[i ...

  6. mysql有类似dbms_output.pu_line();_使用MySQL,SQL_MODE有哪些坑,你知道么?

    SQL_MODE是MySQL中的一个系统变量(variable),可由多个MODE组成,每个MODE控制一种行为,如是否允许除数为0,日期中是否允许'0000-00-00'值. 为什么需要关注SQL_ ...

  7. mysql 显示右边所有名称_查询表 - [ MySql参考手册 ] - 在线原生手册 - php中文网

    一.单表查询 1.1.查询所有字段 1.2.查询指定字段 1.3.查询指定记录 1.4.带IN关键字的查询 1.5.带BETWEEN AND 的范围查询 1.6.带LIKE的字符匹配查询 1.7.查询 ...

  8. MySQL数据库test连接语句_【MySQL数据库开发之二】MySQL 基础语句的书写与操作!...

    本篇Himi简单介绍一些MySQL数据库的基础操作: 注:mysql 语句对大小写不敏感,语句以分号";"标识语句结束: 1.   首先使用两个简单的查询语句: 查询当前版本:se ...

  9. mysql 自动化运维工具_部署MySQL自动化运维工具inception+archer

    *************************************************************************** 部署MySQL自动化运维工具inception+ ...

最新文章

  1. 宏基因组实战10. 绘制圈图-Circos安装与使用
  2. C语言中声明和定义的区别
  3. 给定数组 求和等于固定值 算法_别人家的面试题:不可变数组快速范围求和
  4. 怎样查看电脑开机记录
  5. poj 2653 Pick-up sticks(判断线段相交)
  6. mypow等于1什么意思c语言,C语言基础练习题总结
  7. mac设置python3环境变量_mac下python3的环境变量设置!
  8. java行数可变的表格,怎么在表格中自动增加行,并对输入的数据作判断
  9. 大数据之-Hadoop_大数据技术生态体系---大数据之hadoop工作笔记0014
  10. 挑战程序设计竞赛(第2版) 第3章笔记
  11. tf.one_hot函数用法
  12. Thymeleaf 用法
  13. GoldenGate碎碎念
  14. GD32F103RBT6开发笔记
  15. PR快节奏短视频转场预设 时尚新款照片展示PR免费转场预设
  16. t450加固态硬盘教程_联想 thinkpad t450s 加装固态硬盘及内存图解
  17. OpenCVcv2.imread传入灰度图像,shape还是3通道
  18. Metasploit2: tcp port 139/445 – Samba smbd
  19. 打码,需要一个好的键盘
  20. 成交量占比过半 优信拍继续领跑二手车电商B端市场

热门文章

  1. 第三次学JAVA再学不好就吃翔(part85)--静态导入
  2. 第三次学JAVA再学不好就吃翔(part44)--匿名内部类
  3. 小白的算法初识课堂(part6)--广度优先搜索
  4. SAP Spartacus 中的依赖注入 Dependency Injection 介绍
  5. 如何使用 mock 数据在本地运行 SAP Fiori Elements
  6. SAP Spartacus的ProductAdapter和OccProductAdapter
  7. mySQL初学者一些最常用的命令行
  8. 自定义Java annotation及解析和使用
  9. 微软Azure storage account的path值代表什么含义
  10. 使用SAP Analytics Cloud显示全球新冠肺炎确诊人数和发展趋势的预测