oracle - 存储过程学习笔记

1.在存储过程/包中如何启用并行

如果需要执行alter session,则需要用动态语句执行,如:execute immediate ‘alter session enable parallel dml’;

2.TRUNCATE TABLE

1.在功能上与不带 WHERE 子句的 DELETE 语句相同;
2. 二者均删除表中的全部行;
3. 但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少。
4. DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一项;
5. TRUNCATE TABLE 通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放;
6. TRUNCATE TABLE 删除表中的所有行,但表结构及其列、约束、索引等保持不变;
7.新行标识所用的计数值重置为该列的种子。如果想保留标识计数值,请改用 DELETE;
8. 如果要删除表定义及其数据,请使用 DROP TABLE 语句;
9.对于由 FOREIGN KEY 约束引用的表,不能使用 TRUNCATE TABLE,而应使用不带 WHERE 子句的 DELETE 语句;
10.由于 TRUNCATE TABLE 不记录在日志中,所以它不能激活触发器;
11.TRUNCATE TABLE 不能用于参与了索引视图的表;

3.+parallel(t,n)

t代表表别名或者表名(没有起别名情况);
n代表进程数量。

4.NVL函数

NVL函数的格式如下:NVL(expr1,expr2);
含义是:如果oracle第一个参数为空那么显示第二个参数的值,如果第一个参数的值不为空,则显示第一个参数本来的值。

5.数字式循环

FOR 循环计数器 IN [ REVERSE ] 下限 … 上限 LOOP
要执行的语句;
END LOOP;

每循环一次,循环变量自动加 1;使用关键字 REVERSE,循环变量自动减 1。

例题:

BEGIN
FOR int in 1…10 LOOP
DBMS_OUTPUT.PUT_LINE('int 的当前值为: '||int);
END LOOP;
END;

6.存储过程格式

