plsql语言学习,mybatis调用oracle存储过程

oracle存储过程

1.从HelloWolrd开始

创建存储过程

1.1第一种方式,直接创建
-- 存储过程的Hello world
create or replace procedure p_hello is
--无参的存储过程。
--声明变量
       --调用方法1.新建一个TEST WINDOW  begin与end之间输入 p_hello;即可执行
       --在控制台里输入  exec  存储过程名
begin
       dbms_output.put_line('hello world');      
end p_hello;

  • 测试存储过程的两种方式

    • 第一种方式begin…end
    -- 测试 (第一种方式)
    begin
      -- Call the procedure
      p_hello;
    end;
    
    • 第二种方式 call procedure_name();
    -- 测试 (第二种方式)
    call  p_hello();
    commit;
    
    • 第三种(和第一种类似)
    DECLARE
    begin
      -- Call the procedure
      p_hello;
    end;
    
    • 第四种方式(必须使用命令行的方式)
    exec p_hello;
    
  • 控制台输出

    hello world

    说明:

    plsql的dbms_output.put_line(‘hello world’);

    相当于java的System.out.println(“hello world”);

1.2第二种方式,使用package的方式
  • 创建一张demo表
create table USER_INFO

(

id VARCHAR2(4),

username VARCHAR2(15),

password VARCHAR2(15),

address VARCHAR2(30)

);
  • 然后定义存储过程USER_INSERT,先定义PACKAGE包头USER_CONTROL
-- 存储过程包头USER_CONTROL
CREATE OR REPLACE PACKAGE USER_CONTROL AS

PROCEDURE USER_INSERT (

in_id user_info.id%TYPE,

in_username user_info.username%TYPE,

in_password user_info.password%TYPE,

in_address user_info.address%TYPE

);

END USER_CONTROL;
  • 在定义PACKAGE BODY包体USER_CONTROL,这里包头和包体的名字要相同
-- 存储过程包体
CREATE OR REPLACE PACKAGE BODY USER_CONTROL AS

PROCEDURE USER_INSERT (

in_id user_info.id%TYPE,

in_username user_info.username%TYPE,

in_password user_info.password%TYPE,

in_address user_info.address%TYPE

)IS

BEGIN

INSERT INTO USER_INFO(ID,USERNAME,PASSWORD,ADDRESS) VALUES(in_id,in_username,in_password,in_address);

END;

END USER_CONTROL;
  • 调用存储过程

DECLARE

BEGIN

USER_CONTROL.USER_INSERT('11','11','11','11');

END;

说明:

1.调用存储过程测试,别忘了提交事务,否则也会不生效

2.其实我们可以简单的这样理解,把PACKAGE包头理解为JAVA中的接口,把PACKAGE BODY理解为JAVA中实现这个接口的类,而里面的存储过程就相当于类中的方法了。

2.plsql语法简单学习(面向过程编程语言)

2.1通用模板

– 语法
DECLARE
– 声明部分(变量的声明、游标的声明(cursor)、例外的声明(异常))
BEGIN
– 语句序列(DML语句)
EXCEPTION
– 例外处理语句
END;

  • plsql语言的Helloworld

    declare
    begin
      dbms_output.put_line('helloworld');
      end;
    

2.2说明变量

DECLARE
   -- 说明变量:char、varchar2、date、number、boolean、long
   v_num number;
   -- 赋值
   v_char varchar2(24) := 'it is good';
BEGIN
   -- 赋值
   v_num := 10;
   -- 拼接结果
   dbms_output.put_line('hello, world' || '! v_num=' || v_num || ', v_char=' || v_char);
END;

控制台打印:

hello, world! v_num=10, v_char=it is good

2.3引用变量

declare
v_name demo.name%type;
begin
select name into v_name from demo where id=1;
dbms_output.put_line('v_name的值为:'||v_name);
end;

控制台打印:

v_name的值为:demo的name1

2.4记录型变量

DECLARE
   -- 记录型变量
   v_row demo%rowtype;
BEGIN
   SELECT * INTO v_row FROM demo WHERE id = 1;
   dbms_output.put_line('名字为:' || v_row.name);
END;

2.5if语法

语法

语法:
[1] IF 条件 THEN 
        code....;
    END IF;
[2] IF 条件 THEN
        code....;
    ELSE
        code....;
    END IF;
[3] IF 条件 THEN
        code....;
   ELSIF 条件 THEN
        code...
    ELSE
        code....;
    END IF;

demo示例:

DECLARE
    v_date VARCHAR2(24);
BEGIN
    SELECT trim(to_char(SYSDATE, 'dy')) INTO v_date FROM dual;  -- 当天属于周几
    IF v_date IN ('sun', 'sat') THEN 
      dbms_output.put_line('在中国今天是周末哦!');
    ELSE
      dbms_output.put_line('在中国今天是工作日哦!');
    END IF;
