5.3.2 PLSQL

PLSQL

Day01

一.常见的访问oracle的技术

plsql 过程化(procedure)sql 存储过程

proc/proc++ 使用c或者c++ 来访问oracle

odbc/ado vc中访问数据库的技术

oci oracle提供的底层接口

sqlj/jdbc java 访问数据库的技术

二.plsql 的特点

结构化 模块化编程

良好的可维护性

良好的可移植性 (同类型)

不便于向异构数据库移植

提升系统性能

三.plsql 扩展了sql

变量和类型

控制语句

函数和过程

对象和方法

四.plsql 程序结构

declare

​ /* 申明区

​ 声明变量 定义类型 */

begin

​ /* 执行区

​ 执行sql 语句 或者 plsql语句 */

exception

​ /* 异常处理区

​ 处理异常 */

end;

/

五.第一个plsql程序

begin

​ dbms_output.put_line('hello plsql!');

end;

/

设置输出为打开状态

set serveroutput on

开发工具:

命令行:sqlplus

图形化:windows plsqldeveloper

​ sqlprogramer

标示符:给变量 类型 游标 过程 函数 等命名的

六 变量

​ 6.1 如何声明变量

​ declare

​ 变量名 类型;

​ begin

​ / 如果一个变量没有赋值 则值为NULL /

​ declare

​ var_id number;

​ var_name varchar2(30);

​ begin

​ DBMS_OUTPUT.PUT_LINE(var_id||':'

​ ||var_name);

​ end;

​ /

6.2 plsql如何给变量赋值 和 初始化都是

​ 用 :=

​ declare

​ var_id number:=0;

​ var_name varchar2(30):='a';

​ begin

​ var_id:=100;

​ var_name:='test';

​ DBMS_OUTPUT.PUT_LINE(var_id||':'

​ ||var_name);

​ end;

​ /

6.3 变量的数据类型

​ 标量类型: number char varchar2 date

​ binary_integer boolean

​ 组合类型:record table cursor

​ 参考类型:ref cursor

​ 大类型:BLOB CLOB BFILE

​ (存储数据的位置 varchar2)

6.4 binary_integer boolean

​ declare

​ var_ind binary_integer;

​ var_f boolean;

​ begin

​ var_ind:=1000;

​ / var_f:=false; /

​ var_f:=true;

​ if var_f then

​ dbms_output.put_line(var_ind);

​ end if;

​ end;

​ /

6.5 变量的修饰

​ constant 类型 not null

​ declare

​ var_name varchar2(30) not null:='gg';

​ var_salary constant number:=10000;

​ begin

​ var_name:='hello';

​ -- var_salary:=10001;

​ dbms_output.put_line(var_name||':'||

​ var_salary);

​ end;

​ /

6.6 写一个plsql 定义两个变量 分别和s_emp

表中 first_name 和salary字段的类型相同。然后

把id=1 的first_name 和 salary 分别赋值给这

两个变量。打印这两个变量的值。

declare

​ var_name varchar2(25);

​ var_sal number(11,2);

begin

​ var_name:='Carmen';

​ var_sal:=1600;

​ dbms_output.put_line(var_name||':'

​ ||var_sal);

end;

/

6.7 表名.字段名%type 可以直接获取表的字段

​ 对应的类型。

​ 可以使用sql 语句 对变量进行赋值。

declare

​ var_name s_emp.first_name%type;

​ var_sal s_emp.salary%type;

begin

​ select first_name,salary

​ into var_name,var_sal

​ from s_emp

​ where id=25;

​ dbms_output.put_line(var_name||':'

​ ||var_sal);

end;

/

6.8 类似于c语言 结构体的类型 record类型

​ 6.8.1 语法

​ type 类型名 is record(

​ 字段名 类型,

​ 字段名 类型,

​ 字段名 类型

​ );

​ 变量名 类型名;

​ 6.8.2 把s_emp 表的id,first_name,salary

​ 包装成一个记录类型。然后把id=2 相关数据

​ 放入这个记录类型的变量中。然后输出这个

​ 变量的值。

​ declare

​ / 定义一个记录类型 /

​ type emptype is record(

​ id s_emp.id%type,

​ name s_emp.first_name%type,

​ salary s_emp.salary%type

​ );

​ var_emp emptype;

​ begin

