【工作笔记】Oracle存储过程实战

本篇围绕几种模式:无参存储过程、带参存储过程、带参数存储过程含赋值方式、存储过程中游标定义使用、异常使用分别举例使用。

存储过程使用分为三步:编写存储过程->执行编译->调用使用

一、无参存储过程语法

(1)编写存储过程

create or replace procedure print_Time

IS

BEGIN

  DBMS_OUTPUT.PUT_LINE(SYSDATE);

END print_Time;

(2)运行编译


运行编译

(3)调用使用

A)SQL窗口执行:

DECLARE

BEGIN

  print_Time();

END;

B)SQL命令窗口执行:exec print_Time;


exec print_Time

二、带参存储过程实例

(1)编写存储过程

create or replace procedure print_Time2(in_callDate in varchar2)

IS

BEGIN

  DBMS_OUTPUT.PUT_LINE(to_date(in_callDate, 'yyyy-MM-dd HH24:mi'));

  --insert Log values(in_callDate);

END print_Time2;

(2)调用:

DECLARE

  p_outval number;

  p_inoutval VARCHAR2(10) := '~Hi~';

BEGIN

  print_Time2('2018-10-22');

END;

三、带参数存储过程含赋值方式

(1)创建两张表:一张用户表(并插入数据),一张用于统计用户注册(脚本见附件)


创建两张表

(2)添加几条数据到用户表


添加几条数据到用户表

(3)现在写一个存储过程,完成每天凌晨统计前一天不同城市用户注册数量

首先按照常规写出查询语句:

SELECT u.city as cityNme, count(*) as userCount

FROM z_test_user u

WHERE u.create_time >= to_date('2018-10-25', 'yyyy-MM-dd HH24:mi')

AND u.create_time < to_date('2018-10-25', 'yyyy-MM-dd HH24:mi')+1

GROUP BY u.city;

按照语法创建存储过程:

create or replace procedure PROC_STATISTICS_USER(inDate in varchar2)

IS

cityName          VARCHAR2(20);

userCount        NUMBER(10);

BEGIN

for cur_row in (

SELECT u.city as city, count(*)as tatal FROM z_test_user u

    WHERE u.create_time >= to_date(inDate, 'yyyy-MM-dd HH24:mi')

    AND u.create_time < to_date(inDate, 'yyyy-MM-dd HH24:mi')+1

GROUP BY u.city ) loop


  cityName := cur_row.city;

  userCount:= cur_row.tatal;

  insert into Z_TEST_USER_LOG values (SQL_Z_TEST_USER_LOG.NEXTVAL, cityName, userCount, SYSDATE);

  commit;

end loop;

END PROC_STATISTICS_USER;

说明:a)黑色字体为创建存储过程规范格式(如不明天请看第一部分理论学习)。

b) 红色字体分为三步,第一定义变量包括类型,第二赋值,使用“:=”,第三插入使用变量

    c) BEGIN之后是查询,并进行循环,格式:for 变量名 in() loop ... end loop;

  d)查询语句按照时间条件并按城市名称进行分组查询城市名称,总数,然后赋值给变量cur_row,下文使用cur_row.city、cur_row.tatal进行取值。

  e) insert into... 进行插入。

(4) 编译


编译

(5)调用执行

DECLARE

BEGIN

  PROC_STATISTICS_USER('2018-10-25');

END;

结果如下:


结果

注:实际存储调用一般放在定时任务调用。

四、存储过程中游标定义使用

注:依然使用上面表数据作为演示,完成每天凌晨统计前一天不同城市用户注册数量

(1)创建存储过程

create or replace procedure PROC_STATISTICS_USER_CUR(inDate in varchar2)

IS

  cityName          VARCHAR2(20); --定义变量

  userCount        NUMBER(10);  --定义变量

  -- storeName      VARCHAR2(20); --1定义变量

  Cursor cur_row IS

    SELECT u.city as city, count(*)as tatal FROM z_test_user u

    WHERE u.create_time >= to_date(inDate, 'yyyy-MM-dd HH24:mi')

    AND u.create_time < to_date(inDate, 'yyyy-MM-dd HH24:mi')+1

    GROUP BY u.city;

BEGIN

  FOR c_row IN cur_row LOOP

  cityName := c_row.city;  --赋值

  userCount:= c_row.tatal; --赋值

  -- 有些时候,有其他参数需要从其他表中查询下面给出一个举例

  -- select storeName

  -- into storeName    --2赋值

  -- from STORE_INFO t

  -- where t.STORE_NAME =c_row.city;


  insert into Z_TEST_USER_LOG values (SQL_Z_TEST_USER_LOG.NEXTVAL, cityName, userCount, SYSDATE);

  --storeName      -- 3 使用 

  commit;

END loop;

END PROC_STATISTICS_USER_CUR;

