存储过程是一组为了完成特定功能的sql语句集,存储在数据库中,经过一次编译后再次调用不需要编译。用户通过指定存储过程的名字来执行它。
基本语法:
create or replace procedure procedure_01
is//一直纠结这里是is还是as,查资料后发现:在存储过程(procedure)和函数(function)中没有区别。在视图(view)中只能用as不能用is,在游标(cursor)中只能用is,不能用as。
begin
//要执行的代码行
commit;
end procedure_01;
调用存储过程:
call procedure_01();//注意括号不可省略。创建的时候不用加,调用的时候必需加上。
*前两天公司给安排了一个任务,要求写一个存储过程,循环遍历所有表,找出所有业务已经完成的记录,即status='11'的记录插入到历史表中,并删除原表中的记录。
记录下来,方便日后查询。历史表与原表的区别就是多了‘_H’。
create or replace procedure insertH
is
begin
insert into TW_ZNDW_TASK_MAIN_H select * from TW_ZNDW_TAKS_MAIN where status='11';
delete from TW_ZNDW_TAKS_MAIN T where status = '11' and EXISTS(select 1 from TW_ZNDW_TASK_MAIN_H H where T.id = H.id);
//exists是判断后面的sql语句是否为真,若为真则整个sql句子成立,否则没有任何记录。这句话的意思就是在删除原表记录之前先判断一下是否已经插入到了历史表中
//有时候为了提高效率,只是测试下某个表中是否存在记录,就用1来代替。
commit;
end insertH;
call insertH();
//上述代码只是插入一张表的记录。后面查了资料,学习了怎么循环遍历所有表,接下来分享完整代码。
create or replace procedure insertHistory
is
tableName1 varchar2(100);
tableName2 varchar2(100);
sqlstr varchar2(500);
cursor tableNameAll is Select table_name FROM USER_TABLES where regexp_like(table_name,'^TW_ZNDW_TASK_[0-9]+$') or table_name = 'TW_ZNDW_TASK';
//游标cursor,这里只能用is来赋值。USER_TABLES是系统表,使用USER_TABLES可查询所有的table_name字段。
begin
for tableName in tableNameAll loop
begin
tableName1 := tableName.table_name;//这里赋值用:=冒号加等号的形式赋值,tableName是形参,用来获取table_name赋值给tableName1;
tableName2 := tableName1+'_H';
sqlstr := 'insert into' || tableName2 || 'select * from' || tableName1 || 'where status='' 11'' ';//连接符号用||,也可以用+。
EXECUTE IMMEDIATE sqlstr; //表示立即执行该语句。
sqlstr := 'delete from' tableName1 || 'where status=''11'' and exists (select 1 from' || tableName2 || 't2 where t1.id = t2.id' )';
EXECUTE IMMEDIATE sqlstr;
commit;
end;
end loop;
end insertHistory;
调用:call insertHistory();
*另外一个任务,初始化部分数据。之所以把这个任务放在这里,是因为这是优化之后的代码,刚接手这个任务的时候我是一条一条记录来插入删除的,后来请教了组长才明白这么回事,可以动态执行。感觉跟存储过程有异曲同工之妙。
--删除历史数据
DELETE from TW_PROD_ELEC_RULE_CONFIG where RULE_TYPE='退服指标自动稽核算法';
--插入移动数据
INSERT INTO TW_PROD_ELEC_RULE_CONFIG
select
rawtohex(sys_guid()), o.ORGCODE, o.ORGNAME, NULL, NULL, NULL, NULL, '剔除免责站址数据,剔除夜间免责,未购买发电服务站址停电保够3小时的退服不纳入统计,运营商申告工单', '剔除免责站址数据 ,剔除夜间免责 ,未购买发电服务站址停电保够3小时的退服不纳入统计 ,运营商申告工单', '2', 'sa', sysdate, NULL, NULL, NULL, NULL, NULL, NULL, '退服指标自动稽核算法', '1001'
from BAF_ORG_ORGANIZATION o
where OBJECTTYPEID='3'
and (
o.ORGNAME like '%四川%'
or o.ORGNAME like '%河南%'
or o.ORGNAME like '%江苏%'
);
INSERT INTO TW_PROD_ELEC_RULE_CONFIG
select
rawtohex(sys_guid())as id,P_ORGID,P_ORGNAME,C_ORGID,C_ORGNAME,A_ORGID,A_ORGNAME,RULE_INFO,RULE_INFO_TEXT,STATUS,CREATE_USER,CREATE_DATE,
UPDATE_DATE,UPDATE_USER,COL1,COL2,COL3,RULE_COL_CHECK,RULE_TYPE,'1002' RETIREMENT_SCOPE
from TW_PROD_ELEC_RULE_CONFIG where RULE_TYPE='退服指标自动稽核算法'
UNION
select
rawtohex(sys_guid())as id,P_ORGID,P_ORGNAME,C_ORGID,C_ORGNAME,A_ORGID,A_ORGNAME,RULE_INFO,RULE_INFO_TEXT,STATUS,CREATE_USER,CREATE_DATE,
UPDATE_DATE,UPDATE_USER,COL1,COL2,COL3,RULE_COL_CHECK,RULE_TYPE,'1003' RETIREMENT_SCOPE
from TW_PROD_ELEC_RULE_CONFIG where RULE_TYPE='退服指标自动稽核算法';
*补充:
//union 和 union all都要求两个sql查询列要相同;
//union:联合查询出并集(会去除重复记录);
//union all:联合查询出并集,包含重复记录;