zoukankan      html  css  js  c++  java
  • PL/SQL练习

    简单结构

    set serveroutput on;
    
    DECLARE 
      v_name varchar2(20);
    BEGIN
      v_name := 'hello';
      dbms_output.put_line(v_name);
    END;
    
    /

    异常处理:

    declare
    v_num number :=0;
    begin
    v_num := 2/v_num;
    dbms_output.put_line('devide function...');
    exception
    when others then
    dbms_output.put_line('error....devide by'||v_num);
    end;
    
     /

    引用类型

    declare
    v_empno number(4);
    --v_ename变量使用emp表ename字段的类型
    v_ename emp.ename%type;
    v_sal emp.sal%type;
    begin
    v_sal := 1000.123;
    dbms_output.put_line(v_sal);
    exception
    when others then
    dbms_output.put_line('error....');
    end;

    复合类型:

    数组:table

    declare
    --声明一个table类型(看做数组),数组的值是emp表empno字段的类型,数组下标是binary——integer类型
    type type_a is table of emp.empno%type index by binary_integer;
    --声明一个type——a类型的数组
    v_table_empno type_a;
    begin
    
    --下标可以为负数
    
    v_table_empno(-1) := 1000;
    v_table_empno(0) := 0000;
    v_table_empno(1) := 1000;
    v_table_empno(2) := 2000;
    dbms_output.put_line('打印数组第二个值:'||v_table_empno(2));
    exception
    when others then
    dbms_output.put_line('error....');
    end;

    对象:record

    declare
    --声明一个对象record,各个成员变量引用dept表的类型
    type type_record_dept is record(
    deptno dept.deptno%type,
    dname dept.dname%type,
    loc dept.loc%type
    );
    --声明上述类对应的一个对象
    v_temp type_record_dept;
    begin
    --给对象赋值:
    v_temp.deptno := 50;
    v_temp.dname := 'dname---';
    v_temp.loc := 'beijing';
    dbms_output.put_line('打印v_temp对象:'||v_temp.deptno||', '||v_temp.dname||', '||v_temp.loc );
    exception
    when others then
    dbms_output.put_line('error....');
    end;

    使用rowtype声明一个record对象:

    declare
    --声明一个对象record,她的所有字段同emp所有字段
    v_emp emp%rowtype;
    begin
    --给对象赋值:
    v_emp.empno := 1111;
    v_emp.ename := 'sansan';
    dbms_output.put_line('打印v_temp对象:'||v_emp.empno||', '||v_emp.ename);
    exception
    when others then
    dbms_output.put_line('error....');
    end;

    select into

    declare
    --声明
    v_ename emp.ename%type;
    v_deptno emp.deptno%type;
    begin
    --给对象赋值,不用游标时这个select语句只能返回一条,而且必须返回一条数据
    select ename,deptno into v_ename,v_deptno from emp where empno = 7369;
    dbms_output.put_line('打印v_temp对象:'||v_ename||', '||v_deptno);
    end;

    执行DDL语句:execute immediate 

    begin
    
    --引号中,两个单引号代替一个单引号
    execute immediate 'create table ttt(id varchar2(20),name varchar2(10) default ''sansan'')';
    end;
    

    分支判定:薪水小于1000加倍,大于则减半

    declare
    --声明
    v_ename emp.ename%type;
    v_sal emp.sal%type;
    begin
    --给对象赋值,不用游标时这个select语句只能返回一条,而且必须返回一条数据
    select ename,sal into v_ename,v_sal from emp where empno = 1111;
    if(v_sal < 1000) then
    update emp set sal = sal*2 where empno=1111;
    dbms_output.put_line('小于1000,加倍。。');
    elsif(v_sal = 1000 )then
    dbms_output.put_line('等于1000。。');
    else
    update emp set sal = sal/2 where empno=1111;
    dbms_output.put_line('大于1000,减半。。');
    end if;
    commit;
    end;
    
     

    循环

    --dowhile

    declare
    --声明
    i binary_integer := 1;
    begin
    loop
    dbms_output.put_line('第i='||i);
    i := i+1;
    exit when(i>=5);
    end loop;
    end;

    --while

    declare
    --声明
    i binary_integer := 1;
    begin
    while (i < 5) loop
    dbms_output.put_line('第i='||i);
    i := i+1;
    end loop;
    end;

    --for 循环

    declare
    --声明
    i binary_integer := 1;
    begin
    --顺序循环
    for k in 1..5 loop
    dbms_output.put_line('第k='||k);
    end loop;
    
    --逆序循环
    for k in reverse 1..5 loop
    dbms_output.put_line('第k='||k);
    end loop;
    end;

    异常处理:

    declare
    --声明
    v_ename emp.ename%type;
    v_deptno emp.deptno%type;
    begin
    --给对象赋值,不用游标时这个select语句只能返回一条,而且必须返回一条数据
    select ename,deptno into v_ename,v_deptno from emp where deptno=10;
    dbms_output.put_line('打印v_temp对象:'||v_ename||', '||v_deptno);
    exception 
    --可以把这些异常记录在一张异常表中
    when too_many_rows then
    dbms_output.put_line('异常:记录数大于一条。。。'||SQLCODE||SQLERRM);
    when no_data_found then
    dbms_output.put_line('异常:没有记录。。。'||SQLCODE||SQLERRM);
    when others then
    dbms_output.put_line('其他异常。。。'||SQLCODE||SQLERRM);
    end;

    游标

    declare
    --声明一个游标,不会真正取数据
    cursor c is
    select * from emp;
    --声明一个record
    v_each c%rowtype;
    begin
    --打开游标,执行语句。游标指向第一条记录
    open c;
    --把游标指向的数据拿到v_each中,游标自动向下移动一个
    fetch c into v_each;
    dbms_output.put_line(v_each.ename);
    --关闭游标
    close c;
    exception 
    when others then
    dbms_output.put_line('其他异常。。。'||SQLCODE||SQLERRM);
    end;

    --带参数的游标

    declare
    --声明一个游标,不会真正取数据
    cursor c(v_deptno emp.deptno%type, v_job emp.job%type) is
    select * from emp where deptno=v_deptno and job=v_job;
    --声明一个record
    v_each c%rowtype;
    begin
    --for循环会自动打开游标,把游标指向的数据拿到v_each中,游标自动向下移动一个
    for v_each in c(30,'SALESMAN') loop
    dbms_output.put_line(v_each.ename);
    end loop;
    --for循环会自动关闭游标
    exception 
    --可以把这些异常记录在一张异常表中
    when others then
    dbms_output.put_line('其他异常。。。'||SQLCODE||SQLERRM);
    end;

    --循环遍历游标

    --for循环

    declare
    --声明一个游标,不会真正取数据
    cursor c is
    select * from emp;
    --声明一个record
    v_each c%rowtype;
    begin
    --打开游标,执行语句。游标指向第一条记录
    --for循环会自动打开游标
    --open c;
    --for循环自动把游标指向的数据拿到v_each中,游标自动向下移动一个
    for v_each in c loop
    dbms_output.put_line(v_each.ename);
    end loop;
    --for循环会自动关闭游标
    --close c;
    exception 
    --可以把这些异常记录在一张异常表中
    when others then
    dbms_output.put_line('其他异常。。。'||SQLCODE||SQLERRM);
    end;

    --while循环

    declare
    --声明一个游标,不会真正取数据
    cursor c is
    select * from emp;
    --声明一个record
    v_each c%rowtype;
    begin
    --打开游标,执行语句。游标指向第一条记录
    open c;
    --把游标指向的数据拿到v_each中,游标自动向下移动一个
    fetch c into v_each;
    --如果找找记录,继续向下执行
    while(c%found) loop
    dbms_output.put_line(v_each.ename);
    --游标向后移动
    fetch c into v_each;
    end loop;
    --关闭游标
    close c;
    exception 
    --可以把这些异常记录在一张异常表中
    when others then
    dbms_output.put_line('其他异常。。。'||SQLCODE||SQLERRM);
    end;

    --dowhile循环

    declare
    
    --声明一个游标,不会真正取数据
    cursor c is
    select * from emp;
    --声明一个record
    --v_each c%rowtype;
    begin
    --打开游标,执行语句。游标指向第一条记录
    open c;
    --把游标指向的数据拿到v_each中,游标自动向下移动一个,自动声明v_each变量
    loop
    fetch c into v_each;
    
    --最近的一条记录没有返回记录,退出
    exit when(c%notfound);
    
    dbms_output.put_line(v_each.ename);
    end loop;
    --关闭游标
    close c;
    exception 
    --可以把这些异常记录在一张异常表中
    when others then
    dbms_output.put_line('其他异常。。。'||SQLCODE||SQLERRM);
    end;

    存储过程:

    create or replace procedure ppp is替代declare,其他的一样。

    执行用exec ppp;

    或者:

    begin

    ppp;

    end;

    /

    简单存储过程

    --带参数的游标演示存储过程
    create or replace procedure ppp is
    --声明一个游标,不会真正取数据
    cursor c(v_deptno emp.deptno%type, v_job emp.job%type) is
    select * from emp where deptno=v_deptno and job=v_job;
    --声明一个record
    v_each c%rowtype;
    begin
    --for循环会自动打开游标,把游标指向的数据拿到v_each中,游标自动向下移动一个
    for v_each in c(30,'SALESMAN') loop
    dbms_output.put_line(v_each.ename);
    end loop;
    --for循环会自动关闭游标
    exception 
    --可以把这些异常记录在一张异常表中
    when others then
    dbms_output.put_line('其他异常。。。'||SQLCODE||SQLERRM);
    end;



    带参数的存储过程:

    create or replace procedure ppp2(v_a in number, v_b number, v_c out number,v_d in out number) is
    --三个参数,传入、传出、传入/传出三种类型。存储过程没有返回值。没有写默认是in
    v_temp number := 5;
    begin
    if(v_a > v_b)then
       v_c := v_a;
       v_d := v_c*100;
    elsif(v_a < v_b)then
       v_c := v_b;
       v_d := v_c*10;
    end if;
    exception 
    --可以把这些异常记录在一张异常表中
    when others then
    dbms_output.put_line('其他异常。。。'||SQLCODE||SQLERRM);
    end;

    调用带参数的存储过程:

    declare
    c number;
    d number := 10;
    begin
    ppp2(v_a => 2,v_b => 1,v_c => c,v_d => d);
    dbms_output.put_line('c:'||c||'d:'||d);
    end;
    --函数有返回值,存储过程没有返回值
    create or replace function sal_tax(v_sal number) return number is
    begin
      if(v_sal < 3000) then
          return 0;
        elsif(v_sal < 5000) then
          return v_sal*0.1;
        else
          return v_sal*0.2;
      end if;
     end;

    调用:

    select sal, sal_tax(sal) from emp;

     

     综合使用的例子:

    create table departments(
        DEPARTMENT_ID NUMBER(4) primary key,
        DEPARTMENT_NAME VARCHAR2(30),
        MANAGER_ID NUMBER(6),
        LOCATION_ID NUMBER(4)
        );
    
    insert into departments values(1,'技术部',1,1);
    insert into departments values(2,'人事部',2,2);
    insert into departments values(3,'市场部',3,3);
    insert into departments values(4,'财务部',4,4);
    create table employees(
        EMPLOYEE_ID NUMBER(6) primary key,
        FIRST_NAME VARCHAR2(20),
        LAST_NAME VARCHAR2(25),
        EMAIL VARCHAR2(25),
        PHONE_NUMBER VARCHAR2(20),
        HIRE_DATE DATE,
        JOB_ID VARCHAR2(10),
        SALARY NUMBER(8,2),
        COMMISSION_PCT NUMBER(2,2),
        DEPARTMENT_ID NUMBER(4) references departments(DEPARTMENT_ID)
        );
    
    insert into employees(EMPLOYEE_ID,FIRST_NAME,LAST_NAME,SALARY,DEPARTMENT_ID) values(1,'JIA','JENNY',3000,1);
    insert into employees(EMPLOYEE_ID,FIRST_NAME,LAST_NAME,SALARY,DEPARTMENT_ID) values(2,'guan','rose',4000,3);
    insert into employees(EMPLOYEE_ID,FIRST_NAME,LAST_NAME,SALARY,DEPARTMENT_ID) values(3,'xu','mike',2000,2);
    insert into employees(EMPLOYEE_ID,FIRST_NAME,LAST_NAME,SALARY,DEPARTMENT_ID) values(4,'zhang','billy',1000,2);
    insert into employees(EMPLOYEE_ID,FIRST_NAME,LAST_NAME,SALARY,DEPARTMENT_ID) values(5,'jin','dede',5000,1);

    声明一个存储过程,输入工资数sal,小于sal则+1,小于sal+1000则不变,大于则-1.

    CREATE OR REPLACE PROCEDURE changeSal(sal in number,cnt out number)IS
      --定义一个EMPLOYEES表对应的类型
      eachOne EMPLOYEES%ROWTYPE;
      --定义一个record
      TYPE type_record IS RECORD(
        ename varchar2(45),
        sal EMPLOYEES.SALARY%type
      );
      --定义一个上述record类型的对象
      temp type_record;
      --定义一个数字
      total NUMBER := 0;
      --定义一个游标
      CURSOR c IS select * from employees;
    BEGIN
      OPEN c;
      --读取游标第一个值,游标向后移动
      fetch c into eachOne;
      dbms_output.put_line('存储过程正在执行,小于'||sal||'的薪水+1,小于'||(sal+1000)||'的薪水不变,大于的-1...');
      while(c%found)loop
        --拼接名字全称
        temp.ename := eachOne.first_name||eachOne.last_name;
        --变化薪水
        if (eachOne.salary < sal)then
          --变化了,计数
          total := total+1;
          temp.sal := eachOne.salary + 1;
        elsif(eachOne.salary < sal+1000)then
          temp.sal := eachOne.salary;
        else
          --变化了,计数
          total := total+1;
          temp.sal := eachOne.salary -1;
        end if;
        dbms_output.put_line('名字全称:'||temp.ename||', 变化后的薪水:'||temp.sal);
        --游标向后移动
        fetch c into eachOne;
      end loop;
      CLOSE c;
      cnt := total;
     END;--END PROCEDURE

    调用:

    declare
    cnt1 number;
    begin
    changeSal(sal => 2000,cnt=>cnt1);
    dbms_output.put_line('变化的结果:'||cnt1);
    end;

    结果:

    SQL> declare
      2  cnt1 number;
      3  begin
      4  changeSal(sal => 2000,cnt=>cnt1);
      5  dbms_output.put_line('变化的结果:'||cnt1);
      6  end;
      7  /
    存储过程正在执行,小于2000的薪水+1,小于3000的薪水不变,大于的-1...
    名字全称:JIAJENNY, 变化后的薪水:2999
    名字全称:guanrose, 变化后的薪水:3999
    名字全称:xumike, 变化后的薪水:2000
    名字全称:zhangbilly, 变化后的薪水:1001
    名字全称:jindede, 变化后的薪水:4999
    变化的结果:4
    PL/SQL procedure successfully completed
  • 相关阅读:
    牛客算法周周练2
    牛客算法周周练2
    2020年7月7日Java学习日记
    2020年7月6日Java学习日记
    练习29--if语句
    练习28--布尔练习
    练习27--记忆逻辑
    第18~19讲课后作业
    第20讲:内嵌函数和闭包
    练习25--更多更多练习
  • 原文地址:https://www.cnblogs.com/radio/p/3295991.html
Copyright © 2011-2022 走看看