一.PL/SQL
1.什么是PLSQL
PROCEDURE LANGUAGE/SQL
PL/SQL 是使用sql的数据库编程语言,也是面向程序的程序语言
相比于SQL sql是声明语句 而 PL/SQL是程序语言(有执行体、循环体、结构体)
同时PL/SQL 不与数据库进行交互
用于编写 程序、触发器、函数、包
2.PLSQL数据类型
1.PL/SQL 数据类型:变量常量 生命周期
--变量数据类型分类 6种 number varchar2 date
--剩余三种是新类型 : 引用类型:V_NAME TABLE.COLUMN_NAME%TYPE
--记录型 自定义型: TYPE T_NAME IS RECORD(COLUMN_NAME DATA_TYPE,...);
--行记录型: V_NAME TABELE_NAME%ROWTYPE;
其次是常量 constant
当我们定义变量时规范以V_ 开头 定义变量以C_ 开头
--当我们定义常量时:需要添加关键字CONSTANT
DECLARE
C_TEST CONSTANT NUMBER(16) := 6666;
BEGIN
DBMS_OUTPUT.PUT_LINE(C_TEST);
C_TEST :=9999;
DBMS_OUTPUT.PUT_LINE(C_TEST);
END;--这里会报错 C_TEST不能作为赋值对象,我们看看变量可以复制吗
DECLARE
C_TEST1 NUMBER(16) := 6666;
BEGIN
DBMS_OUTPUT.PUT_LINE(C_TEST1);
C_TEST1 :=9999;
DBMS_OUTPUT.PUT_LINE(C_TEST1);
END;--这里可以看到 变量可以正常重新赋值
2.PL/SQL变量详解
--首先是ORACLE 自带的三种数据类型
DECLARE
V_CHAR VARCHAR2(20) :='SUN';
V_NUM NUMBER(10) :=66;
V_DATE DATE :=TO_DATE(TO_CHAR(SYSDATE,'YYYY/MM/DD'),'YYYY/MM/DD');
BEGIN
DBMS_OUTPUT.PUT_LINE(V_CHAR);
DBMS_OUTPUT.PUT_LINE(V_NUM);
DBMS_OUTPUT.PUT_LINE(TO_DATE(TO_CHAR(SYSDATE,'YYYY/MM/DD'),'YYYY/MM/DD'));
END;
--可以看到都成功打印 但是这种方式都写的是死值 只是举例用 这种变量并不好用 当数据改变 数据也需要重写 所以出现了引用类型变量
--日期格式 DD/M月/YY
--在上面的例子中,我们可以看到在赋值语句,这样的数据类型引用都只能输出单行单列
--其次是新认识的数据类型
引用型变量
%TYPE
DECLARE
--定义引用型变量
V_TEST2 EMP.EMPNO%TYPE;--值传递
--V_NAME TABLE.COLUMN
--%TYPE
BEGIN
SELECT EMPNO INTO V_TEST2 FROM EMP WHERE ENAME='SMITH';
--值传递
--输出结果
DBMS_OUTPUT.PUT_LINE(V_TEST2);
END;
上述实例只有一个变量,我们可以操作多个引用性变量吗?
DECLARE
V_TEST2 EMP.EMPNO%TYPE;
V_TEST3 EMP.MGR%TYPE;
BEGIN
SELECT EMPNO,MGR INTO V_TEST2,V_TEST3 FROM EMP WHERE ENAME='SMITH';
DBMS_OUTPUT.PUT_LINE('EMPNO:'||V_TEST2|| 'MGR:'||V_TEST3);
END;
--可以看到多个变量可以同时赋值(值传递)
行记录型变量
--频繁引用麻烦 也容易出错
--如何记录某张表的某一行的所有数据?
--V_NAME TABELE_NAME%ROWTYPE
DECLARE
V_TEST4 EMP%ROWTYPE;
BEGIN
SELECT * INTO V_TEST4 FROM EMP WHERE EMPNO =7369;
DBMS_OUTPUT.PUT_LINE(V_TEST4.ENAME);--可以输出多个
END;
--这个输出方式不要想着一次性全部输出 必须指定所记录的表的字段名称 并且字符串之间要用连接符号
在如下表连接中,可以输出所有内容,可以使用行记录型来输出吗?
SELECT E.*, D.* FROM EMP E JOIN DEPT D ON E.DEPTNO = D.DEPTNO;
DECLARE
V_EMP EMP%ROWTYPE;
V_DEPT DEPT%ROWTYPE;
BEGIN
SELECT E.*,D.* INTO V_EMP,V_DEPT FROM EMP E,DEPT D WHERE E.DEPTNO=D.DEPTNO AND EMPNO =7369;--ERROR
--报错: 不支持强制放入多个目标
DBMS_OUTPUT.PUT_LINE(V_EMP.ENAME);
END;
自定义类型记录变量
TYPE T_NAME IS RECORD(COLUMN_NAME DATA_TYPE)
T_NAME V_NAME (值传递)
DECLARE
TYPE T_TEST IS RECORD(EMPNO NUMBER(10), MGR NUMBER(10));
V_TEST T_TEST;
BEGIN
SELECT EMPNO,MGR INTO V_TEST FROM EMP WHERE ENAME = 'SMITH';
DBMS_OUTPUT.PUT_LINE(V_TEST.EMPNO||V_TEST.MGR);
END;
--自定义型变量又回到了第一种自定义变量 需要设置合适的字段数据类型和大小才可以 不然会报错
--这样还是输出一行 有啥意义
疑问1:为什么不直接定义一个这样的变量 而是要传递值?
疑问2:有没有能同时赋值多个字段并且多行赋值的变量?
--意义在于:这种写法可以表连接输出多张表的该数据的所有信息
SELECT * FROM EMP;
declare
type t_ed is record(
EMPNO NUMBER(4),
ENAME VARCHAR2(10),
JOB VARCHAR2(9),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7, 2),
COMM NUMBER(7, 2),
eno NUMBER(2),
dno number(2),
dname varchar2(20),
loc varchar2(20));
v_ed t_ed;
begin
select *
into v_ed
from emp e
join dept d
on e.deptno = d.deptno
where empno = 7369;
dbms_output.put_line('员工姓名:'||v_ed.ename||'部门名称:'||v_ed.dname);
end;
--error
declare
type t_ed is record(
v_emp emp%rowtype,
v_dept dept%rowtype);
v_ed t_ed;
begin
select e.*, d.*
into v_ed
from emp e
join dept d
on e.deptno = d.deptno
where empno = 7369;
dbms_output.put_line('员工姓名:' || v_ed.ename || '部门名称:' || v_ed.dname);
end;
--不能强制插入多条数据
3.关于PL/SQL的输出方式
PL/SQL 的打印语法
与JAVA 的 SYSTEM.OUT.PRINTLN()类似
DBMS_OUTPUT.PUT_LINE()作为PL/SQL的输出语句
我们可以看到在 DBMS_OUTPUT. 下有很多可选项 这些类型都被称为PROCEDURE 过程(什么是储存过程?)
其中有PUT_LINE() 和 PUT 两种输出方式
前者会自动换行
后者不会
DECLARE
--变量定义可省略
BEGIN
--执行体不可省略
--DBMS_OUTPUT.PUT_LINE('WECHAT');
DBMS_OUTPUT.PUT('QQ');
DBMS_OUTPUT.PUT('WECHAT');
DBMS_OUTPUT.PUT_LINE('');
--我们如果不执行最后一条输出语句 将不会输出任何结果
DBMS_OUTPUT并不是直接将数据执行输出到屏幕
--它首先将数据放到缓冲区 然后读取到换行符 将所有放入的数据重新读回打印 --->缓冲区减少了数据的打印执行次数 提升效率
--所以意思就是说 DBMS_OUTPUT方法下的PUT过程 在编写的时候没有写 换行符 这一步 导致我们只通过PUT打印会没有结果
--所以需要加一行换行来输出
--执行语句可以以NULL代替
--EXCEPETION
--异常可省略
END;--;必须 不可以省略
4.其它
--记录类型 not null
declare
type t_1 is record(
v_ename varchar2(20) not null := 'ALLEN',
v_job varchar2(20));
v_1 t_1;
begin
v_1.v_ename:=null;
end;
--类似于约束,限制变量不能为空值或者'',在添加后需要在定义时就要初始化,否则报错
--键盘输入符 &--自动搜寻功能
select * from emp where deptno=&部门编号;
select * from emp where ename='&员工姓名';
select * from emp where ename='SMITH';
declare
v_emp emp%rowtype;
v_empno number(4):=&员工编号;
begin
select * into v_emp from emp where empno=v_empno;
dbms_output.put_line('员工姓名:'||v_emp.ename);
end;
--
create view v_emp as select * from emp;
declare
v_e v_emp%rowtype;
begin
select * into v_e from emp where empno=7369;
dbms_output.put_line('员工姓名:'||v_e.ename);
end;
--所以这里不应该写table_name 应该写数据源 视图也可以用,子查询不可以用
(可能是因为视图是数据库对象)
.