今日用比较优雅的方法解决了一个挺恼人的问题,特记录之。

1 背景

学生表 studeng 有字段:

id, name, courseIDs

分别对应

ID,学生姓名,学生选择的课程ID串

23 |  张三 |  ‘234, 235’

24 |  李四 |  '11,12,13'

课程表 course 有字段:

id, name, score

分别对应

ID,课程名称,课程成绩

23   | 大学语文 | 99

234   | 大学物理 | 100

235   | 大学英语 | 120

上面有2个表。学生表和课程表。

学生表的 courseIDs 里面保存着该学生选择的课程的 ID拼接出的字符串。这是比较常见的设计方式。

2 问题

存取都比较方便方便,但是有个问题。比如我们要

查找

所有选择

大学语文

的学生姓名

该如何写SQL语句呢?

3 探索

我在下面的 SQL 语句中,直接使用大学语文的课程 id,即 23 代表大学语文。

通过“大学语文”文字查找其课程 id 不是本文的重要内容。

首先,通过逻辑推算,我们知道问题中的查找结果应为 空结果集

即,张三和李四都没有选择 大学语文课。

3.1 方法一,初级写法,使用 like 关键词

like 是 SQL 语法中的关键词,也是最常用的模糊查询方法。

select s.name
from student s
where
s.courseIDs like '%23%'

查询结果:

张三

这明显是错误的,但是为什么会发生呢?

因为 like '%%' 是模糊查询,只要匹配就返回。

234, 235’ 是满足 like '%23%' 的要求的,因为里面有 23 。

这是很严重,也经常容易出现的错误。

3.2 方法二,使用 instr() 、substr() 函数

注意:instr() 、substr() 都是Oracle数据库软件的内置函数,并非标准的 SQL 语法关键词。也就是说用到这些函数的SQL语句,在MySQL和MS SQL Server是直接报语法错误、无法执行的,只能在 Oracle 数据库中使用。

题外话:其实在 MySQL 中,使用MySQL的内置函数 find_in_set 实现这个问题就特别简单,后面会讲。

这些函数的具体解释不多说了,简单说就是 instr() 返回目标字符串在源头字符串的位置,若查无结果,则返回0。例如:

select instr('helloworld','lo') from dual;  返回结果:4 即:在“lo”中,“l”开始出现的位置。

用这个函数写出SQL语句:

select s.name
from student s
where
instr(s.courseIDs, '23') != 0

查询结果:

张三

同样是错误的。其实 instr() 函数 和 like 关键词有些类似,都是只要出现 23 就认为匹配成功了。而我们要的是独立的23 ,而不是 234 里面的 23。

3.3 方法三,高阶玩法,正则表达式函数 regexp()

很容易的,我们就想到 正则表达式 中的贪婪查询。

正则表达式 就是字符串匹配和查找的神,基本可以满足所有的查找和替换需求。

如果你是一名程序员,却不了解正则表达式,那你一定是一名不合格的程序员。

Oracle内置有四个正则表达式查询函数,非标准SQL语法。

REGEXP_LIKE() :与LIKE() 的功能相似
REGEXP_INSTR() :与INSTR() 的功能相似
REGEXP_SUBSTR() :与SUBSTR() 的功能相似
REGEXP_REPLACE() :与REPLACE() 的功能相似

正则表达式用法我就不写了,反正就是很复杂。下面直接讲我的简单解决方案。

3.4 博主实现的简单方案

思路

其实我们需求很明确,就是只要 23 不要 234。就是如何精确的查找到 独立的 23。

我们观察 courseIDs 用逗号 “,”拼接出的字符串,这个逗号“,"本身就是个天然的分隔符,既然本身就有分隔符,为什么查询的时候不可以用呢?

阻碍1

可以使用  23,  来查询,但是 couseIDs 字符串  234,235  最后末尾少了个逗号啊。这个表的数据我没有权限修改,不能在数据后面加逗号。

并且如果大学语文是 34,那我用   34,   来搜索  234,235  ,依然是查找成功,即查询结果依然会返回张三,说明这个查询策略是有严重BUG的。

阻碍2

那我前面加个逗号,使用 ,23, 来查询呢。但是  couseIDs 字符串 234,235   不仅末尾少了个逗号,最前面也没有逗号,碰到查询第一个和最后一个ID就会查询不到。我们查询  ,234,  就会遗漏了张三。怎么办呢?

解决

我们无需修改数据库表中的数据,只需要在SQL语句中在字段内容前后 拼接上一前一后两个逗号就行了。

查询得知,Oracle有个运算符 “||”可以拼接字符串。于是,有下面的SQL:

select s.name
from student s
where
instr(
','||s.courseIDs||','
,
',23,') != 0

原理很简单:在 s.courseIDs 即  234,235  的首尾各加一个 逗号(变成 ,234,235, ),然后再使用 instr() 函数查询该字符串   ,234,235,  里面是否有 ,23,  。这样就可以使用天然的逗号分隔符,把每个独立的ID数字都独立的包裹起来。

限制条件

