select * from emp ;
declare
begin
end
select * from emp ;
declare
begin
end
constant constant constant constant changliang
constant
%TYPE与%ROWTYPE使用
默认情况下系统输出的显示是关闭的,所以必须先修改显示的设置。
SET SERVEROUTOUT ON;
程序控制1
顺序结构
分支结构 if ,case
循环结构
自定义抛异常
除了有我们Oracle自己的异常;
有两种异常方式:
方式一:在声明EXCEPTION对象,此时有两种选择:
选择一:
声明异常对象并用名称来引用,此方式使用普通的other异常捕获用户定义异常;
选择二:声明一场对象并将它与有效的ORACLE错误代码映射,需要编写单独的WHEN语句块捕获;
方式二:再执行块中构建动态异常。
RAISE_APPLICATION_ERROR 函数可以构建动态的异常。在触发动态异常时,可以使用-20000--20999范围的数字,如果使用动态异常,可以在运行时指派错误消息;
5.00定义自己的异常;
如果不想自己的异常,使用other。
认为的抛出的异常有一个问题。默认的SQLCODE的内容是1.而SQLERRM的内容为用户自定义异常,那么用户可以直接自定义异常设置的一个名称;
在DECLARE 中
v_myexp EXCEPTION;
PRAGMA EXCEPTION_INIT(v_myexp,-20789);
绑定一个错误块:
DECLARE
v_myexp EXCEPTION;
v_input_rowid VARCHAR2(18);
PRAGMA EXCEPTION_INIT(v_myexp,-01410);
BEGIN
v_input_rowid:='&inputRowid';--输入一个ROWID数据;
IF LENGTH(v_input_rowid)<>18 THEN
RAISE v_myexp;
END IF;
EXCEPTION
WHEN v_myexp THEN
DBMS_OUTPUT.put_line('SQLCODE='||SQLCODE);
DBMS_OUTPUT.put_line('SQLERRM='||SQLERRM);
END;
/
可以自己定义错误信息;
范例:构建动态的错误;
2.异常的处理:
使用EXCEPTION,在这个语句中进行捕获:
WHEN异常类型|用户定义异常|异常代码|other|
OTHERS THEN 异常处理;
范例:处理被除数是0的异常:
DECLARE
v_result NUMBER;
BEGIN
v_result:=10/0 --被除数为0;
DBMS_OUTPUT.put_line('异常之后的代码将不再执行');
EXCEPTION
WHEN zero_divide THEN
DBMS_OUTPUT.put_line('被除数不能为零');
DBMS_OUTPUT.put_LINe(‘SQLCODE=’||SQLCODE);--(SQLCODE是异常的代码)
END;
/
正常的执行完毕了 ,同时再异常出现的时候
DECLARE
v_varA VARCHAR(1);
v_varB VARCHAR(4):='java';
BEGIN
v_varA:=v_varB;
DBMS_OUTPUT.put_line('异常之后的代码将不再执行');
EXCEPTION
WHEN value_error THEN
DBMS_OUTPUT.put_line('数据赋值错误');
DBMS_OUTPUT.put_LINe(‘SQLCODE=’||SQLCODE);--(SQLCODE是异常的代码)
END;
以上两个程序演示基本的处理情况;
范例:做一个查询的异常:
DECLARE
v_eno emp.empno%TYPE;
v_ename emp.ename%TYPE;
BEGIN
v_eno:=&empno;
select ename INTO v_ename FRON emp WHERE empno=v_eno;
DBMS_OUTPUT.put_line('编号为:'||v_eno||'雇员的名字为:'||v_ename);
EXCEPTION
WHEN no_data_found THEN
DBMS_OUTPUT.put_line('没有这个雇员!');
END;
/
返回多条数据:
一个变量只能接受一个值,
DECLARE
vdno emp.deptno%TYPE;
v_ename emp.ename%TYPE;
BEGIN
v_eno:=&deptno;
select ename INTO v_ename FRON emp WHERE deptno=v_eno;
EXCEPTION
WHEN too_many_rows THEN
DBMS_OUTPUT.put_line('返回数据过多');
END;
/
所以再plsol中提供了一种更为简单的处理方案;使用others处理十分方便:
DECLARE
vdno emp.deptno%TYPE;
v_ename emp.ename%TYPE;
BEGIN
v_eno:=&deptno;
select ename INTO v_ename FRON emp WHERE deptno=v_eno;
EXCEPTION
WHEN others THEN
DBMS_OUTPUT.put_line('返回数据过多');
DBMS_OUTPUT.put_line('SQLCODE='||SQLCODE);
DBMS_OUTPUT.put_line('SQLERRM='||SQLERRM);
END;
/
1.异常简单介绍:
设计错误,编码错误,硬件错误引起程序的运行错误,
编译错误;语法错误;
运行时异常;
DECLARE
v_i NUMBER:=1;
BEGIN
END;
/
用户只能出路运行异常,而针对于编译的异常,只能够通过语法解决;
内部程序块;
了解内部程序块如何使用:
范例:观察内部程序块:
DECLARE
v_x NUMBER:=30;--全局变量;
BEGIN
DECLARE
v_i VARCHAR2(40):=‘mldjava’;--局部变量
v_y NUMBER:=20;
BEGIN
DBMS_OUTPUT.put_line('内部程序块输出'||v_x);
DBMS_OUTPUT.put_line('内部程序块输出'||v_y);
END;
DBMS_OUTPUT.put_line('外部程序块输出'||v_x);
END;
/
会出现这样的内部形式;内部快会在任何一个地方出现的;
循环结构:
某一段的一共有LOOP FOR
1.LOOP语法
LOOP
循环执行的语句块;
EXIT WHEN 循环结束条件;
循环结束条件修改;
END LOOP;
范例:
DECLARE
v_i NUMBER:=1;
BEGIN
LOOP
DBMS_OUTPUT.put_line('v_i='||v_i);
EXIT WHEN v_i>=3;
v_i:=v_i+1;
END LOOP;
END;
/
结果执行三次;
LOOP 先执行后判断 至少执行一次;
2.WHILE....LOOP
WHILE(循环条件)LOOP
循环执行的语句块;
循环结束条件修改;
END LOOP;
范例:使用while..LOOP
DECLARE
v_i NUMBER:=1;
BEGIN
WHILE(v_i<=3)LOOP
DBMS_OUTPUT.put_line('v_i='||v_i);
v_i:=v_i+1;
END LOOP;
END;
/
先判断后执行;
3.FOR循环索引IN[REVERSE](可以反转)循环区域下限..循环区域上限LOOP
循环执行的语句块;
END LOOP;
DECLARE
v_i NUMBER:=1;
BEGIN
FOR v_i IN 1..3 LOOP
DBMS_OUTPUT.put_line('v_i='||v_i);
END LOOP;
END;
/
循环的语法并不复杂;针对循环个人的意见;
知道循环的次数 利用FOR循环;
不知道循环的次数,但是知道循环的结束条件;利用LOOP循环;
3.控制循环:
EXIT 和CONTINUE;
使用EXIT (和break)一样;
FOR v_i IN 1..10 LOOP
IF v_i=3THEN
EXIT/CONTINE;
END IF;
DBMS_OUTPUT.put_line('');
END LOOP;
END;
/
4.GOTO语句;
GOTO 无条件的一个跳转指令;
FOR v_i IN 1..10 LOOP
IF v_i=3THEN
GOTO endPoint;
END IF;
DBMS_OUTPUT.put_line('');
END LOOP;
<<endPiont>>
DBMS_OUTPUT.point_line('for循环结束');
END;
/
程序控制:
分支和循环语句;顺序,分支,循环
都只有一个出口,一个入口;
这是一个熟悉语法的过程;
分支结构 IF CASE
IF 判断条件THEN
执行语句;
END IF
DECLARE
v_countResult NUMBER
BEGIN
SELECT COUNT(empno) INTO v_countResult
FROM emp;
IF v_countResult>10 THEN
DBMS_OUTPUT.put_line('此记录大于10条')
END IF;
END;
/
IF 判断条件THEN
满足条件时执行语句;
ELSE
不满足条件执行语句;
END IF;
DECLARE
v_countResult NUMBER
BEGIN
SELECT COUNT(empno) INTO v_countResult
FROM emp;
IF v_countResult>10 THEN
DBMS_OUTPUT.put_line('此记录大于10条')
ELSE
DBMS_OUTPUT.put_line('此记录小于10条')
END IF;
END;
/
IF 判断条件1 THEN
满足条件执行语句;
ELSIF 判断条件2 THEN
满足时判断的语句;
ELSE
所有条件不满足时执行的语句;
END IF;
DECLARE
v_countResult NUMBER
BEGIN
SELECT COUNT(empno) INTO v_countResult
FROM emp;
IF v_countResult>10 THEN
DBMS_OUTPUT.put_line('此记录大于10条')
ELSIF v_countResult<10THEN
DBMS_OUTPUT.put_line('此记录小于10条');
ELSE
DBMS_OUTPUT.put_line('此记没有于10条');
END IF;
END;
/
进行IF,,也可以进行逻辑判断的名称;BEWTEEN ..and;
DECLARE
BEGIN
IF TO_DATE('1983-09-19','yyyy-mm-dd') BETWEEN TO_DATE('1980-01-01','yyyy-mm-dd')AND TO_DATE('1989-12-31','yyyy-mm-dd')THEN
DBMS_OUTPUT.put_LINE('');
END IF;
END;
/
IN
BEGIN
IF 10 IN(10,20,30)THEN
DBMS_OUTOUT.put_line('数据在');
END IF;
END;
/
NULL
LIKE
NOT FALSE
OR
2.CASE语句
CASE[变量]
DECLARE
v_choose NUMBER:=1;
v_varchar2 VARCHAR2(100):='';
BEGIN
CASE v_choose
WEHN 0 THEN
DBMS_OUTPUT.put_line('1');
WHEN 1 THEN
DBMS_OUTPUT.put_line('1');
ELSE
DBMS_OUTPUT.put_line('1');
END;
/
输入雇员的编号,根据雇员的职位进行工资提升,提升要求:随便分组就行;
数据类型划分;
各个语言都会有自己的数据类型,数据类型决定变量的类型;
1.类型简单介绍:
一共分为四类:
1.标量(SCALAR 基本数据类型):用于保存单个值,例如:字符串、数字、日期、布尔;
2.复合类型(COMPOSITE):复合类型可以再内部存在多种数值,类似多个变量的集合,例如:
记录类型、嵌套表、索引表、可变数组等
3.引用类型(RERERENCE):用于指向另一不同的对象,例如:REF CURSOR、REF
4.LOB类型:大数据类型,最多可以存储4G的信息,主要用来处理二进制数据;
1.数值型:
保存整数、浮点数,
定义整数(NUMBER(n)) 也可以定义
NUMBER(n,m);
浮点型+整数型=浮点型
2.大数据:
BINARY_INTEGER与PLS_INTEGER
在
v_x PLS_INTEGER:=10;
v_x PLS_INTEGER:=20;
BINARY_FLOAT 与BINARY_DOUBLE;
10g以后再使用的;
DECLARE
v_flag BINARY_FLAOT:=8909.51F;
v_flag BINARY_DOUBLE:=8909.51D;
观察表示的范围类容:
BEGIN
DBMS_OUTPUT.put_line('1、BINARY_FLOAT_MIN_NORMAL='||BINARY_FLOAT_MIN_NORMAL);
DBMS_OUTPUT.put_line('1、BINARY_FLOAT_MAX_NORMAL='||BINARY_FLOAT_MAX_NORMAL);
DBMS_OUTPUT.put_line('1、BINARY_FLOAT_MIN_NORMAL='||BINARY_FLOAT_MIN_SUBNORMAL);
DBMS_OUTPUT.put_line('1、BINARY_FLOAT_MAX_NORMAL='||BINARY_FLOAT_MAX_SUBNORMAL);
DBMS_OUTPUT.put_line('1、BINARY_FLOAT_MIN_NORMAL='||BINARY_DOUBLE_MIN_SUBNORMAL);
DBMS_OUTPUT.put_line('1、BINARY_FLOAT_MAX_NORMAL='||BINARY_DOUBLE_MAX_SUBNORMAL);
END;
/
表示的是范围的标识;
如果超出范围就是inf表示;
2.字符型:
字符型‘’声明的内容,常用的就是VARCHAR2
范例:观察char和varCHAR区别;
DECLARE
v_info_char CHAR(10);
v_info_varCHAR(10);
BEGIN
END;
/
CHAR 如果长度不够,就会自动填充,用空格填充;varCHAR2就不会;
DECLARE
v_info_char NCHAR(10);
v_info_varchar NVRCHAR2(10);
BEGIN
v_info_char:='摸了科技';
v_info_varchar:='java高端培训';
DBMS_OUTPUT.put_line('v_info_char内容长度:'||LENGTH(v_info_char));
DBMS_OUTPUT.put_line('v_info_char内容长度:'||LENGTH(v_info_char));
END;
/
按照unicode的,每一个只能站一位;
使用LONG 和LONG ROW的操作;
DECLARE
v_info_long LONG;
v_info_longraw LONG RAW;
BEGIN
v_info_long:='摸了科技';
v_info_longrow:=ULT_RAW.cast_to_raw('java高端培训');
DBMS_OUTPUT.put_line('v_info_char内容长度:'||LENGTH(v_info_char));
DBMS_OUTPUT.put_line('v_info_char内容长度:'||LENGTH(v_info_char));
UTL.RAW.cast.to.varchar2(v_info_longraw);
END;
/long和long row都是二进制保存的,所以这样的话就必须二进制保存
4.rowid 和UROWID
表示就是的行的信息;
从理论上将ROWID交给UROWID
DECLARE
v_emp_rowid ROWID;
v_emp_
5.日期型:
用户操作时间,时间间隔,
获得当前的时间:SYSDATE或SYSTIMESTAMP
定义DATE变量:
DECLARE
v_date1 DATE:=SYSDATE;
v_date2 DATE:=SYSTIMESTAMP
v_date3 DATE:='19-9月-1981';
BEGIN
DBMS_OUTPUT.put_line('日期数据:'||TO_CHAR(v_date1,'yyyy-mm-dd hh24:mi:ss'));
DBMS_OUTPUT.put_line('日期数据:'||TO_CHAR(v_date2,'yyyy-mm-dd hh24:mi:ss'));
DBMS_OUTPUT.put_line('日期数据:'||TO_CHAR(v_date3,'yyyy-mm-dd hh24:mi:ss'));
END;
/
TIMESTAMP 比DATE更加精确;
DECLARE
v_timestamp1 timestamp:=SYSDATE;
v_timestamp2 timestamp:=SYSTIMESTAMP
v_timestamp3 timestamp:='19-9月-1981';
BEGIN
DBMS_OUTPUT.put_line('日期数据:'||timestamp1);
DBMS_OUTPUT.put_line('日期数据:'||timestamp2);
DBMS_OUTPUT.put_line('日期数据:'||timestamp3);
END;
/
扩充子类型;
TIMESTAMP WITH TIME ZONE时间和格林威治的时间的偏移量;
TIMESTAMP WITH LOCAL ZONE:使用的是当前数据库的时间区;
INTERVAL
两种子类:
INERVAL YEAR[年的精度] TO MONTH
DECLARE
v_interval INTERVAL YEAR(3) TO MONTHS
:=ITERVAL '19-11'YEAR TO MONTH;
BEGIN
DEMS_OUTPUT.put_line('时间间隔:'||v_interval);
DEMS_OUTPUT.put_line(‘当前时间戳+时间间隔’||(systimestamp+v_interva;));
END;
/
定义
DECLARE
v_interval INTERVAL DAY(6) TO SECOND(3)
:=ITERVAL '818:19:27:23232'YEAR TO MONTH;
date和timestamp
5.bool型
DECLARE v_flag BOOLEAN
BEGIN
v_flag;=TURE;
IF v_flag THEN
DBMS_OUTPUT.put_line('条件满足');
END If;
END;
/
定义number的子类型;
SUBTYPE score_subtype IS NUMEBR(5,2) NOT NULL;
v_score score_subtype:=99.35;
BEGIN
DBMS_OUTPUT.put_line('成绩为:'||v_score);
END;
/
运算符:
1。赋值运算符
DECLARE
V_info VARCHAR2(50):='湿答答';
BEGIN
END;
/
连接运算符:
||
关系运算符:
DECLARE
v_url VARCHAR2(50):=‘www.mldnjava.cn’;
v_num1 NUMBER:=80;
v_num2 NUMBER:=30;
BEGIN
IF v_num1>v_num2 THEN
DEMS_OUTPUT.put_line('第一个数字比第二个数字大');
END IF
IF v_ur1 LIKE '%THEN%'THEN
DBMS_OUTPUT.put_line('网址中包含mldn单词');
END IF;
END;
/
4.逻辑运算符
AND OR NOT
范例:
DECLARE
v_flag1 BOOLEAN:=TURE;
v_flag2 BOOLEAN:=FALSE;
v_flag3 BOOLEAN;
BEGIN
IF v_flag1 AND(NOT v_flag2) THEN
DEMS_OUTPUT.put_line('第一个数字比第二个数字大');
END IF
IF v_ur1 LIKE '%THEN%'THEN
DBMS_OUTPUT.put_line('网址中包含mldn单词');
END IF;
END;
/
2016年8月5日 16:27:04 变量的声明和赋值;
1.掌握变量的声明和使用;
2.%type使用
3.%rowtype的使用
1.声明和使用
pl/sql是一种强类型
所有的变量都只能再声明之后才能使用;
DECLARE
v_result VARCHAR2(20)
--只是声明了变量;
BEGIN
DBMS_OUTPUT.put_line(''||)
END;
/
DECLARE
v_resultA NUMBER:=100;
v_resultB NUMBER;
v_result VARCHAR2(20)
--只是声明了变量;
BEGIN
v_resultb:=30;--没有区分大小写
DBMS_OUTPUT.put_line(''||)
END;
/两种方式的赋值;
定义非空变量:
DECLARE
v_result NUMBER NOT NULL=100;
--此变量不为空;
BEGIN
DBMS_OUTPUT.put_line(''||)
END;
/
定义常量
DECLARE
v_result CONSTANT NUMBER NOT NULL=100;
--此变量为常量;
BEGIN
DBMS_OUTPUT.put_line(''||)
END;
/
以上都是定义了已有类型的常量;
2 使用%TYPE声明变量;就是可以将已有的类型的值可以赋值给一个新的变量;
范例:使用% TYPE
DECLARE
v_eno emp.empno%TYPE;
v_ename emp.ename%TYPE;
--此变量为常量;
BEGIN
DBMS_OUTPUT.put_line('请输入雇员编号');
v_eno:=&empno;
select ename INTO v_ename FROM emp WHERE empno=v_eno; --将ename查到的值给予v_name
DBMS_OUTPUT.put_line(v_eno||'请输入雇员编号'||v_ename);
END;
/
使用此种方式,在日后的数据处理很方便;
3.使用%ROWTYPE
3.1.使用%ROWTYPE 标记IN表可以定义表中的一行记录的类型;
3.2.当用户使用了“SELECT。。。INTO。。”将表中的一行记录设置到了ROWTYPE类型的变量之中,就可以利用“rowtype变量.表字段”的方式取得表中每行的对应列数据;
范例:使用%ROWTYPE
DECLARE
v_deptROW dept%ROWTYPE --可以转下一行dept的内容;
BEGIN
SELECT * INTO v_deptROW FROM dept where
deptno=10;
DBMS_OUTPUT.put_line('部门编号:'||deptROW.deptno)
END;
pl/sql主要的特点:
SQL没有变量,sql没有流程控制(分支,循环)pl/sql是结构化和过程话的结合体,每一sql语句都是一句一句发送给数据库,但是pl/sql可以一起打包发送给数据库,减少网络流量。
DECLARE
v_eno NUMBER;--接受雇员的名字;
v_ename VARCHAR2(10)--接受雇员姓名;
BEGIN
v_eno:=&empno;//由键盘输入数据;
select ename INTO v_ename from emp where empno=v_eno;-- 将ename给v_ename
DBMS_OUTPUT.put_line('V_NUM变量的内容是:'||v_ename);
END;
/
DECLARE
v_myexp EXCEPTION ;
PRAGMA EXCEPTION_INIT(v_myexp,-01410) ;
BEGIN
IF (错误代码) THEN
RAISE v_myexp ; -- 抛出异常
END IF ;
EXCEPTION
WHEN v_myexp THEN
DBMS_OUTPUT.put_line('' || SQLCODE) ;
END ;
/
使用others,直接抛出RAISE_AAPLICATION_ERROR:
DECLARE
v_myexp EXCEPTION ;
BEGIN
IF (错误代码) THEN
RAISE_APPLICATION_ERROR(-20347,'此处出错了!') ; -- 设置错误信息
END IF ;
EXCEPTION
WHEN others THEN -- 直接使用others捕获自定义异常(编码要在-2w~-2.09w之间)
DBMS_OUTPUT.put_line('' || SQLCODE) ;
DBMS_OUTPUT.put_line('' || SQLERRM) ;
END ;
/
DECLARE
v_myexp EXCEPTION ;
PRAGMA EXCEPTION_INIT(v_myexp,-20347) ; -- 设置错误号
BEGIN
IF (错误代码) THEN
RAISE_APPLICATION_ERROR(-20347,'此处出错了!') ; -- 设置错误信息
END IF ;
EXCEPTION
WHEN v_myexp THEN -- 使用指定异常对象
DBMS_OUTPUT.put_line('' || SQLCODE) ;
DBMS_OUTPUT.put_line('' || SQLERRM) ;
END ;
/
练习
DECLARE
v_dno dept.deptno%TYPE ;
v_dna dept.dname%TYPE ;
v_deptCount NUMBER ; -- COUNT()函数结果
BEGIN
v_dno := &inputDeptno ;
v_dna := &inputDname ;
SELECT COUNT(deptno) INTO v_deptCount FROM dept WHERE deptno=v_dno ;
IF v_deptCount > 0 THEN
RAISE_APPLICATION_ERROR(-20544,'部门已存在,请重新输入!') ;
ELSE
INSERT INTO dept(deptno,dname) VALUES (v_dno,v_dna) ;
DBMS_OUTPUT.put_line('部门信息添加成功') ;
COMMIT ;
END IF ;
EXCEPTION
WHEN others THEN
DBMS_OUTPUT.put_line(SQLCODE) ;
DBMS_OUTPUT.put_line(SQLERRM) ;
ROLLBACK ;
END ;
/
直接使用others替代异常类型(类似于Exception类)
DECLARE
BEGIN
EXCEPTION
WHEN value_error THEN
DBMS_OUTPUT.put_line() ;
DBMS_OUTPUT.put_line(SQLCODE) ;
WHEN others THEN
DBMS_OUTPUT.put_line() ;
DBMS_OUTPUT.put_line(SQLCODE) ;
DBMS_OUTPUT.put_line(SQLERRM) ;
END ;
/
异常处理
DECLARE
BEGIN
EXCEPTION
END ;
/
内部块(任何位置定义)
DECLARE
v_x NUMBER := 30 ; -- 全局变量
BEGIN
DECLARE
v_x VARCHAR2(40) := '' ; -- 局部变量
BEGIN
DBMS_OUTPUT.put_line(v_x) ;
END ;
DBMS_OUTPUT.put_line(v_x) ;
END ;
/
EXIT ; 等同于 break ;
DECLARE
v_i NUMBER := 1 ;
BEGIN
LOOP
DBMS_OUTPUT.put_line() ;
EXIT WHEN v_i>=3 ;
v_i := v_i + 1 ;
END LOOP ;
END ;
/
DECLARE
v_i NUMBER := 1 ;
BEGIN
FOR v_i IN [REVERSE] 1..3 LOOP
DBMS_OUTPUT.put_line() ;
END LOOP ;
END ;
/