​ select id,first_name,salary into var_emp

​ from s_emp

​ where id=2;

​ dbms_output.put_line(var_emp.id||':'||

​ var_emp.name||':'||var_emp.salary);

​ end;

​ /

6.8.3 记录类型之间的赋值

​ declare

​ / 定义一个记录类型 /

​ type emptype is record(

​ id s_emp.id%type,

​ name s_emp.first_name%type,

​ salary s_emp.salary%type

​ );

​ var_emp emptype;

​ var_emp1 emptype;

​ begin

​ select id,first_name,salary into var_emp1

​ from s_emp

​ where id=2;

​ /* 整体赋值

​ var_emp:=var_emp1; */

​ / 选择部分字段赋值 /

​ var_emp.name:=var_emp1.name;

​ var_emp.salary:=var_emp1.salary;

​ dbms_output.put_line(var_emp.id||':'||

​ var_emp.name||':'||var_emp.salary);

​ end;

​ /

6.8.4 如果查询字段数据 少于记录类型字段数

​ declare

​ / 定义一个记录类型 /

​ type emptype is record(

​ id s_emp.id%type,

​ name s_emp.first_name%type,

​ salary s_emp.salary%type

​ );

​ var_emp emptype;

​ begin

​ select first_name,salary

​ into var_emp.name,var_emp.salary

​ from s_emp

​ where id=2;

​ dbms_output.put_line(var_emp.id||':'||

​ var_emp.name||':'||var_emp.salary);

​ end;

​ /

6.9 思考如何把s_emp 表中 id=1 的所有信息放入

​ 一个记录类型的变量中?

​ 表名%rowtype 获得表的一行对应的类型

​ s_dept%rowtype

​ s_emp%rowtype

​ %rowtype 获取的类型 和 表头中字段名 和 字段

​ 的顺序完全相同。

​ declare

​ var_emp s_emp%rowtype;

​ begin

​ select * into var_emp from s_emp

​ where id=1;

​ dbms_output.put_line(var_emp.id||':'||

​ var_emp.first_name);

​ end;

​ /

6.10 类似于c数组的数据结构 table类型

​ 6.10.1 语法

​ type 数组类型名 is table of

​ 元素类型名 index by binary_integer;

​ 数组变量 数组类型;

​ 6.10.2 定义一个装 整数的数组类型 然后使用

​ 这个类型定义变量 把这些数(9,5,2,7)放入这

​ 个变量中。

​ 数组变量(下标):=值;

​ declare

​ type numstype is table of number

​ index by binary_integer;

​ var_nums numstype;

​ begin

​ var_nums(-1):=9;

​ var_nums(1):=5;

​ var_nums(0):=2;

​ var_nums(2):=7;

​ dbms_output.put_line(var_nums(2));

​ end;

​ /

6.10.3 知道下标从几开始

​ 知道元素个数

​ 知道下标是连续的

​ declare

​ type numstype is table of number

​ index by binary_integer;

​ var_nums numstype;

​ var_ind binary_integer;

​ begin

​ var_nums(-1):=9;

​ var_nums(1):=5;

​ var_nums(0):=2;

​ var_nums(2):=7;

​ var_ind:=-1;

​ dbms_output.put_line(var_nums(var_ind));

​ var_ind:=var_ind+1;

​ dbms_output.put_line(var_nums(var_ind));

​ var_ind:=var_ind+1;

​ dbms_output.put_line(var_nums(var_ind));

​ var_ind:=var_ind+1;

​ dbms_output.put_line(var_nums(var_ind));

​ end;

​ /

6.10.4 不知道下标从几开始

​ 不知道元素个数

​ 不知道下标是连续的

迭代器思想

first() 返回第一个元素对应的下标

next(n) 根据第一个元素的下标 返回 下一个

​ 元素对应的下标。

last() 返回最后一个元素对应的下标。

​ declare

​ type numstype is table of number

​ index by binary_integer;

​ var_nums numstype;

​ var_ind binary_integer;

​ begin

​ var_nums(-1):=9;

​ var_nums(1):=5;

​ var_nums(0):=2;

​ var_nums(3):=7;

​ var_ind:=var_nums.first();

​ dbms_output.put_line(var_nums(var_ind));

​ var_ind:=var_nums.next(var_ind);