很明显,这个方法必须在该字段的数据非常规整的前提下使用的。如果数字与逗号之间出现空格或空白字符,会查询失败。如  ,56   ,  88,   可能就无法查找到  ,56,  和 ,88,   

<全文完>

写文不易,就这一行语句写了近三个小时。如果有收获请点赞支持。

全博所有文章欢迎转载,转载注明出处即可。

【Oracle】SQL字符串查找_精确查询,只要23不要234相关推荐

  1. oracle空格太多,Oracle Sql字符串多余空格处理方法初记

    (一)问题提出: 不知道大家有没有遇到过这样的情况,同样的sql在pl/sql下面执行正常,但是拷贝到表字段中,点击提交的时候老是会报ORA-01480: STR 绑定值的结尾 Null错误,如图: ...

  2. oracle绑定值的结尾,Oracle Sql字符串多余空格处理方法小记

    (一)问题提出: 不知道大家有没有遇到过这样的情况,同样的sql在pl/sql下面执行正常,但是拷贝到表字段中,点击提交的时候老是会报ORA-01480: STR 绑定值的结尾 Null错误,如图: ...

  3. sql字符串函数_另一堆SQL字符串函数

    sql字符串函数 This article is a supplement to the previously published article, An overview of SQL String ...

  4. java oracle 连接字符串函数_通过shell来比较oracle和java中的字符串使用

    这些准备工作齐了之后,我们来从Java中的字符串使用入手来比较一下oracle中对于字符串的处理. java中有如下的一些函数,我会依次来做比较. public char charAt(int ind ...

  5. oracle sql语句执行顺序、查询效率分析、步骤解析

    语句 执行顺序 select –5 from –1 where –2 group by –3 having –4 order by –6 查询语句中select from where group by ...

  6. oracle中执行字符串sql语句,Oracle SQL 字符串操作

    这些函数全都接收的是字符族类型的参数(CHR除外)并且返回字符值. 除了特别说明的之外,这些函数大部分返回VARCHAR2类型的数值. 字符函数的返回类型所受的限制和基本数据库类型所受的限制是相同的. ...

  7. MySQL-获取有性能问题SQL的方法_慢查询 实时获取

    文章目录 生猛干货 官方文档 使用慢查询获取慢SQL 慢查询的相关参数 slow_query_log 是否开启了慢查询 开启慢查询 slow_query_log_file 指定慢查询日志的存储路径及文 ...

  8. oracle多表嵌套查询使用,oracle sql 多表 嵌套子查询 连接查询, join where exist i...

    转:http://hi.baidu.com/delphi_relive/blog/item/d7c0034a49c4932208f7ef21.html in 和 exists也是很好区别的. in 是 ...

  9. oracle sql 多表 嵌套子查询 连接查询, join where exist in 的区别

    sql中exits和in的区别 转:http://hi.baidu.com/delphi_relive/blog/item/d7c0034a49c4932208f7ef21.html in 和 exi ...

最新文章

  1. Vue项目build后静态资源文件路径或新建文件夹图片路径找不到的问题
  2. system.out.println从什么方向执行
  3. Windows下部署最新版青龙、诺兰、傻妞入门保姆级教程
  4. 世界地图20亿像素_高通骁龙690 5G平台发布,支持1.92亿像素性能提升20%
  5. evernote100个做笔记的好方法
  6. 修改webpack的publicPath为动态设置以适配公司活动平台
  7. 前端学习(3014):vue+element今日头条管理--表单验证基本使用2
  8. 计算机设计大赛国奖作品_3. 需求分析
  9. 从0到1详解数据挖掘过程
  10. flask mysql项目模板渲染_Flask系列(二) 模板 templates
  11. layui 行变灰_layui table设置某一行的字体颜色方法
  12. pythonwhile循环怎么修改数据类型_分级程序有while循环问题,使用不同的数据类型...
  13. 三菱fx2n做从站的modbus通讯_三菱FX2N与昆仑通态(MCGS)无线编程口通讯例程
  14. from表单requried属性效果
  15. 解只含加减的一元一次方程
  16. 数学建模优化模型简单例题_数学建模例题.doc
  17. java pdf 加水印
  18. python调用微信截图_Python调用微信截图工具
  19. python爬取京东商品图片_爬取京东和天猫下载商品图片
  20. 400元DIY实现手机 笔记本 GPS导航

热门文章

  1. MATLAB人民币面额识别
  2. 数据库事务的四大特性和四个隔离级别
  3. matlab画晶体结构图,#绘图教程专栏#不会画分子晶体结构模型?看了这篇教程就会了!...
  4. 从唐僧师徒来看团队精神
  5. Python生成密码字典教程
  6. 51单片机定时器2用作串口
  7. 一些Java实用技巧(量变转变为质变后会单独整理出来)
  8. 全国计算机比赛ccf比赛时间,2019年全国青少年信息学奥林匹克相关通知
  9. 斑马打印机的安装调试,生成PDF
  10. 潭州教育python学院_潭州什么学院,直播python课程内幕