存储过程学习1- 无参存储过程
1 存储过程定义:
一组为了完成特定功能的 PL/SQL 语句集,存储在数据库中,
经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。
存储过程是数据库中的一个重要对象。
2 存储过程优点:
- 可维护性高
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 索引表赋值
和字典一样
- select * into v_row(1) from pca_project where id ='1';
- v_var(1) := '正数'; v_var(-1) := '负数'
- v_str_val('liuzhipeng') := '100分';
存储过程学习7-变长数组
1)声明
type array_type is varray(100) of varchar(100);
声明一个最多容纳100个元素的数组,每个元素类型为varchar(100), 下标从1开始,不是0;
- 定义变量
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';
- 为数组初始化长度
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);
- 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;