PL/SQL 数据类型与基本输出
一.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
DECLAREC_TEST CONSTANT NUMBER(16) := 6666;BEGINDBMS_OUTPUT.PUT_LINE(C_TEST);C_TEST :=9999;
DBMS_OUTPUT.PUT_LINE(C_TEST);END;--这里会报错 C_TEST不能作为赋值对象,我们看看变量可以复制吗DECLAREC_TEST1 NUMBER(16) := 6666;BEGINDBMS_OUTPUT.PUT_LINE(C_TEST1);C_TEST1 :=9999;
DBMS_OUTPUT.PUT_LINE(C_TEST1);END;--这里可以看到 变量可以正常重新赋值
2.PL/SQL变量详解
--首先是ORACLE 自带的三种数据类型DECLAREV_CHAR VARCHAR2(20) :='SUN';
V_NUM NUMBER(10) :=66;
V_DATE DATE :=TO_DATE(TO_CHAR(SYSDATE,'YYYY/MM/DD'),'YYYY/MM/DD');
BEGINDBMS_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--在上面的例子中,我们可以看到在赋值语句,这样的数据类型引用都只能输出单行单列
--其次是新认识的数据类型
引用型变量
%TYPEDECLARE
--定义引用型变量
V_TEST2 EMP.EMPNO%TYPE;--值传递
--V_NAME TABLE.COLUMN
--%TYPEBEGINSELECT EMPNO INTO V_TEST2 FROM EMP WHERE ENAME='SMITH';
--值传递
--输出结果
DBMS_OUTPUT.PUT_LINE(V_TEST2);END;上述实例只有一个变量,我们可以操作多个引用性变量吗?DECLAREV_TEST2 EMP.EMPNO%TYPE;
V_TEST3 EMP.MGR%TYPE;BEGINSELECT 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%ROWTYPEDECLAREV_TEST4 EMP%ROWTYPE;BEGINSELECT * 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;DECLAREV_EMP EMP%ROWTYPE;
V_DEPT DEPT%ROWTYPE;
BEGINSELECT 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;declaretype 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;
beginselect *into v_edfrom emp ejoin dept don e.deptno = d.deptnowhere empno = 7369;dbms_output.put_line('员工姓名:'||v_ed.ename||'部门名称:'||v_ed.dname);
end;--error
declaretype t_ed is record(v_emp emp%rowtype,v_dept dept%rowtype);v_ed t_ed;
beginselect e.*, d.*into v_edfrom emp ejoin dept don e.deptno = d.deptnowhere 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
declaretype t_1 is record(v_ename varchar2(20) not null := 'ALLEN',v_job varchar2(20));v_1 t_1;
beginv_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):=&员工编号;
beginselect * 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;
beginselect * into v_e from emp where empno=7369;dbms_output.put_line('员工姓名:'||v_e.ename);
end;
--所以这里不应该写table_name 应该写数据源 视图也可以用,子查询不可以用
(可能是因为视图是数据库对象).