oracle存储过程学习


存储过程学习1- 无参存储过程

1 存储过程定义:
一组为了完成特定功能的 PL/SQL 语句集,存储在数据库中,
经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。
存储过程是数据库中的一个重要对象。

2 存储过程优点:

  1. 可维护性高
    2)简化操作流程

3 存储过程缺点
1)数据库移植不方便

4 hello world

create or replace procedure pro_test_demo
iS
begin
dbms_output.put_line('hello world')
end;
创建存储过程,进行编译,编译成功后会在Procedure看到结果。

5 运行存储过程

begin
pro_test_demo;
end;

存储过程学习2-有参存储过程

1 定义
create or replace procedure pro_with_params(v_a integer, v_b varchar2(36))
is
begin
dbms_output.put_line('第一个参数是:' || v_a);
end;
-- 和c类似, 参数类型写在后面

2 执行
begin
execute pro_with_params(1, 'abd');
end;

存储过程学习3-有输出参数的存储过程

1 定义
create or replace procedure pro_with_out_params(v_in_a in integer, v_out_b out varchar2)
is
begin

b:= 'abdd';
dbms_output.put_line('输入参数:' || a);
end;

2 执行

declare i varchar2(36);
begin
pro_with_out_params(1, i);
dbms_output.put_line('输出参数:' || i);
end;

注:存储过程括弧里面定义varchar时不需要长度,但在declare定义时必须要有长度。

存储过程学习4-存储过程变量%TYPE

1 存储过程中的变量类型:
1)标量类型
2)复合类型:记录类型,索引表类型(关联数组), varry变长数组

2 标量类型

常用的:NUMBER、CHAR 、VARCHAR2 、VARCHAR、NCHAR 、NVARCHAR2 、LONG 、DATE 、TIMESTAMP

3 %TYPE

%TYPE这种定义方式的变量类型, 利用已经存在的数据类型来定义新数据的数据类型,如定义多个变量或常量时,主要前面使用过的数据类型,后面的变量
可以利用%TYPE引用。

sex LY_DS.LY_NB%TYPE, 表示:定义一个变量sex, 它的数据类型与表LY_DS中的字段LY_NB类型一致

create or replace procedure test_select_procedure(
project PCA_PROJECT.NAME%TYPE, countNum out number)
is
begin
select count(*) into countNum from pca_project where name=project_name;
end;

存储过程学习5 -- 记录类型 %ROWTYPE

有一种场景:select多列,除了使用into的方法,还有另外一种引用名称.引用成员
先来into的写法
select count(*), max(id) into countNum, maxId from pca_project where id= 'ad';

如果是要获取多列的结果呢,into不合适。记录类型就是解决这个问题的。

1)type的声明方法
格式:type type_name is recored(col_name, col_type);
括号可多列,以逗号隔开。

declare
TYPE new_type IS RECORD -- 这是声明一种变量类型
(
v_project_name PCA_PROJECT.PROJECT_NAME%TYPE,
v_project_id PCA_PROJECT.PROJECT_ID%TYPE
);

v_obj new_type; -- 使用这种变量类型声明一个变量v_obj

BEGIN
select project_name, project_id into v_obj from pca_project where id='ss';
END;

2 %ROWTYPE的声明方法
%ROWTYPE, 该类型是提取行记录时常用的存储数据的方式。优点都是,避免表中字段数据类型改变,导致pl/sql块出错。

declare
v_obj pca_project%ROWTYPE;
BEGIN
select * into v_obj from pca_project where id='sdf';
dbms_output.put_line('第一个变量' || v_obj.name);
dbms_output.put_line('第二个变量' || v_obj.id);
END;

into前边最好为*, 否则就要将所有字段写全。

存储过程学习6-关联数组(索引表类型)

与数组类型,关联数组利用键值查找对应的数据。不同是,键值和数组的下标只为整数不一样,键值可为字符串。

1type自定义类型

1) 声明一个存储pca_project整行数据的索引表,下标为数字(binary_integer)
type index_row_type is table of pca_project%TYPE index by binary_integer;

2) 声明一个存储字符串数据的索引表,下标为数字
type index_varchar_type is table of varchar2(36) index by binary_integer;

3) 声明一个存储字符串数据的索引表,下标为字符串
type index_str_type is table of varchar(100) index by varchar(10);

2 利用自定义的索引表,定义变量

1) 声明一个下标为数字, 值为pca_project整行数据的变量
v_row index_row_type;

2) 声明一个下标为数字, 值为字符串的变量
v_var index_varchar_type;

3) 声明一个下标为字符串,值为字符串的变量
v_str_val index_str_type;

3 索引表赋值

和字典一样

  1. select * into v_row(1) from pca_project where id ='1';
  2. v_var(1) := '正数'; v_var(-1) := '负数'
  3. v_str_val('liuzhipeng') := '100分';

存储过程学习7-变长数组

1)声明

type array_type is varray(100) of varchar(100);

声明一个最多容纳100个元素的数组,每个元素类型为varchar(100), 下标从1开始,不是0;

  1. 定义变量

v_array array_type := array_type('one', 'two');

v_array2 array_type := array_type();

v_array2 array_type := array_type();
3) 获取第一个元素

v_array(1)

4)为数组扩展下一个空位

v_array2.extend;
v_array2(1) := 'hello';
v_array2.extend;
v_array2(2) := 'world';

  1. 为数组初始化长度