END;

2.6循环(主要掌握loop)

语法

语法:
        [1] WHILE 条件 
          LOOP
            code...;
          END LOOP;
        [2] LOOP
              EXIT WHEN 条件
                   code....
              END LOOP;
        [3] FOR i IN 1...n
                LOOP
                  code...
                END LOOP;

demo示例1:

-- 输出1-10

-- 法一:
DECLARE
   v_tag NUMBER := 1;
BEGIN
   WHILE v_tag < 10
     LOOP
         dbms_output.put_line(v_tag);
         v_tag := v_tag + 1;
     END LOOP;
END;

-- 法二:
DECLARE
    v_tag NUMBER := 1;
BEGIN
    LOOP
      EXIT WHEN v_tag >= 10;
           dbms_output.put_line(v_tag);
           v_tag := v_tag + 1;
      END LOOP; 
END;

-- 法三:
DECLARE
      
BEGIN
      FOR i IN 1..10
        LOOP
          dbms_output.put_line(i);
        END LOOP;
END;

demo示例2:

要求:随机向demo表中添加一百条测试数据

declare
 v_int number(3,0) :=1;
 begin
   while 
     v_int<=100
     loop 
       insert into demo select v_int,'demo的name'||v_int from dual;
       commit;
       v_int :=v_int+1;
       dbms_output.put_line('helloworld'||v_int);
       end loop;
       end;

2.7游标

概念

在Java中有集合的概念,那么在plsql中也会有用到多条记录的情况,这时候我们就要用到游标。游标可以存储查询返回的多条数据。

  • 语法:
-- 语法:
   CURSOR 游标名 [(paramName paramType, ....)] IS SELECT 语句...;
  • 取值步骤
  1. 打开游标 open cursor
  2. 开启循环 loop;
  3. 取值 fetch 游标名称 into 变量名
  4. 结束循环 end loop;
  5. 关闭游标 close 游标名称
  • 示例

    • 示例一(普通游标)

      -- 使用游标方式输出员工编号和姓名
      DECLARE
         pemp emp%ROWTYPE;
         -- 定义游标
         CURSOR pc IS SELECT * FROM emp;
      BEGIN
         -- 打开游标
         OPEN pc;
         -- 取数据
         LOOP
            FETCH pc INTO pemp;
            EXIT WHEN pc%NOTFOUND;
            dbms_output.put_line(pemp.empno || '-' || pemp.ename);
         END LOOP;
      END;
      
    • 示例二(系统引用游标)推荐

      DECLARE
          mycursor1 SYS_REFCURSOR;
          vrow demo%ROWTYPE;
      BEGIN
          OPEN mycursor1 FOR SELECT * FROM demo;
              LOOP
              FETCH mycursor1 into vrow;
              EXIT WHEN mycursor1%NOTFOUND;--%notfound,游标中已经取到最后,没有数据了
                  dbms_output.put_line(' 员工姓名:' || vrow.name || ' demoid:' || vrow.id);  
              END LOOP;
          CLOSE mycursor1;
      END;
      

3.plsql函数

语法:

CREATE [OR REPLACE] FUNCTION

[(param1,param2)]

RETURN IS|AS

[local declarations]

BEGIN

excutable statements;

RETURN result;

EXCEPTION

exception handlers;

END;

入门demo

要求:求两个数的和

  • 新建一个函数
create or replace function add_func(a number, b number)
return number
is
begin
       return (a + b);
end;
  • 写测试
begin
  dbms_output.put_line(add_func(1,2));
  end;
  -- 控制台输出3
  • 在sql语句中使用plsql函数
select add_func(1,1) from dual;
-- 结果:2

4.测试oracle存储过程的crud

(1)insert

  • 建表
create table STUDENT

(

  sid    NUMBER,

  sname  VARCHAR2(20),

  sage   NUMBER,

  sgender VARCHAR2(20)

)
  • 创建存储过程

    • 第一种方式(可以使用,方便)

      create or replace procedure pro_addstudent
      
      (sid in student.sid%type,sname in student.sname%type , sage in student.sage%type,sgender in student.sgender%type)
      
      is
      
      begin
      
        insert into student (sid,sname,sage,sgender)values(sid,sname,sage,sgender);
      
      end;
      
    • 第二种方式(标准的方式)

      create or replace procedure pro_addstudent2
      
      (sid in number,sname in varchar2, sage in number,sgender in varchar2)
      
      is
      
      begin
      
        insert into student (sid,sname,sage,sgender)values(sid,sname,sage,sgender);
      
      end;
      

问题:

存储过程中是否要对增删改的业务进行提交事务?

答:是要提交事务的,否者数据添加不进去

说明:

第一种方式使用参数类型引用的是字段的数据类型

第二种方式是自己声明参数的类型

  • 测试存储过程