​ dbms_output.put_line(var_nums(var_ind));

​ var_ind:=var_nums.next(var_ind);

​ dbms_output.put_line(var_nums(var_ind));

​ var_ind:=var_nums.next(var_ind);

​ dbms_output.put_line(var_nums(var_ind));

​ end;

​ /

6.10.5 定义一个table类型 用来存放 s_emp 表

id=1 id=11 id=20 的所有信息。存放的下标就

是id对应值。输出这些信息的 id first_name.

declare

​ type empstype is table of s_emp%rowtype

​ index by binary_integer;

​ var_emps empstype;

​ var_id number:=1;

begin

​ select * into var_emps(var_id)

​ from s_emp

​ where id=var_id;

​ var_id:=11;

​ select * into var_emps(var_id)

​ from s_emp

​ where id=var_id;

​ var_id:=20;

​ select * into var_emps(var_id)

​ from s_emp

​ where id=var_id;

​ / 使用迭代器遍历 /

​ var_id:=var_emps.first();

​ dbms_output.put_line(var_emps(var_id).id

​ ||':'||var_emps(var_id).first_name);

​ var_id:=var_emps.next(var_id);

​ dbms_output.put_line(var_emps(var_id).id

​ ||':'||var_emps(var_id).first_name);

​ var_id:=var_emps.next(var_id);

​ dbms_output.put_line(var_emps(var_id).id

​ ||':'||var_emps(var_id).first_name);

end;

/

七.变量的作用域 和 可见性

​ 局部区 可以访问全局区的数据

​ 全局区 不可以访问局部区的数据

​ / 这是plsql中的标签 /

​ <>

​ declare

​ var_n number:=1;

​ begin

​ declare

​ var_n number:=99;

​ begin

​ dbms_output.put_line(var_n);

​ dbms_output.put_line(abclab.var_n);

​ end;

​ end;

​ /

八.plsql 中的控制语句

​ 8.1 分支语句

​ 8.1.1 语法

​ if(a>b){ if a>b then

​ } end if;

​ if(a>b){ if a>b then

​ }else{ else

​ } end if;

​ if(a>b){ if a>b then

​ }else if(a>c){ elsif a>c then

​ }else if(a>d){ elsif a>d then

​ } end if;

​ if(a>b){ if a>b then

​ }else if(a>c){ elsif a>c then

​ }else if(a>d){ elsif a>d then

​ }else{ else

​ ; NULL;

​ } end if;

​ 8.1.2 定义三个整数变量 给这三个变量赋值

​ 然后输出这三个变量的最大值。

​ declare

​ var_a number:=9;

​ var_b number:=88;

​ var_c number:=0;

​ begin

​ if var_a<var_b then

​ if var_b<var_c then

​ dbms_output.put_line(var_c);

​ else

​ dbms_output.put_line(var_b);

​ end if;

​ else

​ if var_a < var_c then

​ dbms_output.put_line(var_c);

​ else

​ dbms_output.put_line(var_a);

​ end if;

​ end if;

​ end;

​ /

​ declare

​ var_a number:=9;

​ var_b number:=88;

​ var_c number:=0;

​ var_max number;

​ begin

​ var_max:=var_a;

​ if var_max<var_b then

​ var_max:=var_b;

​ end if;

​ if var_max<var_c then

​ var_max:=var_c;

​ end if;

​ dbms_output.put_line(var_max);

​ end;

​ /

​ 8.1.3 NULL 值的运算特点

​ declare

​ var_x number;

​ var_y number;

​ begin

​ if var_x < var_y then

​ dbms_output.put_line('var_x<var_y');

​ elsif var_x is null

​ and var_y is null then

​ dbms_output.put_line('var_x is null

​ and var_y is null');

​ elsif var_x > var_y then

​ dbms_output.put_line('var_x>var_y');

​ elsif var_x = var_y then

​ dbms_output.put_line('var_x=var_y');

​ end if;

​ end;

​ /

​ 8.2 循环语句

​ 8.2.1 简单循环的语法

​ loop

​ / 循环语句 /

​ end loop;

​ 8.2.2 如何退出循环

​ exit when 结束条件;

​ if 结束条件 then

​ exit;

​ end if;

​ 8.2.3 使用 简单循环 从1 输出到10

​ declare

​ var_i number:=1;

​ begin

​ loop

​ dbms_output.put_line(var_i);

​ exit when var_i=10;

​ var_i:=var_i+1;

​ end loop;

​ end;

​ /

​ 8.2.4 while 循环

​ while 循环条件 loop

​ / 循环代码 /

​ end loop;

​ 使用while 循环从1 输出到 10

​ declare

​ var_i number:=1;

​ begin

​ while var_i<11 loop

​ dbms_output.put_line(var_i);

​ var_i:=var_i+1;

​ end loop;

​ end;

​ /

​ declare

​ var_i number:=10;

​ begin

​ while var_i>0 loop

​ dbms_output.put_line(var_i);

​ exit when var_i=5;

​ var_i:=var_i-1;

​ end loop;

​ end;

​ /

​ 8.2.5 for 循环 (智能循环)

​ for 变量 in a..b loop

​ / 循环代码 /

​ end loop;

​ 使用for 循环输出 1 到 10

​ begin

​ for var_a in 1..10 loop

​ dbms_output.put_line(var_a);

​ end loop;

​ end;

​ /

​ begin

​ for var_a in reverse 1..10 loop

​ dbms_output.put_line(var_a);

​ exit when var_a=4;

​ end loop;

​ end;

​ /

​ for 循环中的变量 不允许外界修改

​ begin

​ for var_a in reverse 1..10 loop

​ dbms_output.put_line(var_a);

​ var_a:=11;

​ end loop;

​ end;

​ /

8.3 goto 语句

​ 8.3.1 语法

​ goto 标签名;

​ 8.3.2 使用 goto 完成 输出1到10

​ declare

​ var_i number:=1;

​ begin

​ <>

​ if var_i < 11 then

​ dbms_output.put_line(var_i);

​ var_i:=var_i+1;

​ goto myloop;

​ end if;

​ end;

​ /

​ 8.3.3

​ 判断退出的是内层循环

​ 但是我想退出外层循环 ?

​ begin

​ <>

​ for x in 1..4 loop

​ for y in 1..4 loop

​ dbms_output.put_line(y);

​ if y=3 then

​ exit myouterloop;

​ end if;

​ end loop;

​ end loop;

​ end;

​ /

​ begin

​ for x in 1..4 loop

​ for y in 1..4 loop

​ dbms_output.put_line(y);

​ if y=3 then

​ goto myouterloop;

​ end if;

​ end loop;

​ end loop;

​ <>

​ NULL;

​ end;

​ /

Day02

一.plsql 中如何使用sql语句

1.1 如何使用select语句

​ select语句要和into 结合使用 把查询的

​ 数据放入变量中。

​ select first_name,salary into var_a,var_b

​ from s_emp

​ where id=1;

1.2 dml(insert delete update)

​ tcl(commit rollback savepoint)

​ 直接在plsql中使用

​ insert into testlog values(1,'test');

​ commit;

1.3 ddl(creat table

​ drop table

​ alter table)

​ 不能直接在plsql中使用 需要使用动态sql

二.动态sql

​ 2.1 概念

​ sql语句在程序执行的过程中可以改变。

​ 2.2 实现

​ 把sql语句 做成字符串

​ 2.3 举例

​ declare

​ sqlstr varchar2(100);

​ begin

​ sqlstr:='create table testdsql(

​ id number)';

​ sqlstr:=substr(sqlstr,1,

​ length(sqlstr)-1);

​ sqlstr:=sqlstr||', name varchar2(30))';

​ dbms_output.put_line(sqlstr);

​ execute immediate sqlstr;

​ end;

​ /

2.4 dml 的动态sql

​ declare

​ sqlstr varchar2(100);

​ begin

​ sqlstr:='insert into testdsql values(

​ 100,''test100'')';

​ dbms_output.put_line(sqlstr);

​ execute immediate sqlstr;

​ commit;

​ end;

​ /

​ declare

​ sqlstr varchar2(100);

​ var_id number:=9527;

​ var_name varchar2(30):='zhouxingxing';

​ begin

​ sqlstr:='insert into testdsql values(';

​ sqlstr:=sqlstr||var_id;

​ sqlstr:=sqlstr||','''||var_name||''')';

​ dbms_output.put_line(sqlstr);

​ end;

​ /

2.5 使用占位符号 简化字符串的拼接

​ declare

​ sqlstr varchar2(100);

​ var_id number:=9527;

​ var_name varchar2(30):='zhouxingxing';

​ begin

​ sqlstr:=

​ 'insert into testdsql values(:b0,:b1)';

​ execute immediate sqlstr using

​ var_id,var_name;

​ commit;

​ end;

​ /

2.6 select 语句也可以是字符串

​ 必须是普通的select 不能带into

​ 只能返回一个结果

三.游标

​ 1.1 概念

​ 是一个数据缓冲区

​ 1.2 使用步骤

​ 定义游标

​ declare

​ cursor 游标名 is select语句;

​ 打开游标

​ open 游标名;

​ 提取数据 处理数据

​ fetch 游标名 into 变量;

​ 关闭游标

​ close 游标名;

​ 1.3 把s_emp 表中所有的数据 放入一个游标

​ 中 然后提取前两条数据 并打印这些数据

​ 的id first_name salary。

​ declare

​ cursor empcursor is

​ select * from s_emp;

​ var_emp empcursor%rowtype;

​ begin

​ open empcursor;

​ fetch empcursor into var_emp;

​ dbms_output.put_line(var_emp.id||':'||

​ var_emp.first_name||':'||var_emp.salary);

​ fetch empcursor into var_emp;

​ dbms_output.put_line(var_emp.id||':'||

​ var_emp.first_name||':'||var_emp.salary);

​ close empcursor;

​ end;

​ /

​ 1.4 游标属性

​ 游标名%found 在提取游标数据时 如果提取到了

​ 新数据则found属性返回真。如果没有提取到

​ 新数据则返回假。游标必须处于打开状态否

​ 则返回非法游标。游标必须fetch 否则返回

​ NULL。

​ 游标名%notfound 在提取游标数据时 如果提取到了

​ 新数据则返回假。如果没有提取到

​ 新数据则返回真。游标必须处于打开状态否

​ 则返回非法游标。游标必须fetch 否则返回

​ NULL。

​ 1.5 使用简单循环 结合 notfound 属性遍历游标

​ declare

​ cursor empcursor is

​ select * from s_emp;

​ var_emp empcursor%rowtype;

​ begin

​ open empcursor;

​ loop

​ fetch empcursor into var_emp;

​ / 当发现不了新数据时 结束循环 /

​ exit when empcursor%notfound;

​ dbms_output.put_line(var_emp.id||':'||

​ var_emp.first_name||':'||var_emp.salary);

​ end loop;

​ close empcursor;

​ end;

​ /

​ 1.6 使用 while循环 结合 found 属性

​ 遍历上面的游标。

​ declare

​ cursor empcursor is

​ select * from s_emp;

​ var_emp empcursor%rowtype;

​ begin

​ open empcursor;

​ fetch empcursor into var_emp;

​ while empcursor%found loop

​ dbms_output.put_line(var_emp.id||':'||

​ var_emp.first_name||':'||var_emp.salary);

​ fetch empcursor into var_emp;

​ end loop;

​ close empcursor;

​ end;

​ /

1.7 游标的其它属性

​ 游标名%isopen 游标是否处于打开状态

​ 如果打开 则返回真

​ 否则返回假

​ 打开的游标不能再打开

​ 关闭的游标不能再关闭

​ 游标名%rowcount 游标指针偏移量

1.8 for 循环遍历游标

​ 智能循环 会自动定义变量 自动打开 提取和关闭

​ declare

​ cursor empcursor is

​ select * from s_emp;

​ begin

​ for var_emp in empcursor loop

​ dbms_output.put_line(var_emp.id||':'||

​ var_emp.first_name||':'||var_emp.salary);

​ end loop;

​ end;

​ /

1.9 带参游标

​ plsql 中参数不能加任何长度修饰

​ 但是可以使用%type

​ 需要打开游标时传参

​ declare

​ cursor empcursor(var_id number) is

​ select * from s_emp where id>var_id;

​ var_emp empcursor%rowtype;

​ begin

​ open empcursor(15);

​ fetch empcursor into var_emp;

​ while empcursor%found loop

​ dbms_output.put_line(var_emp.id||':'||

​ var_emp.first_name||':'||var_emp.salary);

​ fetch empcursor into var_emp;

​ end loop;

​ close empcursor;

​ end;

​ /

​ declare

​ cursor empcursor(var_id number) is

​ select * from s_emp where id>var_id;

​ begin

​ for var_emp in empcursor(20) loop

​ dbms_output.put_line(var_emp.id||':'||

​ var_emp.first_name||':'||var_emp.salary);

​ end loop;

​ end;

​ /

1.10 参考游标(引用游标)

​ 游标 + 动态sql

​ 1.定义参考游标类型

​ type 参考类型名 is ref cursor;

​ 2.使用参考游标类型 定义游标变量

​ 变量名 参考类型名;

​ 3.把字符串关联到游标变量

​ open 游标变量名 for sqlstr;

​ 'select * from s_emp'

​ declare

​ type myrefcursor is ref cursor;

​ var_empcursor myrefcursor;

​ sqlstr varchar2(100);

​ var_emp s_emp%rowtype;

​ begin

​ sqlstr:='select * from s_emp';

​ / 把游标关联到字符串 /

​ open var_empcursor for sqlstr;

​ / 游标一旦打开就是普通的游标 /

​ loop

​ fetch var_empcursor into var_emp;

​ exit when var_empcursor%notfound;

​ dbms_output.put_line(var_emp.id||':'

​ ||var_emp.salary);

​ end loop;

​ close var_empcursor;

​ end;

​ /

​ declare

​ type myrefcursor is ref cursor;

​ var_empcursor myrefcursor;

​ sqlstr varchar2(100);

​ var_emp s_emp%rowtype;

​ begin

​ sqlstr:='select * from s_emp

​ where id>:b0';

​ / 把游标关联到字符串 /

​ open var_empcursor for sqlstr using 10;

​ / 游标一旦打开就是普通的游标 /

​ loop

​ fetch var_empcursor into var_emp;

​ exit when var_empcursor%notfound;

​ dbms_output.put_line(var_emp.id||':'

​ ||var_emp.salary);

​ end loop;

​ close var_empcursor;

​ end;

​ /

二.异常

系统定义的异常

自定义异常

2.1 当程序发生异常 plsql的默认处理方式

declare

​ var_name varchar2(30);

begin

​ dbms_output.put_line('app start!');

​ select first_name into var_name

​ from s_emp where id>1;

​ dbms_output.put_line('var_name='||

​ var_name);

​ dbms_output.put_line('app over!');

exception

​ when no_data_found then

​ dbms_output.put_line('no emp ');

​ when too_many_rows then

​ dbms_output.put_line('too many emp ');

​ when others then

​ dbms_output.put_line('have exception!');

end;

/

2.2 用户自定义异常

​ 1.定义异常

​ 异常变量 exception;

​ 2.根据条件 抛出异常

​ raise 异常变量;

​ 3.捕获异常

​ when 异常变量 then

​ 4.处理异常

declare

​ too_many_emp exception;

begin

​ if 1=1 then

​ raise too_many_emp;

​ end if;

exception

​ when too_many_emp then

​ dbms_output.put_line('have many emp');

​ when others then

​ dbms_output.put_line('others');

end;

/

三.存储过程

3.1 概念

匿名块

有名块(给具有业务含义的一组语句起一个名字

这个名字可以保存到数据库中)

3.2 存储过程的语法

create or replace procedure progetmax(

var_x number,var_y number:=10)

is

begin

​ if var_x < var_y then

​ dbms_output.put_line(var_y);

​ else

​ dbms_output.put_line(var_x);

​ end if;

end;

/

3.3 如何查看存储过程

​ desc 过程名;

​ desc progetmax;

​ select text from user_source

​ where name='PROGETMAX';

SQL> desc progetmax;

PROCEDURE progetmax

Argument Name Type In/Out Default?


VAR_X NUMBER IN

VAR_Y NUMBER IN DEFAULT

参数的名字

参数的类型

参数的模式 in 默认的模式

​ out

​ in out

参数的默认值 如果这个参数不传参 则使用

​ 默认值。

3.4 调用

begin

​ progetmax(1);

​ progetmax(9527,100);

​ progetmax(5,3);

end;

/

declare

​ x number:=1000;

​ y number:=200;

begin

​ progetmax(x,y);

end;

/

3.5 设计一个存储过程 传入一个整数参数

​ 这个参数的默认值是10。参数的作用代表

​ 从1输到的数。写出这个存储过程 并调用

​ 这个存储过程。1,2,9,11。

​ create or replace procedure printNnum10(

​ var_n in number:=10)

​ is

​ begin

​ for var_num in 1..var_n loop

​ dbms_output.put_line(var_num);

​ end loop;

​ end;

​ /

​ begin

​ printNnum10(1);

​ printNnum10(2);

​ printNnum10(9);

​ printNnum10(11);

​ end;

​ /

3.6 参数的模式

​ in 负责给存储过程传入参数

​ out 负责给存储过程传出参数

​ in out 既负责传入 又负责传入

​ void foo(int* x){

​ *x=1001;

​ }

​ int main(){

​ int x=10;

​ foo(&x);

​ x

​ }

​ 设计一个存储过程 传入三个整数参数

​ 然后把前两个参数的和 放入第三个参数中

​ create or replace procedure getSum(

​ x in number,y in number,z out number)

​ is

​ begin

​ z:=x+y;

​ end;

​ /

​ / 参数的位置赋值 /

​ declare

​ z number;

​ begin

​ getSum(1,2,z);

​ dbms_output.put_line(z);

​ end;

​ /

​ / 参数的名字赋值 /

​ declare

​ z number;

​ begin

​ getSum(x=>1,z=>z,y=>3);

​ dbms_output.put_line(z);

​ end;

​ /

3.6 设计一个存储过程 有两个整数参数

​ 打印这两个参数的最大值。并且把这两个

​ 参数的和放入第二个参数中。

​ 调用验证这个存储过程。

​ create or replace procedure getMaxAndSum

​ (x in number,y in out number)

​ is

​ begin

​ if x<y then

​ dbms_output.put_line(y);

​ else

​ dbms_output.put_line(x);

​ end if;

​ y:=x+y;

​ end;

​ /

​ declare

​ y number:=15;

​ begin

​ getMaxAndSum(100,y);

​ dbms_output.put_line(y);

​ end;

​ /

四.函数

​ 4.1 存储过程 和 函数的区别

​ 关键字不同 过程是procedure 函数是function

​ 函数有返回值类型 函数有返回值 过程没有

​ 调用方式不同 过程可以直接在plsql中调用

​ 函数必须组成表达式才能调用。

​ 4.2 设计一个函数 传入两个整数参数 返回最大值

​ create or replace function getmax(

​ x in number,y in number)return number

​ is

​ begin

​ if x<y then

​ return y;

​ end if;

​ return x;

​ end;

​ /

测试函数

select text from user_source

​ where name='GETMAX';

select getmax(1,100) from dual;

函数的调用

declare

​ var_z number:=1;

begin

​ var_z:=getmax(1,111);

​ dbms_output.put_line(var_z);

end;

/

4.3 设计一个函数 传入两个整数参数

返回两个参数的最大值。并且把两个参数

的和放入第二个参数中。

create or replace function getMaxSum(

​ x in number,y in out number)return number

​ is

​ var_temp number;

​ begin

​ var_temp:=y;

​ y:=x+y;

​ if x<var_temp then

​ return var_temp;

​ else

​ return x;

​ end if;

​ end;

​ /

​ declare

​ x number:=1;

​ y number:=1000;

​ z number:=0;

​ begin

​ z:=getMaxSum(x,y);

​ dbms_output.put_line('y='||y);

​ dbms_output.put_line('z='||z);

​ end;

​ /

create or replace procedure fpx11(

​ x in munber,y in out number)

is

begin

if x>y then

dbms_output.put_line(x);

else

dbms_output.put_line(y);

end if;

y:=x+y;

dbms_output.put_line(y);

end;

/

show errors

五.包 package

​ 5.1 概念

​ 把一组逻辑相关的数据 包装成一个逻辑名。

​ 5.2 系统提供的包

​ 使用包中的数据 需要在数据前 加包名。

​ 查看包 desc 包名;

​ dbms_output

​ dbms_output.put_line('hello world');

​ dbms_random

​ select dbms_random.value(1,100)

​ from dual;

​ select trunc(dbms_random.value(1,100))

​ from dual;

​ dbms_job 定时执行存储过程

​ uc crontab

​ 1.建立一张表

​ create table test1402job(

​ id number primary key,

​ name varchar2(30)

​ );

​ 2.建立一个序列

​ create sequence test1402job_id;

​ 3.写一个存储过程 向表中放入一条数据

​ create or replace procedure

​ insert1402_job

​ is

​ begin

​ insert into test1402job values(

​ test1402job_id.nextval,

​ 'test'||test1402job_id.currval);

​ commit;

​ end;

​ /

​ 4.dbms_job.submit(

​ JOB BINARY_INTEGER

​ WHAT VARCHAR2

​ NEXT_DATE DATE

​ INTERVAL VARCHAR2

​ );

​ 把定时任务提交给系统 系统会分配一个

​ 任务编号,把编号的值放入第一个参数中。

​ 第二个参数 是调用的存储过程名

​ 第三个参数 第一次调用的时间

​ 第四个参数 第二次调用的时间 第四个

​ 参数和 第三个参数的差就是周期。

​ dbms_job.run(JOB BINARY_INTEGER);

​ 把任务编号是job的任务执行起来。

​ \5. 周期性调用 存储过程

​ declare

​ jobno binary_integer;

​ begin

​ dbms_job.submit(jobno,

​ 'insert1402_job;',

​ sysdate,'sysdate+1/(24*60)');

​ dbms_output.put_line('jobno='||jobno);

​ dbms_job.run(jobno);

​ end;

​ /

​ select * from test1402job;

​ select job from user_jobs;

​ 6.删除定时任务

​ begin

​ dbms_job.remove(1422);

​ end;

​ /

​ 5.3 用户自定义包

​ 在包中的数据前 加包名。

​ 相当于c语言的头文件

​ create or replace package mypack

​ is

​ procedure packgetmax(x number,

​ y number);

​ function packgetmin(x number,

​ y number) return number;

​ end;

​ /

​ 写一个包的实现 相当于c中的实现文件

​ create or replace package body mypack

​ is

​ procedure packgetmax(x number,

​ y number)

​ is

​ begin

​ if x<y then

​ dbms_output.put_line(y);

​ else

​ dbms_output.put_line(x);

​ end if;

​ end;

​ function packgetmin(x number,

​ y number) return number

​ is

​ begin

​ if x<y then

​ return x;

​ end if;

​ return y;

​ end;

​ end;

​ /

​ 调用

​ begin

​ mypack.packgetmax(1,100);

​ end;

​ /

六.触发器 trigger

​ 6.1 在进行dml(insert delete update)操作时

​ 系统可以根据我们的操作 做出相应的响应。

​ 6.2 如何在一张表上建立触发器

​ create table testemp1021 as select

​ id,first_name,salary from s_emp;

​ create or replace trigger 触发器名

​ before|after insert|delete|update

​ on 表名

​ declare

​ begin

​ end;

​ /

​ create or replace trigger testemp1021_update

​ after update on testemp1021

​ declare

​ begin

​ dbms_output.put_line('update testemp1021');

​ end;

​ /

​ update testemp1021 set salary=salary+100

​ where id=1;

​ update testemp1021 set salary=salary+100

​ where id>1;

​ update testemp1021 set salary=salary+100

​ where id<1;

​ 上面的触发器 无论sql语句影响多少行 只触发

​ 一次 这叫语句级触发器。

​ 希望针对影响没一行都做触发,这样就可以拿到

​ 具体影响的数据。行级触发器。

​ create or replace trigger testemp1021_update

​ after update on testemp1021 for each row

​ declare

​ begin

​ dbms_output.put_line(:old.id||':'

​ ||:old.salary);

​ dbms_output.put_line('update testemp1021');

​ dbms_output.put_line(:new.id||':'

​ ||:new.salary);

​ end;

​ /

​ update testemp1021 set salary=salary+100

​ where id=1;

​ update testemp1021 set salary=salary+100

​ where id>1;

​ update testemp1021 set salary=salary+100

​ where id<1;

​ update :old :new

​ delete :old

​ insert :new

​ 触发器中要注意不能使用事务控制语句。


打赏

微信支付 支付宝支付

License

本作品由Simonhttp://www.uusystem.com)创作,采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。 欢迎转载,但任何转载必须保留完整文章,在显要地方显示此声明以及原文链接。如您有任何疑问或者授权方面的协商,请邮件:postmaster@uusystem.com。

results matching ""

    No results matching ""