PL/SQL练习题目

1 参照变量

--参照变量是指用于存放数值指针的变量(游标的使用)
declare
    -- 游标类型定义,不同于变量
    type sp_emp_cursor is ref cursor;
    -- 定义游标变量
    v_emp sp_emp_cursor;
    --普通变量
    v_ename emp.ename%type;
    v_sal emp.sal%type;
begin
    -- 打开游标(让游标指向了结果集)
    open v_emp for select ename,sal from emp where deptno=&no;
    -- 循环遍历游标指向的值
    loop
        -- 遍历数据
        fetch v_emp into v_ename,v_sal;
        -- 结束条件
        exit when v_emp%notfound;
        -- 输出
        dbms_output.put_line(v_ename || ',' || v_sal);
        end loop;
end;

2 游标

-- 游标基础语法:维护查询结果的内存中的一个区域;%rowcount遍历计数 %isopen 游标是否打开
declare
    -- 创建游标
    cursor emp_cursor is select ename,sal from emp where deptno=&no;
    -- 定义表的行类型变量,此处的表用的游标
    v_emp_row emp_cursor%rowtype;
begin
    -- 打开游标
    open emp_cursor;
    if emp_cursor%isopen then
        dbms_output.put_line('游标已打开');
    end if;
    loop
        fetch emp_cursor into v_emp_row;
        exit when emp_cursor%notfound;
        dbms_output.put_line(v_emp_row.ename || ',' || v_emp_row.sal);
    end loop;
    -- 关闭游标
    close emp_cursor;
end;

/*
在员工表中有 sal(薪水列),实现按员工编号排序,并实现工资不断累加,输出如
下效果:
员工 id, 员工名称, 薪水, 累加薪水
1 A 800 800
2 B 500 1300
3 C 1000 2300
..........
要求创建一个存储过程,使用游标的方式实现
*/
create or replace procedure add_pro is
    cursor emp_cursor is select empno,ename,sal,comm from emp order by empno for update;
    v_empno emp.empno%type;
    v_ename emp.ename%type;
    v_sal emp.sal%type;
    v_comm emp.comm%type;
    v_sum number; --累计工资
begin
    v_sum :=0;
    open emp_cursor;
    loop
        fetch emp_cursor into v_empno,v_ename,v_sal,v_comm;
        v_sum := v_sum+v_sal;
        v_comm := v_sum;
        exit when emp_cursor%notfound;
        dbms_output.put_line(v_empno||','||v_ename||','||v_sal||','||v_comm);
    end loop;
    close emp_cursor;
end;
-- 设置输出显示
set serveroutput on;
-- 过程调用
call add_pro();

3 触发器

/*
在 oracle11g 数据库中创建 D 表,复制 dept 表的结构和数据,创建 E 表复制 emp表的结构和数据。
创建触发器,当对 D 表中的部门编号 deptno 中的值进行修改时,触发器将 E 表中对应部门编号进行修改;
当删除 D 表中某一条数据信息时,触发器会将 E 表部门编号与 D 表中删除数据部门编号相等的数据删除。
*/

-- 复制表结构和数据
create table D as select * from dept;  
create table E as select * from emp; 
/* 
不管是after ,还是 before  在update、insert、delete 时,一定是在事务提交之后才会触发触发器 
before 和after的区别:before、insert、update可以对new进行修改;after不能对new 进行修改;二者都不能对old 进行修改 
*/
-- 创建触发器
create or replace trigger update_d
after
    -- 行触发器for each row和语句触发器:行触发器要求当一个DML语句操作影响数据库中的多行数据时,对于其中的每个数据行,只要它们符合触发约束条件,均激活一次触发器
    insert or update or delete on D for each row
begin
    -- 更新的时候有new和old
    if updating then
        update E e1 set e1.deptno=:new.empno where e1.empno=:old.empno;
    -- 删除时只有old值
    elsif deleting then
        delete from E e2 where e2.Deptno = :old.Deptno;
    end if;
end update_d;

4 过程

-- 过程:无返回值
create or replace procedure update_sal(v_ename varchar2,v_sal number) is
begin
    update emp set sal=v_sal where ename=v_ename;
    commit;
end;

-- 调用
call update_sal('SCOTT',123);

-- 查看过程是否执行成功
select * from emp;

5 函数

--函数:用于返回特定的数据,当建立函数时,在函数头部必须包含return字句
create or replace function get_sal(v_ename varchar2) return number is
-- 接收返回值
v_sal number;
begin
    select sal into v_sal from emp where ename=v_ename;
    return v_sal;
end;
/*
sqlplus中调用函数:
SQL> var sal number;
SQL> call get_sal('SMITH') into:sal;

调用完成。

SQL> print sal;

       SAL
----------
       800
*/

6 包

-- 包:用于在逻辑上组合过程和函数(类似于接口)
-- 创建包
create package sp_package is
    procedure update_sal(v_ename varchar2,v_sal number);
    function get_sal(v_ename varchar2) return number;
end;
-- 实现包体
create or replace package body sp_package is
    -- 过程/函数实现
end;
-- sqlplus中调用包中过程/函数
call sp_package.update_sal('SCOTT',1500);

7 复合类型 

-- 1 标量 即常亮,使用:=赋值 2 声明未知类型的变量:%type 3 复合类型(类比泛型、结构体理解)4 %rowtyp行类型
declare
    type emp_record_type is record(
        v_sal emp.sal%type,
        v_empno emp.empno%type
    );
    v_record emp_record_type;
    -- v_record scott.emp%roetype
begin
    select sal,empno into v_record from emp where ename='SMITH';
    dbms_output.put_line(v_record.v_sal || ',' || v_record.v_empno);
end;

set serveroutput on
begin
dbms_output.put_line('hello');
end;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值