说明:a)首先看一下红色字体,storeName需要从其他表中查询,使用举例

    b) 游标使用格式:在is后Cursor 变量名 IS ... ;

    c) begin中使用:FOR c_row IN cur_row LOOP... END loop;赋值,插入等操作,此时for中in是直接使用游标进行。可以理解cur_row为父亲游标,c_row为子游标,就如数据和数组下标关系。

(2)编译执行及执行结果如下:


结果

五、异常使用

有时候执行存储过程会报错,调用者需要知道执行结果是否报错,此时需要定义传出参数,并在异常块进行赋值。捕获到异常之后:

1.记录错误相关信息  放入相关日志表  SQLCODE  SQLERRM

2.如果有事务相关的操作 一般是要rollback

(1)创建存储过程

create or replace procedure PROC_STATISTICS_USER_EX(inDate in varchar2, out_code out int, out_msg out varchar2)

IS

  val int;  --定义一个整数变量

BEGIN

  out_code := 0;

  out_msg  := 'success';

  val := 0/0;  -- 赋值,使用0做为除数,执行报异常

EXCEPTION

  when others then

    out_code := '-1';

    out_msg  := '统计发生异常' || substr(sqlerrm, 1, 100);

    dbms_output.put_line(out_code || '::'||out_msg);

    rollback ;

END PROC_STATISTICS_USER_EX;

(2)使用:使用命令窗口或者SQL窗口

a)先执行打开调试:set serverout on;

b) 再执行:

DECLARE

out_code number;

out_msg VARCHAR2(100);

BEGIN

  PROC_STATISTICS_USER_EX('2018-10-23', out_code, out_msg);

  dbms_output.put_line(out_code || '::'||out_msg);

END;

/

结果如下:


结果

SQL窗口:


SQL窗口


SQL窗口

留下一个问题:循环里面错误处理(oracle只支持begin...end中放错误捕获)

附件:

1,用户表创建及添加数据:

drop table Z_TEST_USER cascade constraints;

create table Z_TEST_USER

(

  ID          NUMBER not null,

  USERNAME    VARCHAR2(20),

  PASSWORD    VARCHAR2(100),

  CITY        VARCHAR2(50),

  CREATE_TIME DATE

)

tablespace USERS

  pctfree 10

  initrans 1

  maxtrans 255

  storage

  (

    initial 64K

    next 8K

    minextents 1

    maxextents unlimited

  );

comment on column Z_TEST_USER.ID

  is '用户ID';

comment on column Z_TEST_USER.USERNAME

  is '用户姓名(电话)';

comment on column Z_TEST_USER.PASSWORD

  is '密码';

comment on column Z_TEST_USER.CITY

  is '城市';

comment on column Z_TEST_USER.CREATE_TIME

  is '创建日期';

insert into Z_TEST_USER (ID, USERNAME, PASSWORD, CITY, CREATE_TIME)

values (5, 'eee', 'eee', '北京', to_date('25-10-2018 00:02:00', 'dd-mm-yyyy hh24:mi:ss'));

insert into Z_TEST_USER (ID, USERNAME, PASSWORD, CITY, CREATE_TIME)

values (1, 'aaa', 'aaa', '上海', to_date('25-10-2018 02:08:00', 'dd-mm-yyyy hh24:mi:ss'));

insert into Z_TEST_USER (ID, USERNAME, PASSWORD, CITY, CREATE_TIME)

values (2, 'bbb', 'bbb', '上海', to_date('25-10-2018 05:00:00', 'dd-mm-yyyy hh24:mi:ss'));

insert into Z_TEST_USER (ID, USERNAME, PASSWORD, CITY, CREATE_TIME)

values (3, 'ccc', 'ccc', '合肥', to_date('25-10-2018 04:02:01', 'dd-mm-yyyy hh24:mi:ss'));

insert into Z_TEST_USER (ID, USERNAME, PASSWORD, CITY, CREATE_TIME)

values (4, 'ddd', 'ddd', '合肥', to_date('25-10-2018 09:00:01', 'dd-mm-yyyy hh24:mi:ss'));

commit;

2,日志表创建

drop table Z_TEST_USER_LOG cascade constraints;

create table Z_TEST_USER_LOG

(

  ID        NUMBER not null,

  CITY      VARCHAR2(20),

  COUNT      NUMBER,

  COUNT_TIME DATE

)

tablespace USERS

  pctfree 10

  initrans 1

  maxtrans 255

  storage

  (

    initial 64K

    next 8K

    minextents 1

    maxextents unlimited

  );

comment on column Z_TEST_USER_LOG.ID

  is '用户ID';

comment on column Z_TEST_USER_LOG.CITY

  is '城市';

comment on column Z_TEST_USER_LOG.COUNT

  is '注册个数';

comment on column Z_TEST_USER_LOG.COUNT_TIME

  is '统计时间';

commit;

参考资料:

http://blog.csdn.net/u013057786/article/details/17165623

https://www.cnblogs.com/liangyihui/p/5886760.html

https://bbs.csdn.net/topics/391912626?page=1


来源:讯飞技术 https://mp.weixin.qq.com/s/aymp9_40eqKR8IiV9U2ABQ

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容