ITPub博客

首页 > 数据库 > Oracle > SQL函数

SQL函数

原创 Oracle 作者:llnnmc 时间:2017-08-11 09:55:07 1 删除 编辑

SQL函数分单行函数、多行函数(或叫组函数)。

一、字符函数

lower 转小写

upper 转大写

initcap 首字母大写,其余小写,以单词为单位

initcap('we-are-chinese') We Are Chinese

concat 两个字符串的连接, 多字串时可嵌套调用或直接用“||”

length 计算字符串长度,无论单、双字节字符或数字

length('12345') 5

length('中国人') 3

length(123.45) 6

lpad 格式化字符串,左填充(字串,宽度,填充符),填充符默认为空格填充,字串宽度已经超出指定宽度时变为左截取,截取到指定宽度

lpad('12345',10, '0') 0000012345

lpad('12345',10) ' 12345'

lpad('12345',4,'0') 1234

lpad('12345',4) 1234

rpad 右填充,字串宽度已经超出指定宽度时变为左截取,截取到指定宽度

rpad('12345',10, '0') 1234500000

rpad('12345',4,'0') 1234

rpad('12345',4) 1234

该函数可以隐士转换,如果不是字符串

select lpad(sal,10,'*') from emp where empno=7934;

ltrim 删除左侧空格

rtrim 删除右侧空格

trim 删除左右两侧空格

trim('*' from '***hello***') 删除头尾字符,或trim(both '*' from '***hello***') hello

trim (leading '*' from '***hello***') 删除头部字符 hello***

trim(trailing '*' from '***hello***') 删除尾部字符 ***hello

trim中只能指定单个要删除的字符,不能是字符串

instr 获取字符串出现的位置,从指定位置开始,出现的第几次,最后两个参数默认为1,找不到时返回0

instr('HelloWorld','W') 6

instr('HelloWorld','W',1) 6

instr('HelloWorld','W',1,2) 0

substr 截取字符串,起始位置为1,为负时从反向位置向右截取

substr('HelloWorld', 6) World

substr('HelloWorld',1,5) Hello

substr('HelloWorld',-5,5) World

replace 字符串替换,没有替换串时用空字符替换,也就是删除查找串,未找到被替换串时原样返回

replace('jack and jue','j','bl') black and blue

replace('a#b#c','#') abc

replace函数也可以处理数字和日期数据,如

select replace(10000-3,'9','85') from dual; 8585857

select replace(sysdate, 'NOV','DEC') from dual; 25-DEC-16

translate 字符串翻译

translate('+-*/','1+2-3*4/','fajbocld') abcd

常用于去掉字串中的字母或数字

select translate('12fge3k4mab5z','#abcdefghijklmnopqrstuvwxyz',' ') from dual 12345

translate('12ab3c4de5f','#1234567890',' ') abcdef

其中单引号中为空格,不能为空,否则有NULL值做参数的表达式将直接返回NULL,

#号用于剔除跟第一个字符a或1符合的字符的翻译,否则翻译结果会多个空格。

reverse 反转字符串,一般只用于反转单字节字符,多字节字符是乱码

reverse('1234') 4321

wm_concat 字段合并

create table t(a number, b varchar2(20));

insert into t values(1, 'a');

insert into t values(2, 'c');

insert into t values(3, 'b');

insert into t values(2, 'a');

insert into t values(1, 'd');

insert into t values(3, 'e');

col merge for a20

select a, wm_concat(b) merge from t group by a;

A MERGE

---------- --------------------

1 a,d

2 c,a

3 b,e

select a, replace(wm_concat(b), ',', '|') merge from t group by a;

A MERGE

---------- --------------------

1 a|d

2 c|a

3 b|e

regexp_substr 字段拆分

select regexp_substr('a;b;c;d', '[^;]+', 1, level), level from dual connect by level < 5;

REGEXP_SUBSTR( LEVEL

-------------- ----------

a 1

b 2

c 3

d 4

二、数值函数

round 四舍五入

round(1601.916,1) 1601.9

round(1601.916,2) 1601.92

round(1601.916,-3) 2000

round(1601.916) 1602

trunc 截断,不四舍五入,小数部分按指定位数截断,整数部分的截断不改变整数位数

trunc(1601.916,1) 1601.9

trunc(1601.916,2) 1601.91

trunc(1601.916,-3) 1000

trunc(160,-1) 160

trunc(1601.916) 1601

mod 模运算,即取余数,mod(被除数,除数),常用于区分奇数和偶数,除数可以为0

mod(5,2) 1

mod(5,0) 5

mod(3,5) 3

mod(5.2,2) 1.2

ceil 向上取整,取大值整数

ceil(23.45) 24

ceil(-23.45) -23

floor 向下取整,取小值整数

floor(23.45) 23

floor(-23.45) -24

sign 取正负性

sign(-10) -1

sign(10) 1

sign(0) 0

abs 取绝对值

sqrt 求平方根,参数不能为负

power 乘方运算,power(底数,指数)

greatest 求多个值中的最大值

least 求多个值中的最小值

三、日期函数

YY格式

与系统日期处于同一个世纪

RR格式

接近系统日期的世纪

默认是RR格式

DD-MM-RR

nls参数的设置:国家语言支持

alter session set nls_language=english;

修改会话日期时间格式显示:

alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';

alter session set nls_date_format='yyyy-mm-dd hh:mi:ss am';

sysdate 系统时间

sessiontimezone 当前会话时区

current_date 当前会话时区的当前时间

systimestamp 系统时间戳

current_timestamp 当前会话时区的当前时间戳

日期的加减计算

一个日期加一个数字表示增加天数后的新日期

两个日期相减表示相差的天数

有两个日期数据START_DATE,END_DATE,欲得到这两个日期的时间差(以天,小时,分钟,秒,毫秒):?

天:?

ROUND(TO_NUMBER(END_DATE - START_DATE))?

小时:?

ROUND(TO_NUMBER(END_DATE - START_DATE) * 24)?

分钟:?

ROUND(TO_NUMBER(END_DATE - START_DATE) * 24 * 60)?

秒:?

ROUND(TO_NUMBER(END_DATE - START_DATE) * 24 * 60 * 60)?

毫秒:?

ROUND(TO_NUMBER(END_DATE - START_DATE) * 24 * 60 * 60 * 60)

months_between 两个日期相差的月份数,离现在近的日期写在前面

add_months 加几个月后的日期,数字为负时反向推算

当日期为最后一天时,返回下一个月的最后一天,超出月份的最后一天时也返回最后一天

select add_months(to_date('2013-11-30','yyyy-mm-dd'), 1) from dual; 返回2013-12-31 00:00:00

select add_months(to_date('2013-1-31','yyyy-mm-dd'), 1) from dual; 返回2013-02-28 00:00:00

select add_months(to_date('2013-1-30','yyyy-mm-dd'), 1) from dual; 返回2013-02-28 00:00:00

函数中日期会隐式转换

select add_months('2013-1-30', 1) from dual; 返回2013-02-28 00:00:00

next_day 下个星期的那个日期,从星期日开始为1

select next_day(sysdate,2) from dual; 返回下个星期一的日期

last_day 指定日期所在月的最后一天

select last_day(to_date('2012-2-11','yyyy-mm-dd')) from dual; 返回2012-02-29 00:00:00

函数中日期会隐式转换

select last_day('2012-2-11') from dual; 返回2012-02-29 00:00:00

返回下个月的第一个星期一

select next_day(last_day(sysdate),'mon') from dual;

日期的四舍五入和截断

round 按年yy、月mm、日dd、时hh、分mi

select round(to_date('2013-11-22','yyyy-mm-dd'),'mm') from dual; 舍入到月 2013-12-01 00:00:00

select round(to_date('2013-11-12','yyyy-mm-dd'),'mm') from dual; 舍入到月 2013-11-01 00:00:00

select round(to_date('2013-11-12 21:29:35','yyyy-mm-dd hh24:mi:ss'),'dd') from dual; 舍入到日 2013-11-13 00:00:00

trunc 按年、月、日截断

select trunc(to_date('2013-11-12 21:29:35','yyyy-mm-dd hh24:mi:ss'),'dd') from dual; 截断到日 2013-11-12 00:00:00

extract 提取日期中的某个域,extract(域名 from 日期)

extract(month from sysdate) 11

只能提取年、月、日,不能从日期型中提取小时、分钟、秒

可提取到零时区的时间域extract(hour from systimestamp),实际结果还要加上时区sessiontimezone,北京时间为东八区,即要+8

四、转换函数和格式串

chr 将ASCII码转换为字符,与ascii互为反函数

to_char 将数字格式化为字符串,to_char(原数值,格式串,NLS参数)

0 有数字填充数字,没有强制填充0

9 整数部分有数字填充数字,没有不填充,小数部分没有填充0

. 小数点的位置

D 小数分隔符的位置,默认为句点(D和G配合使用,不能D和,或者.和G混合使用)

, 逗号千分符的位置

G 组分隔符的位置,默认为逗号

FM 屏蔽掉没有必要的空格和0

$ 显示美元符号

L 显示系统环境的本地货币符号,如人民币符号“¥”

C 显示系统环境的本地货币种类符号,如中国元“CNY”,“C”不能与“L”或“$”并用

X 转换为十六进制显示,用大写字母,x表示用小写字母,如to_char(255,'XXX')返回FF

MI 表示负数的减号的位置

PR 包围在括号内的负数

EEEE 科学计数法

V 乘以10的n次方,n是V之后9的数量

S 前面加上+ 或-

to_number 将字符串格式化为数字,to_number(字符串,格式串,NLS参数)

掩码格式串类似to_char函数

to_number('$1,000.55', '$999,999.00') 1000.55

进制转换

to_number('ff', 'xxx') 255

to_char 将日期格式格式化为字符串,to_char(日期,格式串,NLS参数)

YEAR、Year、year 区分大小写的年份全拼

yyyy 四位年

yy 两位年

RR 两位已知世纪年

q 季度

mm 两位月份

MONTH、Month、month 区分大小写的月份全拼

MON、Mon、mon 区分大小写的三字母月份缩写

ww 一年中的第几周

w 一月中的第几周

d 一周中的第几天,周日为一周中的第一天

dd 一月中的第几天

ddd 一年中的第几天

DAY、Day、day 区分大小写的星期全拼

DY、Dy、dy 区分大小写的三字母星期缩写

th 后面带上th表示第几天

sp 第几天的英文全拼

AM、PM、A.M.、P.M. 指示上下午

hh、hh12 12时制小时

hh24 24时制小时

mi 分钟

ss 秒

sssss 午夜之后的秒

ff 毫秒

以下是两个日期表达的例子

当天日期的全拼表示

select to_char(sysdate, 'fmDdthsp "of" Month, Year') from dual;

TO_CHAR(SYSDATE,'FMDDTHSP"OF"MONTH,YEAR')

--------------------------------------------------------------------

Seventh of 9月, Twenty Seventeen

下个月的第一个星期一

select to_char(next_day(last_day(sysdate), 2), 'dd "is the first Monday for" fmmonth rrrr') from dual;

TO_CHAR(NEXT_DAY(LAST_DAY(SYSDATE),2),

--------------------------------------

02 is the first Monday for 10月 2017

显示NLS会话参数的视图:nls_session_parameters

show parameter nls_territory;

修改地区

alter session set nls_territory=america;

修改日期语言

alter session set nls_date_language=american;

alter session set nls_date_language='simplified chinese';

语句级别的NLS控制

select to_char(sysdate, 'mm-dd-yyyy hh:mi:ss am', 'nls_date_language = american') from dual;

select to_char(sysdate, 'mm-dd-yyyy hh:mi:ss am', 'nls_date_language = japanese') from dual;

select to_char(sysdate, 'mm-dd-yyyy hh:mi:ss am', 'nls_date_language = ''simplified chinese''') from dual;

注意第三行语句中需要追加两个单引号

to_date 将字符串格式化为日期,to_date(字符串,格式串,NLS参数)

掩码格式串类似to_char函数

fx 类似于to_char函数使用的fm修饰符,指定该修饰符时,不完全匹配格式掩码的字符项会产生错误。

应避免数据类型的隐式转换,出现隐式转换会不使用索引

强制数据类型转换

cast(原数据 as 新的数据类型)

利用原表重建一个新表,并更改列的数据类型

create table salary2 as

select cast(s.salary_id as varchar2(20)) salary_id,

cast(employee_id as varchar2(20)) employee_id,

cast(salary as varchar2(20)) salary

from salary s;

五、条件函数

nvl(original, ifnull),判断原值original是否为空,为空返回ifnull的值,不为空原样返回

ifnull数据类型应与original一致,否则要求能向original转换,函数返回类型与original一致

如

select nvl(1, 'a') from dual; 错误

select nvl('a', 1) from dual; 正确

另外注意该函数的合理使用,如下查询不能返回'00000'

select nvl(dummy, '00000') from dual where 1=2;

改为如下形式则能返回'00000'

select nvl(max(dummy), '00000') from dual where 1=2;

nvl2(original, ifnotnull, ifnull) 不为空返回ifnotnull的值,为空返回ifnull的值

ifnull数据类型应与ifnotnull一致,否则要向ifnotnull转换,不能是long类型,函数返回类型与ifnotnull一致

nvl和nvl2的返回位置概念是反的

nullif(expr1, expr2) 相等返回空,否则返回第一个表达式值

coalesce(expr1, expr2, ...) 返回第一个非空的表达式,否则返回空值

所有非空参数的数据类型必须与第一个非空参数的数据类型一致

decode函数

decode(expr, 值1, 结果1,

值2, 结果2,

...

否则结果)

decode函数认为两个空值是相等的

后面各个值的数据类型应当与值1的数据类型一致,否则要求能向值1转换

函数返回的数据类型转换到与结果1一致

如

select decode(sysdate, null, 1, 'a') from dual; 错误

select decode(sysdate, null, 'a', 1) from dual; 正确

函数也可以只包含三个参数,当不满足值1时返回空的结果

如以下查询如果日期不符合将返回空

select decode(to_char(sysdate, 'yyyy-mm-dd'), '2017-08-15', 'b') from dual;

case语句

case expr when 条件1 then 结果1

when 条件2 then 结果2

else 否则结果

end

参数的数据类型必须一致

六、分组函数(聚合函数)

avg 分组求平均值

sum 分组求和

min 分组最小值

max 分组最大值

count 分组计数

count(*)、count(1) 未指定列,返回记录数量包含重复项和空值

count(列名) 指定了列,返回记录数量包含重复项,但排除空值

count(distinct 列名) 返回记录数量不包含重复项和空值

组函数的计算忽略空值

group by 分组显示

查询中包含正常列和分组函数的列时,需要对正常列使用group by子句,否则报错。

group by的表达式内容必须与select中的表达式保持一致,如下表达不一致是错误的

select to_char(hiredate, 'rr'), avg(sal) from emp group by to_char(hiredate, 'yyyy');

并且group by的表达式不可以用列的别名,如下是错误的

select to_char(hiredate, 'rr') year, avg(sal) from emp group by year;

嵌套分组函数需要group by子句,如以下是错误的

select max(count(*)) from emp;

但加入group by后可以执行,虽然这里的嵌套分组并没有意义

select max(count(*)) from emp group by 1;

group by支持多分组,以下是两种多分组模式rollup和cube

rollup(a, b, c)的分组模式为(a,b,c),(a,b),(a),(全表)

select department_id, job_id, sum(salary)

from employees

group by rollup(department_id, job_id);

cube(a, b, c)的分组模式为(a,b,c),(a,b),(a,c),(b,c),(a),(b),(c),(全表)

select department_id, job_id, sum(salary)

from employees

group by cube(department_id, job_id);

having 分组后的筛选

筛选条件不一定需要存在于select的列表达式中,如以下查询是可以的

select deptno from emp where comm is null group by deptno having count(*)>2;

组函数不能用于where子句中,如果要用,必需放在having子句中。但组函数可以在where子句的子查询中构建。

七、SQL函数的几个练习

以下将日期“19-Mar-2001”表示为“Nineteenth of March 2001 12:00:00 AM”的形式

alter session set nls_date_language=american;

alter session set nls_date_format='DD-Mon-YYYY';

select to_char(to_date('19-Mar-2001', 'DD-Mon-YYYY'), 'fmDdspth "of" Month YYYY fmHH:MI:SS AM') new_date from dual;

或

select to_char(to_date('19-Mar-2001', 'DD-Mon-YYYY'), 'fmDdthsp "of" Month YYYY fmHH:MI:SS AM') new_date from dual;

以下将日期“11-Mar-2007”表示为“Eleventh of October, Two Thousand Seven”的形式:

select to_char(to_date('11-oct-2007', 'DD-Mon-YYYY'), 'fmDdthsp "of" Month, Year') new_date from dual;

此处如果没有sp:

select to_char(to_date('11-oct-2007', 'DD-Mon-YYYY'), 'fmDdth "of" Month, Year') new_date from dual;

则查询结果为:

11th of October, Two Thousand Seven

查询hr用户的employees表

显示干了多少年零多少个月

LAST_NAME YEARS MONTHS 按年和月降序

select last_name,

trunc(months_between(sysdate, hire_date) / 12) years,

trunc(mod(months_between(sysdate, hire_date), 12)) month

from employees

order by years desc, months desc;

查询scott用户下的emp表

显示总人数和入职日期为以下各年的人数

total 1980 1981 1982 1987

select count(*) total,

sum(decode(to_char(hiredate, 'yyyy'), '1980', 1, 0)) "1980",

sum(decode(to_char(hiredate, 'yyyy'), '1981', 1, 0)) "1981",

sum(decode(to_char(hiredate, 'yyyy'), '1982', 1, 0)) "1982",

sum(decode(to_char(hiredate, 'yyyy'), '1987', 1, 0)) "1987"

from emp;

将一列的查询分开在两列里显示

select a.id, b.id from t1 a, t1 b where a.id = b.id - 5;

select a.id, b.id from t1 a, t1 b where a.id + (select count(*) from t1) / 2 = b.id;

select a.id, b.id

from t1 a, t1 b

where a.id = b.id(+) - round((select count(*) from t1) / 2)

and a.id <= round((select count(*) from t1) / 2);

查员工工资在其所在部门平均工资之上的员工,列出其所在部门及该部门的平均工资

select a.last_name, a.salary, a.department_id, round(b.salavg, 2)

from employees a,

(select avg(t1.salary) salavg, t2.department_id depid

from employees t1, departments t2

where t1.department_id = t2.department_id

group by t2.department_id) b

where a.department_id = b.depid

and a.salary > b.salavg;

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/28974745/viewspace-2143372/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: Oracle序列
请登录后发表评论 登录
全部评论
刘鲁宁的个人博客。

注册时间:2016-12-29

  • 博文量
    113
  • 访问量
    287700