📄 script_76_old.txt
字号:
---------- emp_data.txt ----------
/*
* 范例名称:数据准备
* 文件名称:emp_data.txt
*/
--为避免删除scott中的empb数据以其它用户登录
connect system/manager
drop table emp;
create table emp
(empno varchar2(10),
ename varchar2(10),
sal number(6,2),
deptno number(3),
comm number(6,2));
insert into emp values ('a','TOM',100.11,10,null);
insert into emp values ('b','MIKE',200.11,2,null);
insert into emp values ('c','LI',3300.11,2,null);
commit;
---------- implicursor.txt ----------
/*
* 范例名称:隐式cursor(Implicit Cursor)
* 文件名称:implicursor.txt
*/
--Implicit Cursor TEST.USE %FOUND,%ROWCOUNT,%NOTFOUND
begin
update sm_emp
set name = '张飞' , salary = 99 where empid = '0000000009';
--使用隐式光标,判断是否更新成功。
if SQL%NOTFOUND then
--如果还没有相应id的纪录,insert.
dbms_output.put_line('sorry .没有雇员 0000000009 .insert');
insert into sm_emp values ('0000000009','张飞',99,null);
end if;
end;
--test
SELECT * FROM sm_emp;
connect scott/tiger
---------- cursor_loop.txt ----------
/*
* 范例名称:Cursor and Loop
* 文件名称:cursor_loop.txt
*/
--test cursor for loop
DECLARE
CURSOR c_emp IS
SELECT ename,sal
FROM emp
ORDER BY ename;
--定义游标
v_tot_sal NUMBER (10,2);
BEGIN
v_tot_sal :=0;
--游标for循环,求出雇员的工资总数。
FOR r_emp IN c_emp LOOP
DBMS_OUTPUT.PUT_LINE ('Name:' || r_emp.ename ||'salary:' || r_emp.sal);
v_tot_sal :=v_tot_sal +r_emp.sal;
END LOOP;
DBMS_OUTPUT.PUT_LINE ('Total salary is'||v_tot_sal);
END;
--test cursor for loop:光标不必显式打开,以上block没有cursor 的open语句。
--test: record在for loop外不可以引用
DECLARE
CURSOR c_emp IS
SELECT ename,sal
FROM emp
ORDER BY ename;
v_tot_sal NUMBER (10,2);
BEGIN
v_tot_sal :=0;
FOR r_emp IN c_emp LOOP
DBMS_OUTPUT.PUT_LINE ('Name:' || r_emp.ename ||'salary:' || r_emp.sal);
v_tot_sal :=v_tot_sal +r_emp.sal;
END LOOP;
DBMS_OUTPUT.PUT_LINE ('last person is ' || r_emp.ename );
END;
--err!在for以外引用record.
---------- cursor_dml.txt ----------
/*
* 范例名称:Cursor and DML
* 文件名称:cursor_dml.txt
*/
select job ,comm,sal from emp;
DECLARE
CURSOR c1 IS SELECT empno,sal
FROM emp
WHERE comm IS NULL
FOR UPDATE;
--要求对comm(佣金)为空的纪录更新。
v_comm NUMBER(10,2);
BEGIN
--用了一个光标for循环,逐条更新纪录
FOR r1 IN c1 LOOP
IF r1.sal <500 THEN
v_comm :=r1.sal *0.25;
ELSIF r1.sal <1000 THEN
v_comm :=r1.sal *0.20;
ELSIF r1.sal <3000 THEN
v_comm :=r1.sal *0.15;
ELSE
v_comm :=r1.sal *0.12;
END IF;
/*UPDATE USE WHERE CURRENT OF CLAUSE:
用WHERE CURRENT OF更新emp的对应纪录*/
UPDATE emp
SET comm =v_comm
WHERE CURRENT OF c1;
--在comm列中填入对应工资的25%,20%,15%,12%
END LOOP;
END;
--验证
select job ,comm,sal from emp
---------- lock.txt ----------
/*
* 范例名称:锁
* 文件名称:lock.txt
*/
--创建实验表1
--第一个SQL*Plus窗口:sqlplus(1)
create table a(a number);
insert into a values(1);
insert into a values(2);
commit;
--lock1:数据库设置lock的原因
--sqlplus(1)
update a set a=10 where a=2;
--没有commit;
--新打开一个SQL*Plus窗口
--(第二个sqlplus(2))
select * from a;
--可以看到a=2的纪录
update a set a=10 where a=2;
commit;
--此时结果如何呢?sqlplus(1)还未commit,
--如果允许sqlplus(2)更新并commit则sqlplus(1)的用户会发现他刚更改的纪录不见了。
--因此数据库设置lock
--lock2:
--sqlplus(1)
select * from a for update;
--(第二个SQL*Plus(2))
update a set a=10 where a=2;
--lock住。因为a=10这条纪录在sqlplus(1) select * from a for update;锁定范围内。
-此时,系统停顿状态,等待解锁,
-只要在第一个窗口发出roll;或commit;命令,即可解除锁定状态。
--第一个SQL*Plus窗口
--只锁定部分纪录
select * from a where a =1 for update;
--(第二个SQL*Plus)
update a set a=10 where a=2;
--ok.因为a=10不在锁定结果集内。
--另一个sqlplus
update a set a=10;
-此时,系统停顿状态,等待解锁,
-只要在第一个窗口发出roll;或commit;命令,即可解除锁定状态。
--原因是dml并发更改相同数据
---------- exception.txt ----------
/*
* 范例名称:Exceptions:PL/SQL的错误处理机制
* 文件名称:exception.txt
*/
--exception的处理机质:出现exception直接跳到exception处理段。
set serveroutput on
DECLARE
num_a NUMBER := 6;
num_b NUMBER;
BEGIN
num_b := 12;
--num_b := 0;
num_a := num_a / num_b;
num_b := 7;
--正常执行数出结果
dbms_output.put_line(' Value of num_a ' || num_a);
dbms_output.put_line(' Value of num_b ' || num_b);
EXCEPTION
WHEN ZERO_DIVIDE
--当发生.../0时,执行如下代码
/*......*/
THEN
dbms_output.put_line('Trying to divide by zero');
dbms_output.put_line(' Value of num_a ' || num_a);
dbms_output.put_line(' Value of num_b ' || num_b);
END;
--赋值错误EXCEPTION
DECLARE
X NUMBER;
BEGIN
X:= 'yyyy'; --Error Here
EXCEPTION WHEN VALUE_ERROR THEN
DBMS_OUTPUT.PUT_LINE('EXCEPTION HANDED');
END;
---------- named_exception.txt ----------
/*
* 范例名称:预定义EXCEPTION
* 文件名称:named_exception.txt
*/
--先建立SM_EMP:CreateTable_sm_emp.txt
DELETE FROM sm_emp WHERE name='TOM';
SET SERVEROUTPUT ON
--named exception test
DECLARE
v_name VARCHAR2(10);
n_sal NUMBER(8,2);
BEGIN
SELECT name , salary INTO v_name , n_sal FROM sm_emp
WHERE name='TOM';
DBMS_OUTPUT.PUT_LINE('TOM : SALARY :' || n_sal);
EXCEPTION
--注意:当多个exception在exception段中出现,只执行一个,之后不直接跳到end。
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('NO EMPLOYEE NAMED TOM');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('TOO MANY TOM');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERROR!');
END;
--insert TOM
INSERT INTO sm_emp VALUES ('001','TOM',999.99,'62543678');
--再次运行named exception test block
--insert TOM again
INSERT INTO sm_emp VALUES ('002','TOM',999.99,'62543678');
--第三次运行named exception test block
---------- user_defined.txt ----------
/*
* 范例名称:自定义异常处理
* 文件名称:user_defined.txt
*/
INSERT INTO sm_emp VALUES ('003','TOM3',999.99,NULL);
--用户定义的exception
DECLARE
CURSOR c_emp IS SELECT * FROM sm_emp;
loseTelno EXCEPTION;
BEGIN
OPEN c_emp;
FOR r_emp IN c_emp LOOP
--当出现telno IS NULL,自定义例外。
IF r_emp.telno IS NULL THEN
RAISE loseTelno; --AN EMPLOYEE WITHOUT TELNO
END IF;
END LOOP;
EXCEPTION
WHEN loseTelno THEN
DBMS_OUTPUT.PUT_LINE('loseTelno Error!' || r_emp.name || 'is lost');
END;
--Error:PLS-00201: 必须说明标识符 'R_EMP.NAME':为什么?
--记住:cursor for loop 使用的record只在cursor for loop 内有效。
--改进
DECLARE
CURSOR c_emp IS SELECT * FROM sm_emp;
loseTelno EXCEPTION;
v_name varchar(10);
BEGIN
FOR r_emp IN c_emp LOOP
IF r_emp.telno IS NULL THEN
v_name := r_emp.name;
RAISE loseTelno; --AN EMPLOYEE WITHOUT TELNO
END IF;
END LOOP;
EXCEPTION
WHEN loseTelno THEN
DBMS_OUTPUT.PUT_LINE('loseTelno Error!' || v_name || 'is lost');
END;
---------- nested_new.txt ----------
/*
* 范例名称:Nested Blocks
* 文件名称:nested_new.txt
*/
<<OUTER_BLOCK>>
DECLARE
A varchar2(20);
B NUMBER;
BEGIN
--A, B可以在OUTER_BLOCK块中访问
<<SUB_BLOCK>>
DECLARE
C NUMBER;
C1 VARCHAR2(40);
B varchar2(20) :='aaa';
--B再一次被定义 为varchar2(20)。
BEGIN
--C只可以在子块中访问
--A可以在此块中访问
C1 :=A;
--c :=B;--有这句正确吗?
--引用外层block的B
C :=OUTER_BLOCK.B;
END SUB_BLOCK;
--C不可以在这里访问
END OUTER_BLOCK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -