IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 【Oracle】字符串查找,只要23不要234 -> 正文阅读

[大数据]【Oracle】字符串查找,只要23不要234

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

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,???

<全文完>

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

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

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-11-19 17:41:33  更:2021-11-19 17:43:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:40:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码