-- 测试  (第一种方式)
call pro_addstudent(1,'汉汉',23,'男');
Commit;
-- 测试  (第二种方式)
begin
  pro_addstudent(2,'小李1',23,'女');
end;
  • dao层的方法
void insertDemoByCunFun(Map<String, Object> map);
  • mapper.xml里面调用存储过程
<!-- void insertDemoByCunFun(Map<String,Object> map); -->
	<select id="insertDemoByCunFun" parameterType="java.util.Map">
	<![CDATA[
          {call pro_addstudent2(
          #{sid,mode=IN,jdbcType=DOUBLE},
          #{sname,mode=IN,jdbcType=VARCHAR},
          #{sage,mode=IN,jdbcType=DOUBLE},
          #{sgender,mode=IN,jdbcType=VARCHAR}
          )}
      ]]>
	</select>

说明:

书写要规范,否则存储过程调用会失败

<![CDATA[  ]]>  标签的使用可以解决存储过程不识别的问题
  • 测试方法
@Test
	public void  testcun2(){
	   /*
	    * #{sid,mode=IN,jdbcType=INTEGER},
          #{sname,mode=IN,jdbcType=VARCHAR},
           #{sage,mode=IN,jdbcType=INTEGER},
          #{sgender,mode=IN,jdbcType=VARCHAR},
          sid,sname,sage,sgender
	    */
	      Map<String, Object> mp = new HashMap<String, Object>();
	      mp.put("sid", 1.0);
	      mp.put("sname", "1111");
	      mp.put("sage", 2.0);
	      mp.put("sgender", "男");
	      demoDao.insertDemoByCunFun(mp);
	     
	  
	}
  • 控制台打印

​ 无

  • 进行验证
select * from student;
-- 1	1	1111	2	男

(2)select返回list集合

  • (1创建测试表
create table demo(id number(5,0),name varchar2(50));
  • (2使用plsql的存储过程或者不使用存储过程新建测试数据

    • 第一种方式:使用declare直接创建一百条测试数据
       declare 
       v_id number(5,0) := 1;
       begin
         while v_id<101
           loop
             insert into demo (id,name) values(v_id,'测试的demo数据'||v_id);
             commit;
             v_id :=v_id+1;
             dbms_output.put_line('demo的id为: '||v_id||', demo的name为:  '||'测试的demo数据'||v_id);
            end loop;
             end;
    
    • 第二种方式:使用存储过程,直接调用存储过程

      • 创建存储过程
      create or replace procedure insert_sometestdata is
      begin
        for i in 1 ..100 loop
          insert into demo(id,name) values(i, '测试的demo数据'||i);
          commit;
          end loop;
      end insert_sometestdata;
      
      • 调用存储过程插入数据
       call insert_sometestdata();
      
    • mybatis调用存储过程创建创建测试数据

      • dao层的方法
       //使用存储过程创建一百条测试数据
      	void insertOneHundredDataByCun();
      
      • mapper.xml
      <!--  //使用存储过程创建一百条测试数据
      	void insertOneHundredDataByCun(); -->
      	<select id="insertOneHundredDataByCun" statementType="CALLABLE">
      	<![CDATA[
      		{call insert_sometestdata(
      		)}
      		]]>
      	</select>
      
      • 测试方法进行添加
      /**
      	 * mybatis调用存储过程插入一百条数据
      	 */
      	@Test
      	public void testinsertOneHundredDataByCun() {
      		demoDao.insertOneHundredDataByCun();
      		
      	}
      	
      
  • (3 创建存储过程

create or replace procedure demo_List (v_id in number,v_cursor out sys_refcursor) is
begin
  open v_cursor for select * from demo where id < v_id;
end ;
  • (4 dao层方法
//并接收返回值(游标类型)
	List<Map<String,Object>> queryByCuncursor(Map<String,Object> map);
  • (5 mapper.xml
<resultMap type="com.fcmap.ssm.domain.Demo" id="demo_rp">
		<result column="id" property="id" />
		<result column="name" property="name" />
	</resultMap>
<!-- List<Map<String,Object>> queryByCuncursor(Map<String,Object> map); -->
	<select id="queryByCuncursor" parameterType="java.util.HashMap"
		statementType="CALLABLE">
		<![CDATA[
		{call demo_List(
		#{v_id,mode=IN,jdbcType=INTEGER},#{result,mode=OUT,
		jdbcType=CURSOR,javaType=ResultSet,resultMap=demo_rp}
		)}
		]]>
	</select>
  • (6 测试方法查询结果集
@Test
	public void testCunreturnCursor() {
		Map<String, Object> map = new HashMap<String,Object>();
		map.put("v_id",10);
		map.put("result", OracleTypes.CURSOR);
		demoDao.queryByCuncursor(map);
		List<Demo> demoList= (List<Demo>) map.get("result");
		System.out.println(demoList);
		
	}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值