首先区分一下存储过程和视图的区别:
存储过程
存储过程可以使得对数据库的管理、以及显示关于数据库及其用户信息的工作容易得多。存储过程是SQL语句和可选控制流语句的预编译集合,以一个名称存储并作为一个单元处理。存储过程存储在数据库内,可由应用程序通过一个调用执行,而且允许用户声明变量、有条件执行以及其它强大的编程功能。
存储过程可包含程序流、逻辑以及对数据库的查询。它们可以接受参数、输出参数、返回单个或多个结果集以及返回值。
可以出于任何使用SQL语句的目的来使用存储过程,它具有以下优点:
可以在单个存储过程中执行一系列SQL语句。
可以从自己的存储过程内引用其它存储过程,这可以简化一系列复杂语句。
存储过程在创建时即在服务器上进行编译,所以执行起来比单个SQL语句快。
存储过程的功能取决于数据库所提供的功能。
视图
视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。
对其中所引用的基础表来说,视图的作用类似于筛选。定义视图的筛选可以来自当前或其它数据库的一个或多个表,或者其它视图。分布式查询也可用于定义使用多个异类源数据的视图。如果有几台不同的服务器分别存储组织中不同地区的数据,而您需要将这些服务器上相似结构的数据组合起来,这种方式就很有用。
通过视图进行查询没有任何限制,通过它们进行数据修改时的限制也很少。
补充:在内部来说其实两者实现基本一致,视图更重于数据展示,而存储过程 更重于数据内部逻辑处理
1.什么是存储过程。
存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存储过程。
2.存储过程的作用。
1)简单化复杂的操作。
2)增加数据独立性。
3)提高安全性。
4)提高性能。
3.存储过程语法。
CREATE OR REPLACE PROCEDURE [schema.] procedure_name
[parameter_name [[in] datatype[{:=|default}expression]
|{out|in out}[nocopy]datatype][,...]
{is | as}
BODY;
3.创建存储过程(范例)。
例1:
创建:
set serveroutput on
create or replace procedure pro_lentim as
begin
dbms_output.put_line('我的第一个存储过程');
end;
/
执行:
begin
pro_lentim;
end;
/
我的第一个存储过程
例2:
4.查看存储过程。
select * from user_source where NAME='PRO_LENTIM' order by LINE; --从user_source表中查询过程或函数需把名称大写。
5.查看存储过程错误。
show errors procedure pro_lentim;
6.无参存储过程示例。(存储过程无参数)
create or replace procedure pro_wucang as
begin
update t_avg
set t_avg.type = '促销'
where t_avg.jiage in (
select t_avg.jiage from (
select *from t_avg order by t_avg.jiage desc
)
where rownum < 4
);
commit;
end;
/
执行存储过程,验证是否成功。
EXEC pro_wucang;
SQL> select * from t_avg order by jiage asc;
ID NAME SHULIANG TYPE JIAGE
---------- ---------- ---------- ---------- ----------
1 苹果 5 促销 12
2 桃子 8 促销 30
3 莉 10 促销 33
1 芒果 6 45
2 李子 12 77
3 柠檬 8
7.存储过程中使用游标
set serveroutput on
create or replace procedure pro_youbiao as
pro_typeid t_type.typeid%type;
pro_typename t_type.type%type;
cursor cur_type is select typeid from t_type group by typeid;
begin
open cur_type;
loop
fetch cur_type into pro_typeid;
exit when cur_type%notfound;
select t_type.type into pro_typename from t_type where typeid=pro_typeid;
if sql%found then
dbms_output.put_line('----------------------------------');
dbms_output.put_line(pro_typename||':');
end if;
for a in (select * from t_procedure where type=pro_typename)
loop
dbms_output.put_line('商品名称:'||a.name||'商品数量:'||a.shuliang||'商品价格:'||a.jiage);
end loop;
end loop;
end;
/
SQL> exec pro_youbiao
----------------------------------
水果:
商品名称:苹果商品数量:100商品价格:9
商品名称:芒果商品数量:100商品价格:5
----------------------------------
电子:
商品名称:小米4商品数量:50商品价格:1499
商品名称:mini平板商品数量:20商品价格:2000
商品名称:MP3商品数量:50商品价格:300
----------------------------------
家具:
商品名称:双人床商品数量:3商品价格:1000
8.存储过程中的DDL语句。(创建临表)
书上例题解法:
set serveroutput on
create or replace procedure pro_ddl as
b_create varchar2(500);
b_delete varchar2(500);
b_insert varchar2(500);
b_yes_no varchar2(10);
b_type t_type.type%type;
b_output t_procedure%rowtype;
cursor cur_a is select type from t_type group by type;
cursor cur_b(a_type varchar) is select * from (select * from t_procedure where type=a_type order by jiage asc) where rownum<2;
begin
select count(1) into b_yes_no from all_tables t where t.TABLE_NAME='T_PROCEDURE_TMP';
b_create:='create global temporary table T_PROCEDURE_TMP (ID varchar2(10),NAME VARCHAR2(10),SHULIANG VARCHAR2(10),TYPE VARCHAR2(10),JIAGE VARCHAR2(10)) ON COMMIT PRESERVE ROWS';
b_delete:='delete from T_PROCEDURE_TMP';
b_insert:='insert into T_PROCEDURE_TMP (ID,NAME,SHULIANG,TYPE,JIAGE) VALUES
('''
||b_output.ID
||''','''
||b_output.NAME
||''','''
||b_output.SHULIANG
||''','''
||b_output.TYPE
||''','''
||b_output.JIAGE
||''')';
if b_yes_no=0 then
execute immediate b_create;
dbms_output.put_line('成功创建t_procedure_tmp临时表');
else
execute immediate b_delete;
dbms_output.put_line('t_procedure_tmp临时表已存在,且已清空表数据');
end if;
open cur_a;
loop
fetch cur_a into b_type;
exit when cur_a%notfound;
open cur_b(b_type);
fetch cur_b into b_output;
if cur_b%found then
if b_output.jiage<20 then
dbms_output.put_line('产品ID:'||b_output.id||'产品名称:'||b_output.name||'价格:'||b_output.jiage);
else
execute immediate 'insert into T_PROCEDURE_TMP (ID,NAME,SHULIANG,TYPE,JIAGE) VALUES
('''
||b_output.ID
||''','''
||b_output.NAME
||''','''
||b_output.SHULIANG
||''','''
||b_output.TYPE
||''','''
||b_output.JIAGE
||''')';
end if ;
end if;
close cur_b;
end loop;
commit;
close cur_a;
execute immediate 'update T_PROCEDURE_TMP SET TYPE=''促销''';
end;
/
SQL> EXEC PRO_ddl
t_procedure_tmp临时表已存在,且已清空表数据
产品ID:1产品名称:芒果价格:5
PL/SQL procedure successfully completed
SQL> select * from T_PROCEDURE_TMP
2 /
ID NAME SHULIANG TYPE JIAGE
---------- ---------- ---------- ---------- ----------
6 双人床 3 促销 1000
5 MP3 50 促销 300
注:
1、表名最好全用大写,用小写可能会出现查不到表的情况。
2、有一个疑问是我用b_insert去替换插入语句时居然无效,用来创建表和删除表数据时都没有问题,为什么插入数据时就不能用了呢?感觉真是奇怪。
3.execute immediate语句不得于执行效率,能少用就少用。
--------------------------------------------------------------------------------------
个人练习代码:
declare
a_output t_procedure%rowtype;
cursor cur_a is select * from t_procedure where jiage<20;
begin
open cur_a;
loop
fetch cur_a into a_output;
exit when cur_a%notfound;
dbms_output.put_line('产品id:'||a_output.id||'产品名称:'||a_output.name||'产品价格:'||a_output.jiage);
end loop;
end;
/
set serveroutput on
declare
b_create varchar2(200):='create global temporary table t_procedure_tmp(id varchar2(10),name varchar2(10),shuliang varchar2(10),type varchar2(10),jiage varchar2(10))on commit preserve rows';
b_delete varchar2(200):='delete from t_procedure_tmp';
b_insert varchar2(200);
b_yes_no varchar2(10);
b_output t_procedure%rowtype;
cursor cur_b is select * from t_procedure where jiage>20;
begin
select count(1)into b_yes_no from SYS.ALL_TABLES t where TABLE_NAME='T_PROCEDURE_TMP';
if b_yes_no=0 then
execute immediate b_create;
dbms_output.put_line('临表t_procedure_tmp创建成功');
else
execute immediate b_delete;
dbms_output.put_line('表记录删除成功');
end if;
open cur_b;
loop
fetch cur_b into b_output;
exit when cur_b%notfound;
execute immediate 'insert into t_procedure_tmp (ID,NAME,SHULIANG,TYPE,JIAGE) values
('''
||b_output.ID
||''','''
||b_output.NAME
||''','''
||b_output.SHULIANG
||''','''
||b_output.TYPE
||''','''
||b_output.JIAGE
||''')';
end loop;
commit;
close cur_b;
execute immediate 'update T_PROCEDURE_TMP set type=''促销商品''';
end;
/
9.有参的存储过程。
create or replace procedure pro_youcang(a_type in varchar2) as -----输入参数a_type
a_id t_type.typeid%type;
begin
select t_type.typeid into a_id from t_type where t_type.type=a_type;
if sql%found then
dbms_output.put_line('-----------------------------');
dbms_output.put_line(a_type||':');
end if;
for my_data_rec in (select * from t_procedure where t_procedure.type=a_type)-----for in 语句的灵活使用
loop
dbms_output.put_line('产品名称'||my_data_rec.name||'产品类别:'||my_data_rec.type||'产品价格:'||my_data_rec.jiage);
end loop;
exception
when no_data_found then
dbms_output.put_line('没有该类别数据');
when too_many_rows then
dbms_output.put_line('数据过多!');
end;
/
SQL> exec pro_youcang('电子');
-----------------------------
电子:
产品名称小米4产品类别:电子产品价格:1499
产品名称mini平板产品类别:电子产品价格:2000
产品名称MP3产品类别:电子产品价格:300
PL/SQL procedure successfully completed
SQL> exec pro_youcang('测试');
没有该类别数据
10.有默认值的带参数的存储过程。
create or replace function fun_moren return varchar2 is
begin
dbms_output.put_line('------已经进入到函数---------');
dbms_output.put_line('默认值是“水果”');
return '水果';
end fun_moren;
/
SQL> select fun_moren() from dual;
FUN_MOREN()
--------------------------------------------------------------------------------
水果
------已经进入到函数---------
默认值是“水果”
create or replace procedure pro_youcang(a_type in varchar2 default fun_moren()) as -----添加了默认的参数(使用function函数)
a_id t_type.typeid%type;
begin
select t_type.typeid into a_id from t_type where t_type.type=a_type;
if sql%found then
dbms_output.put_line('-----------------------------');
dbms_output.put_line(a_type||':');
end if;
for my_data_rec in (select * from t_procedure where t_procedure.type=a_type)-----for in 语句的灵活使用
loop
dbms_output.put_line('产品名称'||my_data_rec.name||'产品类别:'||my_data_rec.type||'产品价格:'||my_data_rec.jiage);
end loop;
exception
when no_data_found then
dbms_output.put_line('没有该类别数据');
when too_many_rows then
dbms_output.put_line('数据过多!');
end;
/
SQL> exec pro_youcang;
------已经进入到函数---------
默认值是“水果”
-----------------------------
水果:
产品名称苹果产品类别:水果产品价格:9
产品名称芒果产品类别:水果产品价格:5
11.存储过程中输出类型参数的使用
create or replace procedure pro_out(a_name in varchar2,a_id out varchar2) as
begin
select typeid into a_id from t_type where type=a_name;
if sql%found then
dbms_output.put_line(a_name||'对应的id是:'||a_id);
end if;
exception
when no_data_found then
dbms_output.put_line('没有数据');
when too_many_rows then
dbms_output.put_line('数据重复');
end pro_out;
/
create or replace procedure pro_out_yingyong(a_name in varchar2,a_jiage number) as
b_id t_type.typeid%type;
b_output t_procedure%rowtype;
begin
pro_out(a_name,b_id);
if sql%found then
dbms_output.put_line('-------------------');
dbms_output.put_line(a_name||' 产品的ID是:'||b_id);
end if;
for my_data_rec in (select * from t_procedure a where type_id=b_id and a.jiage<a_jiage)
loop
dbms_output.put_line('产品名称:'||my_data_rec.name||'产品价格:'||my_data_rec.jiage);
end loop;
end;
/
SQL> exec pro_out_yingyong('电子',700);
电子对应的id是:3
-------------------
电子 产品的ID是:3
产品名称:MP3产品价格:300
12.存储过程中in out函数的调用。
create or replace procedure pro_inout(a_id in varchar2,a_jiage in out number) as
begin
update t_procedure t set t.jiage=t.jiage*(1-a_jiage) where t.type_id=a_id;
if sql%found then
a_jiage:=sql%rowcount;
end if;
end pro_inout;
/
------------------------------
create or replace procedure pro_inout_yingyong(b_name in varchar2) as
b_n number;
b_id t_type.typeid%type;
begin
select t_type.typeid into b_id from t_type where t_type.type=b_name;
pro_inout(b_id,b_n);
if b_n>0 then
dbms_output.put_line('共修改了'||b_n||'条记录');
end if;
exception
when too_many_rows then
dbms_output.put_line('数据过多');
when no_data_found then
dbms_output.put_line('没有数据');
end;
/
SQL> exec pro_inout_yingyong('水果')
共修改了2条记录
13.使用plsql工具创建存储过程。
14.修改存储过程
create or replace procedure procedure_name.....
15.删除存储过程
drop procedure procedure_name;
评论回复