v_array3.extend(v_array2.count());

v_array3.extend(4);

存储过程学习8-简单增删改查sql

1 调用存储过程的方法

1) begin end内
begin
pro_test_demo;
pro_with_params(1);
end;

2)execute执行
execute pro_test_demo;
execute pro_with_params(1);

  1. call
    call pro_test_demo;
    call pro_with_out_params(1);

2 查询
create or replace procedure test_select2_procedure
(sex varchar)
AS
countNum number(10); --别忘了写上具体的长度,并且以分号结束
maxId number(10); --别忘了写上具体的长度,并且以分号结束
BEGIN
select count(*),max(id) into countNum,maxId from ly_ds where LY_NB=sex;
dbms_output.put_line(countNum);
dbms_output.put_line(maxId);
END;

3 插入 insert into
create or replace procedure test_add_procedure
(id varchar,createtime varchar,name varchar,
age varchar,sex varchar)
AS
BEGIN
insert into ly_ds values(id,createtime,name,age,sex);
commit; --别忘了加提交
end;

4 update

create or replace procedure test_update_procedure
(dsId varchar,mc varchar)
AS
BEGIN
update ly_ds set ly_mc = mc where id = dsId ;
commit; --别忘了加提交
end;

存储过程学习-9 游标cursor

当查询返回多条记录时,需要循环,就要使用到cursor。

1 cursor定义
游标就像查询数据返回的集合类型,比如List,把它当做一个引用类型,指向内存中查询结果集。

2 cursor例子
create or replace procedure pro_with_cursor(v_name varchar2)
is
CURSOR test_cursor is select id, name, type from pca_project where name=v_name;
v_cursor test_cursor%ROWTYPE; -- 因为select出来是行记录,可以使用%ROWTYPE, v_cursor表示一行记录的对象
BEGIN
for v_cursor in test_cursor loop
exit when test_cursor%notfound;
dbms_output.putline('数据是:' || v_cursor.id ||''||v_cursor.name ||''||v_cursor.type);
end loop;
END;

注意到:游标的操作步骤:声明游标,打开游标,提取数据,结束游标。但loop循环没有显示打开游标和关闭游标。

存储过程学习-10 遍历游标的方法for fetch while

create or replace procedure myprocedure is
CURSOR CUR_TEST IS --声明显式游标
SELECT ECODE,ENAME
FROM EMP;
CUR CUR_TEST%ROWTYPE; --定义游标变量,该变量的类型为基于游标C_EMP的记录

BEGIN 
  --For 循环
  FOR CUR IN CUR_TEST LOOP
      --循环体
    DBMS_OUTPUT.PUT_LINE('员工编号:'||CUR.ECODE ||'员工姓名:'|| CUR.ENAME);
  END LOOP;

  --Fetch 循环
  OPEN CUR_TEST;--必须要明确的打开和关闭游标
  LOOP 
    FETCH CUR_TEST INTO CUR;
    EXIT WHEN CUR_TEST%NOTFOUND;
    --循环体
    DBMS_OUTPUT.PUT_LINE('员工编号:'||CUR.ECODE ||'员工姓名:'|| CUR.ENAME);
  END LOOP;
  CLOSE C_EMP;

  --While 循环
  OPEN CUR_TEST;--必须要明确的打开和关闭游标
    FETCH CUR_TEST INTO CUR;
    WHILE CUR_TEST%FOUND LOOP  
      --循环体
      DBMS_OUTPUT.PUT_LINE('员工编号:'||CUR.ECODE ||'员工姓名:'|| CUR.ENAME);

      FETCH CUR_TEST INTO CUR;
    END LOOP;
  CLOSE C_EMP;



END myprocedure; 

从代码中可以很明显的看出:

1 使用for循环不需要关注游标是否打开或关闭。
2 for循环会自动将数据fetch到记录型变量。
3 for循环不需要关注何时要退出,也就是不需要写退出满足条件。遍历完成就会退出。

存储过程学习11-赋值、相等、分支

1 赋值
i := 0

2 相等
i=0 不相等<>

3 分支
if(条件1) then ... elsif(条件2)then ... else... end if

4 例子
create or replace procedure test_select5_procedure
(innum number,outnum out number)
AS
BEGIN
if (innum > 5) then --(判断条件是否大于5 ,满足条件则以then标识进入当前分支)
if(innum = 10) then -- (= 为相等)
outnum := 20; -- (:= 表示赋值)
else
outnum := innum + 1 ;
end if; --- (每个分支的结束都以 end if;来结束)
dbms_output.put_line('第一个分支:'||outnum);
elsif (innum > 0) then --- (elsif 的写法注意,亲测必须这么写才行,写成else if不行的)
outnum := innum - 1 ;
dbms_output.put_line('第二个分支:'||outnum);
else
outnum := -1 ;
dbms_output.put_line('第三个分支:'||outnum);
end if; --- (每个分支的结束都以 end if;来结束)
END;

存储过程学习11-case

create or replace procedure test_case_procedure(idnum varchar)
as
v_project pca_project%rowtype;
begin
select * into v_project from pca_project where id=idnum;
case v_project.sex
when '女' then
dbms_output.put_line('女人');
when '男' then
dbms_output.put_line('男人');
else
dbms_output.put_line('人妖');
end case;
end;


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM