- PL/SQL(PROCEDURAL LANGUAGE/SQL) 是标准的SQL的基础上增加了过程化处理的语言
- ORACLE 客户端工具访问ORACLE服务器的操作语言,对SQL的扩充
-
- 还有其他的客户端编程软件,例如pro*c/c++,ODBC,OCI,JDBC,SQLJ
- 程序结构:
- 申明部分:declare
- 执行部分:begin
- 异常处理:exception
- 对大小写不敏感
- 注释:-- 或者 /* */
-
-
- DECLARE
- v_firstName varchar2(32);
- v_firstName studengs.first_name%TYPE;
- v_TempVar Number(7,3) NOT NULL :=12.3;
- v_StuRec student%ROWTYPE;
-
- TYPE record_name IS RECORD(
- field1 type1 [NOT NULL] [:=EXPR1],
- field2 type2 [NOT NULL] [:=EXPR1]);
- 限定NOT NULL,那么它必须拥有一个初始值。
- TYPE tabletype IS TABLE OF type INDEX BY BINARY_INTEGER;
-
- TABLE类型的例子
- DECLARE
- TYPE t_StuTable IS TABLE OF Student%ROWTYPE
- INDEX BY BINARY_INTEGER;
- v_Student t_StuTable;
- BEGIN
- SELECT * INTO v_Student(1001)
- FROM Student
- WHERE id = 1001;
- END;
-
- 变量的作用域与可见性和PL/SQL控制语句(不作介绍,只显示例子)
-
-
DECLARE
-
v_str VARCHAR2(20);
-
v_num NUMBER:=199.01;
-
v_int BINARY_INTEGER:=220;
-
BEGIN
-
v_str:='well done leo!';
-
DBMS_OUTPUT.PUT_LINE(v_str);
-
DBMS_OUTPUT.PUT_LINE(v_int);
-
END;
-
-
-
1 DECLARE
-
2 v_str VARCHAR2(20);
-
3 v_num NUMBER:=199.01;
-
4 v_int BINARY_INTEGER:=220;
-
5 v_bool BOOLEAN;
-
6 BEGIN
-
7 v_str:='well done leo!';
-
8 DBMS_OUTPUT.PUT_LINE(v_str);
-
9 DBMS_OUTPUT.PUT_LINE(v_int);
-
10 v_bool:=false;
-
11 IF(v_bool) THEN
-
12 DBMS_OUTPUT.PUT_LINE('FALSE');
-
13 END IF;
-
14* END;
-
-
-
DECLARE
-
TYPE t_emp IS TABLE OF s_emp%ROWTYPE INDEX BY BINARY_INTEGER;
-
v_emp t_emp;
-
BEGIN
-
SELECT * INTO v_emp(100) FROM s_emp WHERE ID=12;
-
SELECT * INTO v_emp(200) FROM s_emp WHERE ID=15;
-
DBMS_OUTPUT.PUT_LINE(v_emp(100).id||':'||v_emp(100).last_name);
-
DBMS_OUTPUT.PUT_LINE(v_emp(200).id||':'||v_emp(200).last_name);
-
END;
-
-
-
1 DECLARE
-
2 TYPE t_emp_r IS RECORD(
-
3 v_id s_emp.id%TYPE,
-
4 v_last_name s_emp.last_name%TYPE);
-
5 TYPE t_emp_t IS TABLE OF t_emp_r INDEX BY BINARY_INTEGER;
-
6 v_emp_t t_emp_t;
-
7 BEGIN
-
8 FOR cnt in 1..25 LOOP
-
9 SELECT id,last_name
-
10 INTO v_emp_t(cnt).v_id,v_emp_t(cnt).v_last_name
-
11 FROM s_emp
-
12 WHERE id=cnt;
-
13 END LOOP;
-
14 FOR cnt IN 1..25 LOOP
-
15 DBMS_OUTPUT.PUT_LINE(v_emp_t(cnt).v_id||':'||v_emp_t(cnt).v_last_name);
-
16 END LOOP;
-
17 DBMS_OUTPUT.PUT_LINE('bye!');
-
18* END;
-
-
-
-
DECLARE
-
v1 NUMBER;
-
v2 VARCHAR2(10);
-
BEGIN
-
v1:=100;
-
v2:='hello';
-
DECLARE
-
v3 NUMBER;
-
v2 NUMBER;
-
BEGIN
-
v3:=300;
-
v2:=200;
-
END;
-
DBMS_OUTPUT.PUT_LINE(v1);
-
DBMS_OUTPUT.PUT_LINE(v2);
-
END;
-
结果
-
100
-
hello
-
-
-
-
1 <<outer>>
-
2 DECLARE
-
3 v1 NUMBER;
-
4 v2 VARCHAR2(10);
-
5 BEGIN
-
6 v1:=100;
-
7 v2:='hello';
-
8 DECLARE
-
9 v3 NUMBER;
-
10 v2 NUMBER;
-
11 BEGIN
-
12 v3:=300;
-
13 v2:=200;
-
14 DBMS_OUTPUT.PUT_LINE(outer.v2);
-
15 END;
-
16 DBMS_OUTPUT.PUT_LINE(v1);
-
17 DBMS_OUTPUT.PUT_LINE(v2);
-
18* END;
-
19 /
-
结果:hello
-
100
-
hello
-
-
-
1 DECLARE
-
2 bool BOOLEAN;
-
3 v_int BINARY_INTEGER;
-
4 BEGIN
-
5 bool := null;
-
6 IF(bool)THEN
-
7 DBMS_OUTPUT.PUT_LINE('WELL DONE');
-
8 END IF;
-
9 v_int:=3;
-
10 IF(v_int=1) then
-
11 DBMS_OUTPUT.PUT_LINE('1');
-
12 ELSIF(v_int=2) then
-
13 DBMS_OUTPUT.PUT_LINE('2');
-
14 ELSIF(v_int=3) then
-
15 DBMS_OUTPUT.PUT_LINE('3');
-
16 ELSE
-
17 DBMS_OUTPUT.PUT_LINE('5');
-
18 END IF;
-
19* END;
-
-
-
-
1 DECLARE
-
2 v_id s_emp.id%TYPE;
-
3 v_last_name s_emp.last_name%TYPE;
-
4 v_count NUMBER:=1;
-
5 BEGIN
-
6 LOOP
-
7 IF(v_count>25) THEN 通常loop之前一定要加上 IF语句来控制
-
8 EXIT;
-
9 END IF;
-
10 SELECT id,last_name
-
11 INTO v_id,v_last_name
-
12 FROM s_emp
-
13 WHERE id=v_count;
-
14 DBMS_OUTPUT.PUT_LINE(v_id||':'||v_last_name);
-
15 v_count :=v_count +1;
-
16 END LOOP;
-
17 DBMS_OUTPUT.PUT_LINE('END');
-
18* END;
-
-
-
1 DECLARE
-
2 v_id s_emp.id%TYPE;
-
3 v_last_name s_emp.last_name%TYPE;
-
4 v_salary s_emp.salary%TYPE;
-
5 v_cnt NUMBER:=1;
-
6 v_grade VARCHAR2(5);
-
7 BEGIN
-
8 LOOP
-
9 SELECT id,last_name,salary
-
10 INTO v_id,v_last_name,v_salary
-
11 FROM s_emp
-
12 where id=v_cnt;
-
13 IF (v_salary >=2000) THEN v_grade:='a';
-
14 ELSIF (v_salary >=1500) THEN v_grade:='b';
-
15 ELSIF (v_salary >=1000) THEN v_grade:='c';
-
16 ELSE v_grade:='d';
-
17 END IF;
-
18 DBMS_OUTPUT.PUT_LINE(v_last_name||':'||v_grade);
-
19 v_cnt:=v_cnt+1;
-
20 EXIT WHEN v_cnt>25; 当v_cnt大于25时就退出循环
-
21 END LOOP;
-
22* END;
-
-
-
1 DECLARE
-
2 v_id s_emp.id%TYPE;
-
3 v_last_name s_emp.last_name%TYPE;
-
4 v_salary s_emp.salary%TYPE;
-
5 v_cnt NUMBER:=1;
-
6 v_grade VARCHAR2(5);
-
7 BEGIN
-
8 WHILE(v_cnt<=25) LOOP 每一次循环 都要执行一次 WHILE里面的条件判断句
-
9 SELECT id,last_name,salary
-
10 INTO v_id,v_last_name,v_salary
-
11 FROM s_emp
-
12 where id=v_cnt;
-
13 IF (v_salary >=2000) THEN v_grade:='a';
-
14 ELSIF (v_salary >=1500) THEN v_grade:='b';
-
15 ELSIF (v_salary >=1000) THEN v_grade:='c';
-
16 ELSE v_grade:='d';
-
17 END IF;
-
18 DBMS_OUTPUT.PUT_LINE(v_last_name||':'||v_grade);
-
19 v_cnt:=v_cnt+1;
-
20 END LOOP;
-
21* END;
-
-
-
1 DECLARE
-
2 v_id s_emp.id%TYPE;
-
3 v_last_name s_emp.last_name%TYPE;
-
4 BEGIN
-
5 FOR cnt IN REVERSE 1..5 LOOP 加了REVERSE ,CNT由5开始减1
-
6 SELECT id,last_name
-
7 INTO v_id,v_last_name
-
8 FROM s_emp
-
9 WHERE id=cnt;
-
10 DBMS_OUTPUT.PUT_LINE(v_id||':'||v_last_name);
-
11 END LOOP;
-
12* END;
-
-
-
CURSOR游标
-
游标用于提取多行数据集
-
游标的使用:
-
(1)声明游标
-
(2)为查询打开游标
-
(3)将结果提取出来,存入PL/SQL变量中
-
(4)关闭游标
-
-
(1)CURSOR cursor_name IS SELECT * FROM...
-
(2)OPEN cursor_name;
-
(3)FETCH cursor_name INTO var1,var2...;
-
FETCH cursor_name INTO record_var;
-
(4)CLOSE cursor_name;
-
-
游标的属性:
-
%FOUND 前面FETCH返回一行数据,则为TRUE,未打开为false
-
%NOTFOUND 和上面的相反,未打开也为FALSE
-
%ISOPEN
-
%ROWCOUNT 指针位移量
-
-
-
-
1 DECLARE
-
2 CURSOR c_emp IS
-
3 SELECT * FROM s_emp;
-
4 v_emp s_emp%ROWTYPE;
-
5 BEGIN
-
6 OPEN c_emp;
-
7 FETCH c_emp INTO v_emp;
-
8 DBMS_OUTPUT.PUT_LINE(v_emp.id||':'||v_emp.last_name);
-
9* END;
-
-
-
1 DECLARE
-
2 CURSOR c_emp IS
-
3 SELECT * FROM s_emp;
-
4 v_emp s_emp%ROWTYPE;
-
5 BEGIN
-
6 OPEN c_emp;
-
7 LOOP
-
8 FETCH c_emp INTO v_emp;
-
9 DBMS_OUTPUT.PUT_LINE(v_emp.id||':'||v_emp.last_name);
-
10 END LOOP;
-
11* END;
-
-
-
1 DECLARE
-
2 CURSOR c_emp IS
-
3 SELECT * FROM s_emp;
-
4 v_emp s_emp%ROWTYPE;
-
5 BEGIN
-
6 OPEN c_emp;
-
7 LOOP
-
8 FETCH c_emp INTO v_emp;
-
9 EXIT WHEN c_emp%FOUND=false; 依赖于游标的属性
-
10 DBMS_OUTPUT.PUT_LINE(v_emp.id||':'||v_emp.last_name);
-
11 END LOOP;
-
12* END;
-
-
-
1 DECLARE
-
2 CURSOR c_emp IS
-
3 SELECT * FROM s_emp;
-
4 v_emp s_emp%ROWTYPE;
-
5 BEGIN
-
6 OPEN c_emp;
-
7 LOOP
-
8 FETCH c_emp INTO v_emp;
-
9 EXIT WHEN c_emp%NOTFOUND=true; 与c_emp%FOUND=false; 的结果是一样的
-
10 DBMS_OUTPUT.PUT_LINE(v_emp.id||':'||v_emp.last_name);
-
11 END LOOP;
-
12* END;
-
-
-
1 DECLARE
-
2 CURSOR r_em IS
-
3 SELECT last_name
-
4 FROM s_emp e,s_dept d
-
5 WHERE e.dept_id=d.id
-
6 AND d.region_id=4;
-
7 v_name s_emp.last_name%TYPE;
-
8 BEGIN
-
9 OPEN r_em;
-
10 LOOP
-
11 FETCH r_em INTO v_name;
-
12 EXIT WHEN r_em%NOTFOUND;
-
13 DBMS_OUTPUT.PUT_LINE(v_name);
-
14 END LOOP;
-
15 CLOSE r_em;
-
16* END;
-
-
-
1 DECLARE
-
2 CURSOR r_em IS
-
3 SELECT e.id,e.last_name
-
4 FROM s_emp e,s_dept d
-
5 WHERE e.dept_id=d.id
-
6 AND d.region_id=4;
-
7 v_name s_emp.last_name%TYPE;
-
8 v_id s_emp.id%TYPE;
-
9 BEGIN
-
10 OPEN r_em;
-
11 FETCH r_em INTO v_id,v_name; 两次FETCH
-
12 WHILE r_em%FOUND LOOP
-
13 DBMS_OUTPUT.PUT_LINE(v_id||':'||v_name); 先打印出来 ,再FETCH一次
-
14 FETCH r_em INTO v_id,v_name;
-
15 END LOOP;
-
16 CLOSE r_em;
-
17* END;
-
-
FOR 循环
-
1 DECLARE
-
2 CURSOR r_em IS
-
3 SELECT e.id,e.last_name
-
4 FROM s_emp e,s_dept d
-
5 WHERE e.dept_id=d.id
-
6 AND d.region_id=4;
-
7 BEGIN
-
8 FOR v_emp IN r_em LOOP
-
9 DBMS_OUTPUT.PUT_LINE(v_emp.id||':'||v_emp.last_name);
-
10 END LOOP;
-
11* END;
-
-
-
1 DECLARE 不用定义语句
-
2 BEGIN
-
3 FOR v_emp IN ( 用SELECT语句直接跟在FOR的IN语句后当作游标
-
4 SELECT e.id,e.last_name
-
5 FROM s_emp e,s_dept d
-
6 WHERE e.dept_id=d.id
-
7 AND d.region_id=4 这里不用分号
-
8 )LOOP
-
9 DBMS_OUTPUT.PUT_LINE(v_emp.id||':'||v_emp.last_name);
-
10 END LOOP;
-
11* END;
-
-
-
DECLARE
-
CURSOR c_emp IS
-
SELECT * FROM s_emp
-
WHERE dept_id=32
-
FOR UPDATE OF salary; 不加上OF的话,整个表都会加锁。有OF的话,只为这一列加锁
-
BEGIN
-
FOR v_emp IN c_emp LOOP
-
UPDATE s_emp set salary=salary*1.1
-
WHERE id=v_emp.id;
-
END LOOP;
-
END;
-
-
-
EXCEPTION
-
-
1 DECLARE
-
2 my_exception EXCEPTION;
-
3 v_emp s_emp%ROWTYPE;
-
4 v_sal s_emp.salary%TYPE;
-
5 BEGIN
-
6 SELECT salary INTO v_sal FROM s_emp
-
7 WHERE id=20;
-
8 IF(v_sal<1000) THEN
-
9 RAISE my_exception;
-
10 END IF;
-
11 DBMS_OUTPUT.PUT_LINE('END');
-
12 EXCEPTION
-
13 WHEN my_exception THEN
-
14 UPDATE s_emp set salary=salary+500 where id=20;
-
15* END;
-
-
-
-
-
SUB-PROGRAM
-
-
-
(1) PROCEDURE过程
-
CREATE[OR REPLACE] PRODUCE proc_name
-
[(arg_name[{IN | OUT| IN OUT}]TYPE,
-
arg_name[{IN | OUT| IN OUT}]TYPE]
-
{ IS | AS }
-
procedure_body
-
-
(2)FUNCTION函数
-
CREATE [OR REPLACE] FUNCTION func_name
-
[(arg_name[{ IN | OUT | IN OUT }]TYPE,
-
(arg_name[{ IN | OUT | IN OUT}]TYPE)]
-
RETURN TYPE
-
{IS|AS}
-
Func_body
-
-
-
-
PACKAGE 包
-
包头规范
-
CREATE [OR REPLACE] PACKAGE pack_name
-
{ IS | AS }
-
procedure_specification|;
-
function_specification|
-
variable_declaration|
-
type_definition|
-
exception_declaration|
-
cursor_declaration
-
END pack_name;
-
-
-
PACKAGE BODY 包主体
-
CREATE OR REPLACE PACKAGE BODY pac_name
-
{ IS | AS }
-
....
-
BEGIN
-
.....initialization code
-
END pac_name;
-
-
-
TRIGGER触发器,必须存在数据库中
-
都是带有名字的执行块
-
都有声明,执行体和异常处理部分
-
1 CREATE OR REPLACE TRIGGER zh_trigger
-
2 AFTER INSERT OR UPDATE OR DELETE ON s_emp
-
3 DECLARE
-
4 v_cnt NUMBER;
-
5 BEGIN
-
6 SELECT COUNT(*) INTO v_cnt FROM s_emp;
-
7 DBMS_OUTPUT.PUT_LINE('something changed!');
-
8* END;
-
9 /
-
-
Trigger created.