作者:empty 出版社:empty |
Oracle高级SQL培训与讲解
李康康 liakngkang@126.com QQ:353730289
1With子句
1.1学习目标
掌握with子句用法,并且了解with子句能够提高查询效率的原因。
1.2With子句要点
1.with子句的返回结果存到用户的临时表空间中,只做一次查询,反复使用,提高效率。
2.如果定义了with子句,而在查询中不使用,那么会报ora-32035 错误:未引用在with子句中定义的查询名。
3.前面的with子句定义的查询在后面的with子句中可以使用。但是一个with子句内部不能
嵌套with子句。
4.当一个查询块名字和一个表名或其他的对象相同时,解析器从内向外搜索,优先使用子查询块名字。
5.with查询的结果列有别名,引用的时候必须使用别名或*。
6.with有可能影响执行计划。
1.3with子句语法
With alias_name as (select1), --as和select中的括号都不能省略
alias_name2 as (select2),--后面的没有with,逗号分割,同一个主查询同级别地方,with子
查询只能定义一次
…
alias_namen as (select n) –与下面的实际查询之间没有逗号
Select ….
1.4with使用例子:
1.最简单的使用方法:
如查询部门名称包含“A”的所有员工信息
--with clause
with a as
(select deptno from dept where dname like '%A%')
select * from emp where deptno in (select * from a);
with a as
(select deptno from dept where dname like '%A%'),--a结果集
a2 as(select * from a where deptno>20)--a1结果集直接从a中筛选
select * from emp where deptno in (select * from a2);
2.多层同级只能用一个with,并且后面的结果集可以使用前面的结果集:
查询部门名称包含“A”并且部门编号大于20的所有员工信息
with a as
(select deptno from dept where dname like '%A%'),--a结果集
a2 as(select * from a where deptno>20)--a1结果集直接从a中筛选
select * from emp where deptno in (select * from a2);
3.不同级查询可以使用多个with:
查询部门名称包含“A”并且部门编号大于20的所有员工信息的另外一种实现方式如下
with a as
(select deptno from dept where dname like '%A%')--a结果集
select * from emp where deptno in (--括号内层作为子查询,为第二级
with a2 as(select * from a where deptno>20)--a1结果集直接从a中筛选
select * from a2
);
1.5使用场景
那什么情况下能使用到with子句呢?以下我就举几个简单的例子,简单的说明以下:
1.我想测试一句sql,而我不想专门建立一个测试表:
我想测试成绩大于90的学生,我不想建立学生表,可以用到with子句
with stu as(
select '张娜' sname,99 score from dual union
select '王杰' ,35 from dual union
select '宋丽' ,85 from dual union
select '陈晓' ,73 from dual union
select '李元' ,100 from dual
)--with 组成一个临时的结果集,存放在用户的临时表空间
select * from stu where score>90
2.当一个sql重复用到某个相同的结果集作为子查询:
--查询销售部工资>1500或者销售部工资小于1000的员工
select * from emp where deptno=(select deptno from dept where dname ='SALES') and sal >1500
union all
select * from emp where deptno=(select deptno from dept where dname ='SALES') and sal 1000
--以上sql select deptno from dept where dname ='SALES'需要执行两次,影响效率
--可以使用with优化一下
with salno as(select deptno from dept where dname ='SALES')
select * from emp where deptno=(select * from salno) and sal >1500
union all
select * from emp where deptno=(select * from salno) and sal 1000
2集合操作
2.1学习目标
掌握union,union all,minus,intersect的使用,能够描述集合运算,了解内部运行原理。
2.2要点
Union all 效率一般比union高。Union all内部不做排序工作,也不做剔除
重复行工作,而union则做这个工作。所以当数据量比较大的时候,能用union all的时候尽量用union all。除了union all 默认不做排序和剔除重复行的操作外,
union,minus,intersect都默认按第1个查询结果的第1列进行升序排列,并且
不包含重复行。
2.3语法
(select resource 1)
Union/union all/minus/intersect
(select resource 2)
Union/union all/minus/intersect
(select resource 3)
……….
其中查询结果集的各个字段的类型能够互相兼容,并且总的结果集字段名与第一个结果集相同。
2.4使用案例
数据准备:
create table t1 as select rownum rn from dual connect by rownum 7;
create table t2 as select rownum+3 rn from dual connect by rownum 7;
1.查询t1和t2表的所有记录,不去除重复。
2.查询t1和t2表的所有记录,去除重复。
3.查询t1和t2表都存在的记录
4.查询t1表存在,t2表不存在的记录
5.排序操作:
6.除了union all其他的全部会在总的结果集中剔除重复,例如:
insert into t1 values(1);
commit;
现在t1表中有两条相同的记录,其rn的值为1。
在进行集合运算时重复的记录被剔除:
2.5使用场景
当要对多个结果集进行集合操作时,可是使用集合操作。
3case与decode
3.1学习目标
会使用case表达式和decode函数,理解各个参数和返回值的含义。
3.2要点
Case表达式:
1.When后面的表达式类型应该全部保持一致,返回值类型也必须保持一致,或者能够进行隐式转换。
2.case 表达式 when 值,如果值是null,就算表达式也是null,结果也是返回false。也就是case 后面的表达式如果值为null,不会与when null 匹配,只会与else 匹配。
Decode函数的使用方法与case when相似,但是decode只能用等号匹配。
3.3语法
Case表达式第一种:
case exp when comexp then returnvalue
..when comexp then returnvalue
Else
Returnvalue
End
Case表达式第二种:
case when Boolean then returnvalue
..when Boolean then return value
Else
Returnvalue
End
Decode函数:
decode(exp,
value1,res1,
value2,res2,….,
valuen resn,
elsevalue)。
3.4使用案例
Case 第一种用法:
Case 第二种用法:
Decode用法:
上文提到过null,碰到null的时候要注意,比如:
这种情况可以这样处理:
如果用decode函数:
3.5使用场景
当我们的sql要求根据不同的条件返回不同的值时,可以使用。
4exists与in、not exists与not in
4.1学习目标
掌握exists与in的、not exists与not in的用法,了解其内部的执行顺序 与执行原理,知道什么情况下用exists,什么情况下用in。
4.2要点
1.Exists 用于只能用于子查询,可以替代in,若匹配到结果,则退出内部
查询,并将条件标志为true,传回全部结果资料。
2.若子查询结果集比较小,优先使用in,若外层查询比子查询小,优先使用exists。因为若用in,则oracle 会优先查询子查询,然后匹配外层查询,若使用exists,则oracle 会优先查询外层表,然后再与内层表匹配。最优化匹配原则,拿最小记录匹配大记录。
4.3语法
In:Select select_fields from table_name where field_name in(select clause);
Exists:Select select_fields from table_name exists (select clause)
4.4使用案例
查询员工部门编号在部门表中存在的员工记录:
以上语句可以用Exist替换:
另外not in和not exists在某些情况下也可以相互转换,但是要注意一点,not in中的子查询返回的结果集包含null值的时候,查询会失效。例如我想查询对应员工记录数为0的部门。如下:
用not exists:
以上语句不能用not in替换:
查询失效无记录返回。注意这并不是oracle的bug,因为在oracle中null不表示空,而是表示未知,当使用not in的时候,如果子查询返回的结果集中包含null值,我们并不知道外层查询的记录在不在子查询返回的结果集之内,所以无记录返回。虽然这样,但是并不表示not in和not exists是完全不可以转换的,比如子查询所选的字段在对应的表中没有null值,这时not in和not exists是可以相互转换的。或者在某些情况下内层子查询加上field_name is not null限制条件也是可以的。
4.5使用场景
当内层查询返回的结果集较小时,用in 或者not in效率较高。当内层子查询返回的结果集比较大时,用exists或者not exists执行的效率较高。
5行列互换
5.1学习目标
掌握列转行技术和常用的行专列技术。
5.2要点
行专列的情况有多种,不同的情况侧重点也不一样。
5.3语法
5.4使用案例
1.列转行
第一种方法:需要用到union或者union all:
第二种方法:用到model
2.行专列,如我有escore表用来记录每个学生每个科目的成绩,如下:
如果我想将每个学生的成绩统计在一行上,如:
3 语文 11 数学 55 英语 66
则我可以使用如下sql:
这个sql表面上看没什么问题,但是仔细看一下三个结果集es、ys和ss,他们来源于同一个表,而且查询方法也类似,都是根据type的值去筛选的,这样就会对escore表查询三遍,严重影响查询速率,那这个sql我们如何去优化呢!
首先在你的脑海里面要有一种思路,根据需求,原先每个学生成绩有多行记录,现在要显示到一行上,那一般情况下我们是需要根据学生分组的。所以group by sid 这个是一定要有的,既然分组那我们可是使用oracle的聚合函数去求其他行的数据。至于科目字段目前都是已知的,也就是第2,4,6列显示的分别是英语、语文、数学这几个字,是常量,我们不用去考虑,那剩下的也就是最关键的,我们去求三科的成绩就可以了。
让我们再看一下escore表,当指针移到某一行数据时,当type=e时,我们就取到score,加到第三列上,那第五列和第七列就加0,也就是sum(decode(type,’e’,score,0)),其他列类似,这样group by时用到的聚合函数还有decode结合在一起使用,就可以完成我们的要求了,sql写出来时这样的:
3.字符串组合的多行转一列,例如我有一张测试表如下:
我想根据id分组,将每一行的name连接起来,如下图是我想要的结果:
这种行转列不是真正意义的行转列,是多行数据的值拼接后显示到一列上,那这种情况怎么处理呢,首先分析一下:多行id相同的值转换成一行,一般情况下需要用到group by,但是对于字符串,oracle中没有一个聚合函数适合用到此处的字符串连接,那该怎么办呢?
在oracle中,有sys_connect_by_path(field_name,concat_value)函数,可以通过connect by来依次连接每一行的数据,connect by 的语法是这样的:
start with field1=1--以当前表达式返回true的行开始
connect by prior field2=field3--通过当前行查找下一行,也就是说某一行数据的field3字段等于当前行的field2,那就把这行数据作为下一行
有了这个思路,我们就可以用connect by 通过使用sys_connect_by_path(field_name,concat_value)这个函数,并且根据id分组,将字符串连接在一起,然后通过max聚合函数,选出每组最长的字符转就可以了,那剩下的也就是最关键的问题就是我怎样去使用connect by,通过当前行找到下一行呢?充分发散一下你的思维,看一下如下结果集:
那我下一步用如下思路使用connect by将所要的结果查询上来:
start with lg is null--以lg为null的行作为起始行
connect by prior rn=lg and prior id=id --当前行与其他行比较,满足这个条件的就作为下一行数据
总的查询结果如下:
其实怎么使用connect by 方法很多,例如如下sql也能完成:
5.5使用场景
当开发过程中,需要我们将多列转换成多行或者将多行转换成多列的时候,就需要用到行列转换,要根据不同的情况确定不同的结果方案,典型的行列转换就这几种,还有一种比较复杂的是不定不定行专列,不定行转列需要用到oracle的package,在次先不做讲解。
6merge into
6.1学习目标
掌握merge into,学会使用merger into批量处理数据。
6.2要点
1.MERGE语句是Oracle9i新增的语法,用来合并UPDATE和INSERT语句。
2.过MERGE语句,根据一张表或子查询的连接条件对另外一张表进行查询,连接条件匹配上的进行UPDATE,无法匹配的执行INSERT。
3.这个语法仅需要一次全表扫描就完成了全部工作,执行效率要高于INSERT+UPDATE。
6.3语法
MERGE [INTO [schema .] table [t_alias]
USING [schema .] { table | view | subquery } [t_alias]
ON ( condition )
WHEN MATCHED THEN merge_update_clause
WHEN NOT MATCHED THEN merge_insert_clause;
6.4使用案例
1.基于escore表创建escore2表,英语成绩每个同学加上5分的课时分,新增政治成绩,如下:
create table escore2 as select sid,type,score+5 score from escore where type='e'
insert into escore2 values(1,'z',31);
insert into escore2 values(2,'z',45);
insert into escore2 values(3,'z',66);
insert into escore2 values(4,'z',76);
commit;
根据escore2表更新escore表,根据sid和type匹配,对于已经存在的记录进行更新操作,对于不存在的记录进行插入操作。
merge into escore t
using escore2 t2--此处可以是表、视图和查询结果集
on (t.sid=t2.sid and t.type=t2.type)--匹配条件,需要加括号
when matched then
update set t.score=nvl(t2.score,decode(t.type,'e',5,0))--根据匹配条件,更新escore
when not matched then
insert values(t2.sid,t2.type,t2.score)--无匹配条件的记录,插入新记录
执行merge以后的escore表如下:
注意update的时候不能修改匹配的连接字段,否则就会报错。
6.5使用场景
当要依赖别的表、视图或者结果集批量修改和插入目标表数据时,可以使用此方法,运行速率快,而且简单。
7group by高级特性
7.1学习目标
学会使用group by语句,学会使用group by输出小计、合计。
7.2要点
1.在select 语句中可以使用group by 子句将行划分成较小的组,然后,使用聚合函数返回每一个组的汇总信息。
2.可以使用having子句限制返回的结果集。
3.在带有group by 子句的查询语句中,在select 列表中指定的列要么是group by 子句中指定的列,要么包含聚组函数语法。
4.使用rollup操作符产生subtotal(小计)的值,cube 操作符产生cross-tabulation(列联交叉表)的值。
5.使用grouping函数标识通过rollup和cube 建立的行的值。
6.使用grouping sets产生一个single result set(结果集)。
7.使用grouping_id和group_id函数。
7.3使用案例
1.查询部门员工的最高工资大于1500的部门,如下:
相信这样的案例大家已经很熟悉了,以下讲解一下group by的高级特性。
2.Rollup可以返回合计,例如:
rollup(a,b) 包括:(a,b)、(a)、()的合计
rollup(a,b,c) 包括:(a,b,c)、(a,b)、(a)、()的合计
我想按班级和学生分组,查询班级下学生的总分,并且做一下小计,使用以上的escore表,并且新建学生班级的关系表如下:
create table refcs as
select 1 cid,1 sid from dual
union all select 1,2 from dual
union all select 2,1 from dual
union all select 2,2 from dual
则查询的sql如下,红色区域是每个班级的总分合适,蓝色区域是所有的总分合计:
3.cube可以返回交叉的合计,例如:
cube(a,b) 包括:(a,b)、(a)、(b)、()
cube(a,b,c) 包括:(a,b,c)、(a,b)、(a,c)、(b,c)、(a)、(b)、(c)、()
与rollup相比,多了灰色区域,灰色区域是对分组的第二个字段sid的小计,用来统计每个学生的总分数,但在此是没有多大意义的,因为学生和班级是1->n的关系,统计每个学生的总分数和统计每个班级下每个学生的总分数没有区别。
4.GROUPING函数可以接受一列,返回0或者1。如果列值为空,那么GROUPING()返回1;如果列值非空,那么返回0。GROUPING只能在使用ROLLUP或CUBE的查询中使用。当需要在返回空值的地方显示某个值时,GROUPING()就非常有用。
看如下sql,红色区域和蓝色区域的grouping参数字段是null,因此grouping字段返回1,非null时返回0:
但是返回0和1似乎没有多大意义,通常返回一些有意义的字符串可读性能好一些,如下:
其实你可以再优化一下,让第一行只显示“总计”两个字。
5.Grouping sets:以上用GROUP BY ROLLUP或GROUP BY CUBE替代GROUP BY,来计算高级的统计,不过它们会生成所有可能的总数,而你可能不需要全部总数,可以用GROUP BY GROUPING SETS来代替GROUP BY CUBE。你可以应用来指定你感兴趣的总数组合。因为它不必计算它不需要集合(也不会产生太多结果),所以对SQL引擎来说更为高效。例如:
在图中我已经用不同颜色的边框和箭头指明某行数据来源于grouping sets之后的哪些集合。
7.4使用场景
分组时常用。
8分析函数
8.1学习目标
掌握分析函数的使用,能用分析函数解决复杂查询等问题。
8.2要点
1.分析函数可分为四类:等级函数(ranking),聚合函数(aggregate),行比较函数(row comparison),统计函数(statistical)。
2.
8.3语法
函数名(参数)over(partition by …order by…windows clause)
8.4使用案例
1.Row_number,rank,dense_rank属于等级函数,例如,我想根据部分分区,查询部门内部员工公司的排名,看一下用这三个等级函数会有什么区别:
我们发现三个函数都是返回分区排序后的序号,不同之处在于排序字段相同时,row_number是从1到n连续不跳号的,rank是给予值相同的两行相同的序号,而且跳号,dense_rank也是给予值相同的两行同样的序号,但是不跳号。
2.常用分析函数:看一下以下一个sql中包含了多个常用的分析函数,图中需要注意的地方我已经圈出来并且标明了:
常用的分析函数还有lag、lead、percent_rank、PERCENTILE_COUNT等,大家可以自己回去研究一下。
3.First、last返回通过dense_rank排序后的第一个或者最后一个。例如我想查询员工的最小工资最小的部门和员工的最大工资最大的部门:
4.Windows子句,用来指明分析函数的计算窗口,语法如下:
窗口的划分方式有range和rows两种,Rows 表示物理偏移量,range表示逻辑偏移量。用rows 或range划分窗口,按照起点在上,终点在下的原则(如果违反这个原则,则分析函数的计算结果为null),对窗口中的每一行应用分析函数计算结果。如果我想取:当前sal-500到当前sal为一个窗口,并按照窗口来计算工资总和,可以用如下sal来实现:
5.分析函数与group by结合,进行topN查询,例如我想查询总工资前三名的部门,如下:
8.5使用场景
逻辑比较复杂的查询,往往需要用到分析函数。
9rownum
9.1学习目标
理解oracle内部rownum的原理,会使用rownum进行top-N查询和其他范围查询。
9.2要点
1.rownum 和where 在同一层查询中,where 条件之后使用rownum 比较,只能使用 =, ,!=, >,不能使用>,>=(>=1是可以的,和不加效果一样),=(使用=,只能是where rownum=1才可以)。否则不返回任何数据。如果使用!=或 >,那么只是返回前n-1行,其他按照rownum工作原理推算。
2.当rownum 和order by 在一个语句级别中(同一层)使用的时候.看这个查询的数据是否从索引中获取(或者根据索引先得到rowid然后定位行)的,如果不是,那么就是先查询出来,每行标上rownum,然后order by 将结果重新排序,那么rownum的顺序是乱的。如果排序的数据是从索引中查询的,这样结果有序。这取决于执行计划,执行计划又和oracle优化器相关。
3.在执行语句时,有关rownum执行的顺序是这样的:
1)执行查询操作,初始化rownum值为1。
2)指针指向第一行,将该行的rownum标记为1。
3)进行where条件匹配,如果where条件返回false,则抛弃行,返回true,则返回该行,并且将rownum值自增1。
4)Oracle获取下一行,将该行的rownum标记为当前rownum值。
5)返回第三步。
9.3语法
Rownum可以用在where条件中,如:
Select * from emp where rownum 5;
9.4使用案例
1.Top-N查询:
2.查询中间几行:
看一下oracle执行的原理,当指针移动到第一行的时候,rownum=1,rownum between 3 and 5返回false,第一行被抛弃,指针指向第二行,此时rownum还是为1,第二行也被抛弃,以此类推,无结果返回。这种情况可以使用子查询,先把rownum最为rn字段缓存到结果集里面,然后对结果集进行筛选:
3.上述查询其实存在隐患,不知道大家注意没有?子查询中select rownum rn,empno from emp order by empno,oracle的执行顺序是先取到结果集,标记上rownum,然后进行排序,这样rownum的序号不一定是排序后的序号,所以取到的数据可能不是我想要的。那此处为什么我能取到正确的数据呢?这取决与执行计划,在emp表中,empno作为表的主键,也就是唯一索引,在取得子查询结果集得时候,oracle是根据索引读取数据的,而索引一般是在oracle的内存中,并且索引是有序的,优化器选择索引的方式访问emp表,所以oracle读取数据的同时为当前行标记上rownum,所以rownum顺序不会错乱。如果我是通过ename排序取3-8行,emp在ename上并没有建立索引,所以读取的数据时错乱的,如下:
此时再用外层查询取得rn between 3 and 8,就会取得错误的数据。
此时能够保证数据是正确的。有关案例2的order by和rownum要慎用,因为即使在相关字段上有索引,oracle的优化器也不一定会选择索引访问数据,这根表的状态和其他很多原因都有关系,有关索引和执行计划的相关知识,这里不做讲解,将会在以后的课程中放在oracle优化的科目中进行讲解。
9.5使用场景
在进行top-N查询或者取中间数据时可能用到。
10rowid
10.1学习目标
了解rowid的组成部分,会使用rowid进行删除重复行等查询。
10.2要点
1.rowid的是基于64位编码的18个字符,由数据对象编号+文件编号+块编号+行编号组成(数据对象编号(6) +文件编号(3) +块编号(6)+行编号(3)=18位)。
10.3语法
10.4使用案例
1.Rowid经常用于删除重复行,如我用如下语句加入escore2两条重复数据,如下:
insert into escore2 select * from escore2 where sid=1;
commit;
很显然,圈出的数据为重复数据,如下我可以用rowid来删除重复数据:
delete from escore2 where rowid not in(
select min(rowid) from escore2 group by sid ,type,score
);
commit;
再来看一下escore2表,重复数据没有了:
2.分页,例如我想取escore2表的第4-6条数据,也就是上图4、5、6行,如下:
10.5使用场景
Rowid可用于删除重复数据或者分页,还可以用于其他的需要唯一标识行的sql。
11Dade的使用
11.1学习目标
掌握date数据类型,会使用date类型,并且掌握date类型的常用函数。
11.2要点
1.一些常用的数据格式要牢记,他们就像date对象的属性,当你要访问date对象的相应属性时,需要将这个属性作为参数传入,属性对应的值才能被返回,如:
1)Y或YY或YYY 年的最后一位,两位或三位
2)Q 季度
3)MM 月份
4)Month 用9个字符长度表示的月份名
5)WW 当年第几周
6)W 本月第几周
7)DDD 当年第几天
8)DD 当月第几天
9)D 周内第几天
10)DY 中文的星期几
11)HH或HH12 12进制小时数 HH24 24小时制
例如今天是2011年7月18日,星期一,执行如下sql看一下结果:
2.一些常见函数的用法:
1)对于to_date和to_char函数大家应该很熟悉了,这应该是oracle里面最常用的函数了,如下:
需要强调一点的是,oracle有默认的显示格式,对于这个格式的字符串,oracle是可以识别的,并且能通过隐式转换将其转换为date类型,如下sql(在命令行执行):
由以上结果的输出可以看出我当前数据库的时间匹配格式是18-JUL-11的,那oracle可以接收这种类型的字符串将其隐式转换为date类型,如下sql:
如下我修改了当前session的默认时间格式,则执行不报错,但是只在当前session有效:
2)Last_day(mydate),此函数返回mydate所在月份的最后一天。
3)Add_month(mydate,n),返回mydate推后n个月后的日期。
4)Months_between(date1,date2),返回date1与date2间隔的月数。
5)Next_day(mydate,dayofweek),返回自mydate日期起,下一个dayofweek(星期几)的日期。
6)Trunc(mydate,格式字符串),返回对mydate截断到指定位置后的日期。Round(mydate,格式字符串),返回对mydate四舍五入到指定位置的字符串,如下sql:
11.3使用场景
对于日期的计算需要用到日期函数,如:
1)上个月末:trunc(sysdate,'mm')-1
2)本月最后一秒:trunc(last_day(sysdate)+1,'dd')-1/24/60/60
3)本月的天数:trunc(last_day(sysdate)+1)-trunc(sysdate,'mm')
12字符串函数的使用
12.1学习目标
掌握常用的字符串函数,能够用字符串函数解决相关问题。
12.2要点
1.ascii(char):返回字符串首字符串的ASCII码值。Chr(n):返回ASCII码值n对应的字符。如下:
2.concat(str1,str2,…),返回str1,str2,……连接后的字符串。
3.initcap(str),返回每个单词首字母大写的字符串。
4.instr(char1,char2[,n[,m]]):用于取得子串在字符串中的位置,其中数字n为起始搜索位置,数字m为子串出现次数。如果数字n为负数,则从尾部开始搜索。数字m必须为正整数,并且n和m的默认值为1。
5.length(char):返回字符串的长度。如果字符串的类型为char,则其长度包括所有的后缀空格;如果char是null,则返回null。
6.lower(char):用于将字符串转换为小写格式;upper(char):将字符串转换为大写格式。
7.lpad(char1,n,char2):用于在字符串char1的左端填充字符串char2,直至字符串总长度为n,char2的默认值为空格。如果char1长度大于n,则该函数返回char1左端的n个字符;rpad(char1,n,char2)用于在字符串char1的右端填充字符串char2,直至字符串总长度为n,char2的默认值为空格。如果char1长度大于n,则该函数返回char1左端的n个字符。
8.trim(char from string)用于从字符串的头部、尾部或两端截取特定字符;ltrim(char1[,set]):用于去掉字符串char1左端所包含的set中的任何字符。Oracle从左端第一个字符开始扫描,逐一去掉在set中出现的字符,当遇到不是set中出现的字符时终止,然后返回剩余结果;rtrim(char1[,set]):用于去掉字符串char1右端所包含的set中的任何字符。Oracle从右端第一个字符开始扫描,逐一去掉在set中出现的字符,当遇到不是set中出现的字符时终止,然后返回剩余结果。
9.replace(char,search_string[,replacement_string]):用于将字符串的子串替换为其他子串。如果search_string为null,则返回原有字符串;如果replacement_string为null,则会去掉指定子串。