| |
|
开发:
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?有字段:
分别对应?
课程表 course 有字段:
分别对应
上面有2个表。学生表和课程表。 学生表的 courseIDs 里面保存着该学生选择的课程的 ID拼接出的字符串。这是比较常见的设计方式。 2 问题存取都比较方便方便,但是有个问题。比如我们要
该如何写SQL语句呢? 3 探索我在下面的 SQL 语句中,直接使用大学语文的课程 id,即 23 代表大学语文。 通过“大学语文”文字查找其课程 id 不是本文的重要内容。 首先,通过逻辑推算,我们知道问题中的查找结果应为 空结果集。 即,张三和李四都没有选择 大学语文课。 3.1 方法一,初级写法,使用 like 关键词like 是 SQL 语法中的关键词,也是最常用的模糊查询方法。
查询结果:
这明显是错误的,但是为什么会发生呢? 因为 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语句:
查询结果:
同样是错误的。其实 instr() 函数 和 like 关键词有些类似,都是只要出现 23 就认为匹配成功了。而我们要的是独立的23 ,而不是 234 里面的 23。 3.3 方法三,高阶玩法,正则表达式函数 regexp()?很容易的,我们就想到 正则表达式 中的贪婪查询。 正则表达式 就是字符串匹配和查找的神,基本可以满足所有的查找和替换需求。 如果你是一名程序员,却不了解正则表达式,那你一定是一名不合格的程序员。 Oracle内置有四个正则表达式查询函数,非标准SQL语法。?
正则表达式用法我就不写了,反正就是很复杂。下面直接讲我的简单解决方案。 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:
原理很简单:在 s.courseIDs 即? 234,235??的首尾各加一个 逗号(变成?,234,235, ),然后再使用 instr() 函数查询该字符串? ?,234,235, ?里面是否有 ,23,??。这样就可以使用天然的逗号分隔符,把每个独立的ID数字都独立的包裹起来。 限制条件很明显,这个方法必须在该字段的数据非常规整的前提下使用的。如果数字与逗号之间出现空格或空白字符,会查询失败。如? ,56? ?,? 88,? ?可能就无法查找到? ,56,? 和?,88,??? <全文完> 写文不易,就这一行语句写了近三个小时。如果有收获请点赞支持。 全博所有文章欢迎转载,转载注明出处即可。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
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- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |