一、常见函数
1、字符连接函数:concat
select concat('0371-','67255555')|| '转856' 电话号码 from dual;
字符串连接另一种方法,使用 || 字符串连接符
2、首字符大写:initcap
select initcap('micro SOFT') as name from dual;
(参数无论是什么样字母组成,都将第一个字母大写,其余小写)
3、字符串查找:instr
select instr('410106199012132018','19901213',1,1) instring from dual;
参数1:被查找的字符串,
参数2:要查找的字符串
参数3:查找的起始位置
参数4:第几次出现
4、字符串大小写:initcap(首字符大写),upper(全部大写),lower(全部小写)
select initcap(ename),upper(ename),lower(ename),eanme from emp;
5、字符补充函数 lpad(左补充), rpad(右补充)
select rpad('gao',10,'#') from dual;
select lpad(rpad('gao',10,'#'),15,'*') from dual;
参数1:原字符串
参数2:补充后达到的个数
参数3:补充的字符
6、提取子字符串:substr
select substr(‘13012345678’,3,8) from dual;
--从第三个字符开始,提取8个字符
7、字符串替换:replace
select replace('java是世界上最好的语言!','java','php') from dual;
8、字符去除空格 :trim
--删除tech两端的字符串 :默认删除两边的空格
select trim(' tech ') from dual;
也可以这样 : 删除两边的指定字符
select trim('-' from '-------东方不败------') from dual;
删除 000123头部的0字符 : 删除字符串头部的指定字符
select trim(leading '0' from '000123') from dual;
删除Teach尾部的1字符 : 删除字符串尾部的指定字符
select trim(trailing '1' from 'Teach111') from dual;
删除123Teach111两端的字符 : 删除字符串两端的指定字符
select trim(both '1' from '123Teach1111') from dual;
9、数学函数
Ceil返回大于或等于给出数字的最小整数
select ceil(3.1415927) from dual;
Floor返回小于或等于给定数字的最大值
select floor(3.1415927) from dual;
Round函数进行四舍五入,trunc函数进行截取。
第二个参数为正时,表示从小数点向后计算。
第二个参数为负时,表示从小数点向前计算。
select round(124.1666,-2),round(124.1666,2) from dual; -- 100 ,124.17
select trunc(124.1666,-2) , trunc(124.16666,2) from dual; --100 ,124.16
10、日期函数
--sysdate显示当前日期
select sysdate from dual;
--日期格式化,day表示当前星期几
select to_char(sysdate,’yyyy-mm-dd day’) from dual;
trunc(date,fmt)按照给出的要求将日期截断,如果fmt=‘mi’表示保留分,截断秒,就是截断分后边要显示的内容数据,
--trunc(date,fmt) fmt表示截取的内容,就是保留的内容,其余的为默认值(2021.07.26 04:00:00)
select to_char(trunc(sysdate,'hh'),'yyyy.mm.dd hh:mi:ss') from dual; --阶段时
addMonths 增加或减去月份
select add_months(sysdate,2) from dual;
select to_char( add_months(sysdate,2),'yyyy-mm') from dual;
select to_char( add_months( to_date('1999-12','yyyy-mm'),2), 'yyyy-mm') from dual;
Months_between 显示日期相差的月数
select months_between('1-1月-2022','26-7月-2021') 相差月份 from dual;
select months_between ( to_date('2021.05.20','yyyy.mm.dd'), to_date('2005.05.20','yyyy.mm.dd') ) 相差月份 from dual;
总结:得到结果,取绝对值,去小数
select floor(ABS(months_between('1-1月-2022','26-7月-2021'))) 相差月份 from dual;
11、其他函数
-- 返回当前用户的唯一标识
select UID from dual;
-- 返回当前用户的用户名
select user from dual;
-- NVL(expr1, expr2)
expr1不为空的时候值未expr1,为空时值为expr2
--NVL2 (expr1, expr2, xpr3)
expr1不为NULL,返回expr2;为NULL,返回expr3
--NULLIF (expr1, expr2)
expr1和expr2相等返回NULL,不等返回expr1
max(x):求最大值
min(x):求最小值
count(x):求总数
sum(x):求和
avg(x):求平均值
二、PL/SQL
1、PL/SQL块
所有的PL/SQL程序都以块作为基本单位
块中包含过程化语句和SQL的DML语句,这些块可以按照顺序出现,也可以相互嵌套
匿名块:
匿名块是出现在应用程序中的没有名字且不存储到数据库中的块
匿名块出现在SQL语句可以出现的地方,它们可以调用其他程序,却不能被其他程序调用
命名块:
命名块是一种带有标签的匿名块,标签为块指定了一个名称
子程序:
子程序是存储在数据库中的过程(procedure),函数(function)生成之后可以被多次执行
程序包:
程序包是存储在数据库中的一组程序,变量定义
程序包中的子程序可以被其他程序或者子程序调用
触发器:
触发器是一种存储在数据库中的命名块,生成之后可以被多次执行
在相应的触发事件发生之前或之后就会被执行一次或多次
2、PL/SQL程序结构
定义部分
用于定义常量,变量,游标,异常和复杂数据类型
执行部分
用于实现应用模块功能,该部分包含需要执行的PL/SQL语句和SQL语句
异常处理部分
用于处理执行部分可能出现的运行错误
DECLARE
定义部分
BEGIN
执行部分
EXCEPTION
异常处理部分
END;
~~~~~~~~~~~~~~~~~~~~~~~~
DECLARE
v_ename varchar2(50);
BEGIN
select ename into v_ename from emp where empno=&eno;
dbms_output.put_line('您要查找的姓名是:'|| v_ename);
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('输入的员工编号不存在!');
END;
3、常量与变量
constant:常量声明专用名词
:=:冒号+等号为赋值符号
dbms_output.put_line('需要输出的内容'||'+拼接的内容!!!')
~~~~~~~~~~~~~~~~~~~
declare
v_pi constant number(6,5):=3.14; --定义圆周率常量
v_r number(1):=2;
v_area number(6,2); --定义保存圆面积的变量
begin
v_area:=v_pi*v_r*v_r;
dbms_output.put_line('半径:'||v_r); --输出半径值
dbms_output.put_line('面积:'||v_area); --输出圆的面积
end;
4、数据类型
char:固定长度字符串,长度不够时使用空格来补充,最多存储2000字节
varchar2:可变长字符串,最多可以存储4000字节
number:可以存储正数,负数,零,定点数和精度为38的浮点数,number(m,n)m为数字的总长度,n为小数点右边的位数
date:存储表中的日期和时间数据,长度为7,分别是世纪,年,月,日,时,分,秒
timestamp:存储日期的年、月、日、小时、分和秒值。其中,秒值精确到小数点后6位数,该数据类型同时包含时区信息。
clob:存储长文本信息,最多可存储4GB
blob:存储二进制对象,图像,视频和音频,最多可存储4GB
a b%type ==>表示声明一个变量a,其数据类型和b相同
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
type emp_record_type is RECORD(--定义一个记录类型,包含员工信息
ename emp.ename%type,
sal emp.sal%type,
comm emp.comm%type,
total_sal sal%type
);
v_emp_record emp_record_type;--声明记录类型变量
==>表示声明一个记录类型emp_record_type,里边包含了一张表的数据内容类型
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
declare
type emp_record_type is RECORD(
ename emp.ename%type,
sal emp.sal%type,
comm emp.comm%type,
total_sal sal%type
);
v_emp_record emp_record_type;
begin
select ename,sal,nvl(comm,0),sal+nvl(comm,0) into v_emp_record
from emp where empno=7369;
dbms_output.put_line('员工姓名:'|| v_emp_record.ename);
dbms_output.put_line('基本工资:'|| v_emp_record.sal);
dbms_output.put_line('奖金:'|| v_emp_record.comm);
dbms_output.put_line('实发工资:'|| v_emp_record.total_sal);
end;
type dept_table_type is table of dept%rowtype index by binary_integer;
v_dept_table dept_table_type;
==>table数据类型,使一张表的一行数据类型赋给一个变量
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
declare
type dept_table_type is table of dept%rowtype
index by binary_integer;
v_dept_table dept_table_type;
begin
select * into v_dept_table(0) from dept where deptno=10;
select * into v_dept_table(1) from dept where deptno=20;
dbms_output.PUT_LINE('编号:'||v_dept_table(0).deptno||' 名称:'
||v_dept_table(0).dname||' 所在地:'||v_dept_table(0).loc);
dbms_output.PUT_LINE('编号:'||v_dept_table(1).deptno||' 名称:'
||v_dept_table(1).dname||' 所在地:'||v_dept_table(1).loc);
end;
5、流程控制
IF条件控制
条件控制1:
if 条件1 then
语句段1
elsif 条件2 then
语句段2
elsif 条件3 then
语句段3
......
elsif 条件n
end id;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
输入员工编号,如果该员工
原来没有奖金,则按照工资的10%发放
原来有奖金但不超过1000的,补到1000;
其余的按照原来奖金基础再加上10%发放;
declare
v_emp emp%rowtype;
begin
v_emp.empno:=&no;
select * into v_emp from emp where empno=v_emp.empno;
dbms_output.PUT_LINE('更新前的奖金'||nvl(v_emp.comm,0));
if v_emp.comm is null then
update emp set comm=v_emp.sal*0.1 where empno=v_emp.empno;
elsIf v_emp.comm<1000 then
update emp set comm=1000 where empno=v_emp.empno;
else
update emp set comm=comm+comm*0.1 where empno=v_emp.empno;
end if;
end;
CASE条件控制
条件控制2
CASE 表达式
WHEN 条件表达式结果1 THEN
语句段1;
WHEN 条件表达式结果2 THEN
语句段2;
......
ELSE
语句段n;
END CASE;
~~~~~~~~~~~~~~~~~~~~~~
根据部门编号输出部门所在地
10 纽约
20 达拉斯
30 芝加哥
40 波士顿
declare
v_deptno dept.deptno%type:=&deptno;
begin
case v_deptno
when 10 then dbms_output.put_line('部门所在地:纽约');
when 20 then dbms_output.put_line('部门所在地:达拉斯');
when 30 then dbms_output.put_line('部门所在地:芝加哥');
when 40 then dbms_output.put_line('部门所在地:波士顿');
else dbms_output.put_line('不存在该部门');
end case;
end;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
根据员工编号输出员工工资级别
sal<2000 A级工资
sal>=2000 and sal<3000 B级工资
其余 C级工资
declare
v_sal emp.SAL%type;
begin
select sal into v_sal from emp where empno=&empno;
case
when v_sal<2000 then dbms_output.put_line('A级工资');
when v_sal>=2000 and v_sal<3000 then
dbms_output.put_line('B级工资');
else dbms_output.put_line('C级工资');
end case;
exception
when no_data_found then
dbms_output.put_line('员工编号不存在');
end;
LOOP循环控制
循环控制1
LOOP
语句段;
EXIT [WHEN 条件表达式]
END LOOP;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
declare
type dept_table_type is table of dept%rowtype
index by binary_integer;
i number(1):=0;
v_dept_table dept_table_type;
begin
v_dept_table(0).deptno:='50';
v_dept_table(0).dname:='研发部';
v_dept_table(0).loc:='北京';
v_dept_table(1).deptno:='60';
v_dept_table(1).dname:='开发部';
v_dept_table(1).loc:='上海';
v_dept_table(2).deptno:='70';
v_dept_table(2).dname:='推广部';
v_dept_table(2).loc:='北京';
loop
if i>2 then exit; end if;
insert into dept values
( v_dept_table(i).deptno,v_dept_table(i).dname,v_dept_table(i).loc);
i:=i+1;
end loop;
end;
WHILE循环控制
循环控制2
WHILE 条件表达式 LOOP
语句段;
END LOOP;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
declare
type dept_table_type is table of dept%rowtype
index by binary_integer;
i number(1):=0;
v_dept_table dept_table_type;
begin
v_dept_table(0).deptno:='50';
v_dept_table(0).dname:='研发部';
v_dept_table(0).loc:='北京';
v_dept_table(1).deptno:='60';
v_dept_table(1).dname:='开发部';
......
while i<=2 loop
insert into dept values(
v_dept_table(i).deptno,v_dept_table(i).dname,v_dept_table(i).loc);
i:=i+1;
end loop;
end;
FOR循环控制
循环控制3
FOR 循环变量 in [REVERSE] 初值表达式..终值表达式 LOOP
语句段;
END LOOP;
~~~~~~~~~~~~~~~~~~~~~~~~~~~
declare
type dept_table_type is table of dept%rowtype
index by binary_integer;
i number(1):=0;
v_dept_table dept_table_type;
begin
v_dept_table(0).deptno:='50';
v_dept_table(0).dname:='研发部';
v_dept_table(0).loc:='北京';
v_dept_table(1).deptno:='60';
......
for i in 0..v_dept_table.count-1 loop
insert into dept values
( v_dept_table(i).deptno,v_dept_table(i).dname,v_dept_table(i).loc);
end loop;
end;
6、异常处理
EXCEPTION
WHEN 异常错误名称1 [OR 异常错误名称2......] THEN
语句段1;
WHEN异常错误名称3 [OR 异常错误名称4......] THEN
语句段2;
......
WHEN OTHERS THEN
语句段3;
~~~~~~~~~~~~~~~用法~~~~~~~~~~~~~~~~
EXCEPTION
WHEN 错误名称 THEN
错误之后的后续内容(例如输出:dbms_output.put_line('出错了');)
预定义异常:
begin
insert into dept values(10,'aaaa','bbbb');
exception
when dup_val_on_index then
dbms_output.put_line('违反唯一约束!');
when others then
dbms_output.put_line('发生其他错误!');
end;
常用预定义异常:
NO_DATA_FOUND ===》select操作未返回行
TOO_MANY_ROWS ===》select操作,结果集超过一行
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
自定义异常:
declare
dept_no_emp exception;
begin
delete from emp where empno=&empno;
if sql%notfound then --sql未正确执行
raise dept_no_emp; --调用该错误
else
dbms_output.put_line('删除成功!');
end if;
exception
when dept_no_emp then
dbms_output.PUT_LINE('该员工不存在!');
end;
7、事务控制
Commit 语句用于提交事务
Rollback 语句可以将事务回滚到事务的起点或某个保存点开始
Savepoint <回滚点> ==设置回滚点
Rollback to <回滚点> ==回滚到该事务回滚点