CREATE [OR REPLACE] PROCEDURE Procedure_name
[ (argment [ { IN | IN OUT }] Type,
argment [ { IN | OUT | IN OUT } ] Type ]
[ AUTHID DEFINER | CURRENT_USER ]
{ IS | AS }
<类型.变量的说明>
BEGIN
<执行部分>
EXCEPTION
<可选的异常错误处理程序>
END;

7. 遇到的问题

  • 使用PL/SQL写存储过程,使用 dbms_output.PUT_LINE(bc_date_from);语句打印信息,但是看不到打印出来的信息在哪。如何查看呢?
    答:如果是PL/SQL的工具的话,使用‘SQL窗口’,结果在你执行SQL的小窗体的左上角有一个‘OutPut’窗体里面;
    如果使用的命令行的话,你得先设置允许显示输出类似dbms_output,命令如下:
    SQL>set serveroutput on;

8.流程控制

declare
v_sal employees.salary%type;
begin
select salary into v_sal from employees where employee_id=150;
if v_sal >=10000 then dbms_output.put_line(‘salary>=10000’);
elsif v_sal >=5000 then dbms_output.put_line(‘10000>salary>=5000’);
else dbms_output.put_line(‘salary<5000’);
end if;
end;

declare
v_sal employees.salary%type;
v_temp varchar2(30);
begin
select salary into v_sal from employees where employee_id=150;
if v_sal >=10000 then v_temp := ‘salary>=10000’;
elsif v_sal >=5000 then v_temp := ‘10000>salary>=5000’;
else v_temp := ‘salary<5000’;
end if;
dbms_output.put_line(v_sal||’,’||v_temp);
end;

9.Oracle中的dual

1.dual是Oracle中的一个伪表,利用这个伪表可以设置或查看序列,或者是调用一些内置的函数,方便操作。
2.dual表就是oracle与数据字典自动创建的一张表,这张表是一个单行单列的表,这个表只有1列:DUMMY,数据类型为VERCHAR2(1),dual表中只有一个数据’X’, Oracle有内部逻辑保证dual表中永远只有一条数据。dual表主要是用来选择系统变量或是求一个表达式的值。
比如:
求系统当前时间
SELECT sysdate FROM daul
按位数四舍五入
select round(1.25,1) from dual;------1.3

10.游标的使用

10.1 使用游标

  • 打印出 80 部门的所有的员工的工资:salary: xxx

declare
–1. 定义游标
cursor salary_cursor is select salary from employees where department_id = 80;
v_salary employees.salary%type;
begin
–2. 打开游标
open salary_cursor;

–3. 提取游标
fetch salary_cursor into v_salary;

–4. 对游标进行循环操作: 判断游标中是否有下一条记录
while salary_cursor%found loop
dbms_output.put_line('salary: ’ || v_salary);
fetch salary_cursor into v_salary;
end loop;

–5. 关闭游标
close salary_cursor;
end;

10.2 使用游标

-== 打印出 80 部门的所有的员工的工资: Xxx 's salary is: xxx==

declare
  cursor sal_cursor is select salary ,last_name from employees where department_id = 80;
  v_sal number(10);
  v_name varchar2(20);
begin
  open sal_cursor;
  
  fetch sal_cursor into v_sal,v_name;
  
  while sal_cursor%found loop
        dbms_output.put_line(v_name||'`s salary is '||v_sal);
        fetch sal_cursor into v_sal,v_name;
  end loop;
  
  close sal_cursor;
  
end;

10.3. 使用游标的练习:
打印出 manager_id 为 100 的员工的 last_name, email, salary 信息(使用游标, 记录类型)

declare
–声明游标
cursor emp_cursor is select last_name, email, salary from employees where manager_id = 100;

       --声明记录类型
       type emp_record is record(
            name employees.last_name%type,
            email employees.email%type,
            salary employees.salary%type
       );
       
       -- 声明记录类型的变量
       v_emp_record emp_record;

begin
–打开游标
open emp_cursor;

       --提取游标
       fetch emp_cursor into v_emp_record;
       
       --对游标进行循环操作
       while emp_cursor%found loop
              dbms_output.put_line(v_emp_record.name || ', ' || v_emp_record.email || ', ' || v_emp_record.salary );                
              fetch emp_cursor into v_emp_record;
       end loop;
       
       --关闭游标
       close emp_cursor;

end;
(法二:使用for循环)
declare

  cursor emp_cursor is 
  select last_name,email,salary
  from employees
  where manager_id = 100;

begin

  for v_emp_record in emp_cursor loop
      dbms_output.put_line(v_emp_record.last_name||','||v_emp_record.email||','||v_emp_record.salary);
  end loop;

end;

  1. 利用游标, 调整公司中员工的工资:

    工资范围 调整基数
    0 - 5000 5%
    5000 - 10000 3%
    10000 - 15000 2%
    15000 - 1%

declare
–定义游标
cursor emp_sal_cursor is select salary, employee_id from employees;

--定义基数变量
temp number(4, 2);

--定义存放游标值的变量
v_sal employees.salary%type;
v_id employees.employee_id%type;

begin
–打开游标
open emp_sal_cursor;

--提取游标
fetch emp_sal_cursor into v_sal, v_id;

--处理游标的循环操作
while emp_sal_cursor%found loop
      --判断员工的工资, 执行 update 操作
      --dbms_output.put_line(v_id || ': ' || v_sal);
        
      if v_sal <= 5000 then
         temp := 0.05;
      elsif v_sal<= 10000 then
         temp := 0.03;   
      elsif v_sal <= 15000 then
         temp := 0.02;
      else
         temp := 0.01;
      end if;
      
      --dbms_output.put_line(v_id || ': ' || v_sal || ', ' || temp);
      update employees set salary = salary * (1 + temp) where employee_id = v_id; 
              
      fetch emp_sal_cursor into v_sal, v_id;
end loop;
--关闭游标
close emp_sal_cursor;

end;

使用SQL中的 decode 函数

update employees set salary = salary * (1 + (decode(trunc(salary/5000), 0, 0.05,
1, 0.03,
2, 0.02,
0.01)))

  1. 利用游标 for 循环完成 14.

declare
–定义游标
cursor emp_sal_cursor is select salary, employee_id id from employees;

--定义基数变量
temp number(4, 2);

begin
–处理游标的循环操作
for c in emp_sal_cursor loop
–判断员工的工资, 执行 update 操作
–dbms_output.put_line(v_id || ': ’ || v_sal);

      if c.salary <= 5000 then
         temp := 0.05;
      elsif c.salary <= 10000 then
         temp := 0.03;   
      elsif c.salary <= 15000 then
         temp := 0.02;
      else
         temp := 0.01;
      end if;
      
      --dbms_output.put_line(v_id || ': ' || v_sal || ', ' || temp);
      update employees set salary = salary * (1 + temp) where employee_id = c.id;
end loop;

end;

16*. 带参数的游标

declare
–定义游标
cursor emp_sal_cursor(dept_id number, sal number) is
select salary + 1000 sal, employee_id id
from employees
where department_id = dept_id and salary > sal;

--定义基数变量
temp number(4, 2);

begin
–处理游标的循环操作
for c in emp_sal_cursor(sal => 4000, dept_id => 80) loop
–判断员工的工资, 执行 update 操作
–dbms_output.put_line(c.id || ': ’ || c.sal);

      if c.sal <= 5000 then
         temp := 0.05;
      elsif c.sal <= 10000 then
         temp := 0.03;   
      elsif c.sal <= 15000 then
         temp := 0.02;
      else
         temp := 0.01;
      end if;
      
      dbms_output.put_line(c.sal || ': ' || c.id || ', ' || temp);
      --update employees set salary = salary * (1 + temp) where employee_id = c.id;
end loop;

end;

  1. 隐式游标: 更新指定员工 salary(涨工资 10),如果该员工没有找到,则打印”查无此人” 信息

begin
update employees set salary = salary + 10 where employee_id = 1005;

     if sql%notfound then
        dbms_output.put_line('查无此人!');
     end if;

end;

11.触发器

  • helloworld级别的触发器
create or replace trigger hello_trigger
 after 
update on employees
--for each row
begin 
 dbms_output.put_line('hello...');
 --dbms_output.put_line('old.salary:'|| :OLD.salary||',new.salary'||:NEW.salary);
end;

然后执行:

update employees set salary =  salary + 1000;
  • 行级触发器: 每更新 employees 表中的一条记录, 都会导致触发器执行:
create or replace trigger employees_trigger
after 
update on employees
for each row
begin
       dbms_output.put_line('修改了一条记录!');
end;
  • 语句级触发器: 一个 update/delete/insert 语句只使触发器执行一次:
create or replace trigger employees_trigger
after 
update on employees
begin
       dbms_output.put_line('修改了一条记录!');
end;

  • 使用 :new, :old 修饰符:
create or replace trigger employees_trigger
after 
update on employees
for each row
begin
       dbms_output.put_line('old salary: ' || :old.salary || ', new salary: ' || :new.salary);
end;
  • 编写一个触发器, 在对 my_emp 记录进行删除的时候, 在 my_emp_bak 表中备份对应的记录

1). 准备工作:

create table my_emp as select employee_id id, last_name name, salary sal from employees
create table my_emp_bak as select employee_id id, last_name name, salary sal from employees where 1 = 2

2).

create or replace trigger bak_emp_trigger
       before delete on my_emp
       for each row
       
begin
       insert into my_emp_bak values(:old.id, :old.name, :old.sal);
end; 
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值