Oracle数据库——PL/SQL程序设计语言

PL/SQL

PL/SQL 是一种高级数据库程序设计语言,该语言专门用于在各种环境下对 ORACLE 数据库进行访问 。由于该语言 集成于数据库服务器中 所以 PL/SQL 代码可以对数据进行快速高效的处理。
PL/SQL是Procedure Language & Structured Query Langu age 的缩写,是一种过程处理语言。 PL/SQL是对 SQL 语言存储过程语言的扩展语言的过程化扩展,指在 SQL 命令语言中增加了过程处理语句(如分支、循环等),使 SQL 语言具有过程处理能力。把 SQL 语言的数据操纵能力与过程语言的数据处理能力结合起来,使得 PLSQL 面向过程但比过程语言简单、高效、灵活和实用。 从 ORACLE6 以后, ORACLE 的 RDBMS 附带了 PL/SQL 。

PL/SQL块:
PL/SQL程序由三个块组成,即声明部分、执行部分、异常处理部分
PL/SQL块的结构如下
DECLARE
声明部分 : 在此声明 PL/SQL 用到的变量 类型及游标,以及局部的存储过程和函数
BEGIN
执行部分 : 过程及 SQL 语句 , 即程序的主要部分
EXCEPTION
执行异常部分 : 错误处理
END;
其中执行部分是必须的。

变量

声明变量的语法
变量名 类型(长度);
比如number(5,2)
3表示这个数据的有效位数(精度),2表示两个小数位(刻度)
例如:123.45

变量赋值的语法

  1. 变量名 := 变量值;
  2. select 列名 into 变量名
    一般要求被赋值的变量与SELECT 中的列名要一一对应 。
--变量声明与赋值
declare
  v_price number(10,2);--单价
  v_usenum number;--水费字数
  v_usenum2 number(10,2);--吨数
  v_money number(10,2);--金额

begin
  v_price:=2.45;--单价赋值
  v_usenum:=8953;--水费字数
  v_usenum2:=round(v_usenum/1000,2);--吨数
  v_money:=v_price*v_usenum2;--金额
  
  DBMS_OUTPUT.put_line('金额:'||v_money);
  
end;

--select 列名 into  变量名
declare
  v_price number(10,2);--单价
  v_usenum number;--水费字数
  v_usenum2 number(10,2);--吨数
  v_money number(10,2);--金额
  v_num0 number;--上月水表数
  v_num1 number;--本月水表数
begin
  v_price:=2.45;--单价赋值
  --v_usenum:=8953;--水费字数
  --从数据库中查询
  select usenum,v_num0,v_num1 into v_usenum,v_num0,v_num1  from t_account
  where year = '2012' and month='01' and owneruuid=1;
  
  v_usenum2:=round(v_usenum/1000,2);--吨数
  v_money:=v_price*v_usenum2;--金额
  
  DBMS_OUTPUT.put_line('水费字数:'||v_usenum||' 金额:'||v_money);
  
end;

属性类型

属性类型

  1. %TYPE引用型
    作用:引用某表某列的字段类型
    使用%TYPE 特性的优点在于:
    所引用的数据库列的数据类型可以不必知道;
    所引用的数据库列的数据类型可以实时改变。
  2. %ROWTYPE 记录型
    作用: 标识某个表的行记录类型
    使用%ROWTYPE 特性的优点在于:
    所引用的数据库中列的个数和数据类型可以不必知道;
    所引用的数据库中列的个数和数据类型可以实时改变。
--属性类型(引用型 表名.列名%type)
declare
  v_price number(10,2);--单价
  v_usenum t_account.usenum%type;--水费字数
  v_usenum2 number(10,2);--吨数
  v_money number(10,2);--金额
  v_num0 t_account.num0%type;--上月水表数
  v_num1 t_account.num1%type;--本月水表数
begin
  v_price:=2.45;--单价赋值
  
  --从数据库中查询
  select usenum,v_num0,v_num1 into v_usenum,v_num0,v_num1  from t_account
  where year = '2012' and month='01' and owneruuid=1;
  
  v_usenum2:=round(v_usenum/1000,2);--吨数
  v_money:=v_price*v_usenum2;--金额
  
  DBMS_OUTPUT.put_line('水费字数:'||v_usenum||' 金额:'||v_money);
  
end;

--属性类型 (记录型 表名%rowtype)
declare
  v_price number(10,2);--单价
  v_usenum2 number(10,2);--吨数
  v_money number(10,2);--金额
  v_account t_account%rowtype;--台账行记录类型

begin
  v_price:=2.45;--单价赋值
  
  --从数据库中查询
  select * into v_account  from t_account
  where year = '2012' and month='01' and owneruuid=1;
  
  v_usenum2:=round(v_account.usenum/1000,2);--吨数
  v_money:=v_price*v_usenum2;--金额
  
  DBMS_OUTPUT.put_line('水费字数:'||v_account.usenum||' 金额:'||v_money);
  
end;

记录类型

记录类型
记录类型是把逻辑相关 的数据作为一个单元存储起来 称作 PL/SQL RECORD 的域 ( FIELD),其作用是存放互不相同但逻辑相关的信息。
定义记录类型语法如下:
TYPE
record_type IS RECORD(
Field1 type1 [NOT NULL] [:= exp1 ],
Field2 type2 [NOT NULL] [:= exp2 ],
. . . . .
Fieldn typen [NOT NULL] [:= expn ] );

--记录类型
declare
  --定义一个记录类型
  type customer_type is record(
    v_cust_name varchar2(20),
    v_cust_id number(10));

  --声明自定义记录类型的变量
  v_customer_type customer_type;
begin
  v_customer_type.v_cust_name := '刘德华';
  v_customer_type.v_cust_id := 1001;
  
  dbms_output.put_line(v_customer_type.v_cust_name||','||v_customer_type.v_cust_id);
end;

异常

概念:异常情况处理(EXCEPTION)是用来处理正常执行过程中未预料的事件 程序块的异常处理预定义的错误和 自定义错误 由于 PL/SQL 程序块一旦产 生异常而没有指出如何处理时 程序就会自动终止整个程序运行。

分类:
1. 预定义 (Predefined)错误
ORACLE预定义的异常情况大约有 24 个。对这种异常情况的处理,无需在程序中定义, 由 ORACLE 自动将其引发 。
2. 非预定义 (Predefined)错误
即其他标准的ORACLE 错误。对这种异常情况的处理,需要用户在程序中定义,然后由 ORACLE 自动将其引发。
3. 用户定义 (User_define) 错误
程序执行过程中,出现编程人员认为的非正常情况。对这种异常情况的处理,需要 用户在程序中定义,然后显式地在程序中将其引发 。

异常处理部分一般放在PL/SQL 程序体的后半部结构为:
EXCEPTION
WHEN first_exception THEN code to handle first exception
WHEN second_exception THEN code to handle second exception
WHEN OTHERS THEN code to handle others exception
END
异常处理可以按任意次序排列但 OTHERS 必须放在最后

--异常处理1
declare
  v_price number(10,2);--单价
  v_usenum2 number(10,2);--吨数
  v_money number(10,2);--金额
  v_account t_account%rowtype;--台账行记录类型

begin
  v_price:=2.45;--单价赋值
  
  --从数据库中查询
  select * into v_account  from t_account
  where year = '2012' and month='01' and owneruuid=200;
  
  v_usenum2:=round(v_account.usenum/1000,2);--吨数
  v_money:=v_price*v_usenum2;--金额
  
  DBMS_OUTPUT.put_line('水费字数:'||v_account.usenum||' 金额:'||v_money);
  
exception
  when no_data_found then
    DBMS_OUTPUT.put_line('没有找到账务数据');
end;


--异常处理2
declare
  v_price number(10,2);--单价
  v_usenum2 number(10,2);--吨数
  v_money number(10,2);--金额
  v_account t_account%rowtype;--台账行记录类型

begin
  v_price:=2.45;--单价赋值
  
  --从数据库中查询
  select * into v_account  from t_account
  where year = '2012' and month='01';
  
  v_usenum2:=round(v_account.usenum/1000,2);--吨数
  v_money:=v_price*v_usenum2;--金额
  
  DBMS_OUTPUT.put_line('水费字数:'||v_account.usenum||' 金额:'||v_money);
  
exception
  when no_data_found then
    DBMS_OUTPUT.put_line('没有找到账务数据');
  when too_many_rows then
    dbms_output.put_line('返回了多行数据');
end;

条件判断

三种语法形式:

  • IF <布尔表达式 > THEN
    PL/SQL和 SQL 语句
    END IF;
  • IF<布尔表达式 > THEN
    PL/SQL和 SQL 语句
    ELSE 其它语句
    END IF;
  • IF<布尔表达式 > THEN
    PL/SQL和 SQL 语句
    ELSIF < 其它布尔表达式 > THEN其它语句
    ELSIF < 其它布尔表达式 > THEN其它语句
    ELSE 其它语句
    END IF;
    提示: ELSIF 不能写成 ELSEIF
--条件判断
declare
  v_price1 number(10,2);--单价
  v_price2 number(10,2);--单价
  v_price3 number(10,2);--单价
  
  v_usenum2 number(10,2);--吨数
  v_money number(10,2);--金额
  v_account t_account%rowtype;--台账行记录类型

begin
  v_price1:=2.45;--单价赋值(5吨以下)
  v_price2:=3.45;--单价赋值(5-10吨)
  v_price3:=4.45;--单价赋值(超多10吨)
  
  --从数据库中查询
  select * into v_account  from t_account
  where year = '2012' and month='01' and owneruuid=1;
  
  v_usenum2:=round(v_account.usenum/1000,2);--吨数
  --v_money:=v_price*v_usenum2;--金额
  
  --阶梯水费计算
  if v_usenum2<=5 then
    v_money:=v_price1*v_usenum2;
  elsif v_usenum2>5 and v_usenum2<=10 then
    v_money:=v_price1*5+v_price2*(v_usenum2-5);
  else
    v_money:=v_price1*5 + v_price2*5 + v_price3*(v_usenum2-10);
  end if;
  
  DBMS_OUTPUT.put_line('水费字数:'||v_account.usenum||' 金额:'||v_money);
  
exception
  when no_data_found then
    DBMS_OUTPUT.put_line('没有找到账务数据');
  when too_many_rows then
    dbms_output.put_line('返回了多行数据');
end;

循环

  1. 简单循环
    LOOP
    要执行的语句;
    EXIT WHEN 条件语句 > 条件满足,退出循环语句
    END LOOP;
  2. WHILE 循环 (相较 1 ,推荐使用 2)
    WHILE <布尔表达式 > LOOP
    要执行的语句
    END LOOP;
  3. 数字式循环
    FOR 循环计数器 IN [REVERSE ] 下限 … 上限 LOOP
    要执行的语句;
    END LOOP;
    每循环一次,循环变量自动加1;使用关键字 REVERSE ,循环变量自动减 1 。跟在 IN REVERSE 后面的数字必须是从小到大的顺序, 而且必须是整数,不能是变量或表达式 。可以使用 EXIT 退出循环。

标号和 GOTO
PL/SQL中 GOTO 语句是 无条件跳转到指定的标号去 的意思。语法如下:
GOTO label;
. . . . .
<< label >>标号是用 括起来的标识符

--无条件循环:输出1-100的数
declare
    v_num number;

begin
  v_num:=1;
  loop
    dbms_output.put_line(v_num);
    v_num:=v_num+1;
/*方式一:
    if  v_num>100  then
      exit;
    end if;
*/
--方式二:
    exit when v_num>100;
  end loop;
end;

--有条件循环:输出1-100
declare
  v_num number;
begin
  v_num:=1;
  while v_num <=100
  loop
    dbms_output.put_line(v_num);
    v_num:=v_num+1;
  end loop;
end;

--for循环
--declare
  --自动声明变量
begin
  for v_num in 1..100
   
  loop
    dbms_output.put_line(v_num);
  end loop;  

end;

--GOTO的示例
DECLARE
V_counter NUMBER := 1;
BEGIN
LOOP
DBMS_OUTPUT.PUT_LINE('V_counter 的当前值为 :'||V_
V_counter := v_counter + 1;
IF v_cou nter > 10 THEN
GOTO l_ENDofLOOP;
END IF;
END LOOP;
<<l_
DBMS_OUTPUT.PUT_LINE('V_counter 的当前值为 :'||V_
END ;

游标

含义:是系统为用户开设的一个数据缓冲区存放 SQL 语句的执行结果。 我们可以把游标理解为 PL/SQL 中的结果集。程序中,对于 处理多行记录 的事务经常使用游标来实现。

在声明区声明游标,语法如下:
CURSOR 游标名称 IS SQL 语句
使用游标语法:
OPEN 游标名称
LOOP
FETCH 游标名称 INTO 变量
EXIT WNEN 游标名称 %NOTFOUND
END LOOP;
CLOSE 游标名称

游标属性:
%FOUND 布尔型属性,当最近一次读记录时成功 返回 则值为 TRUE
%NOTFOUND 布尔型属性,与 %FOUND 相反;
%ISOPEN 布尔型属性,当游标已打开时返回 TRUE
%ROWCOUNT 数字型属性,返回已从游标中读取的记录数。

游标的 FOR 循环:
PL/SQL 语言提供了 游标 FOR 循环语句,自动执行游标的 OPEN 、 FETCH 、 CLOSE 语句和 循环 语句的功能;
当进入循环时,游标 FOR 循环语句 自动 打开游标,并提取第一行游标数据,当程序处理完 当前所提取的数据而进入下一次循环时,游标 FOR 循环语句自动提取下一行数据供程序处理,当提取完结果集合中的所有数据行后结束循环,并自动关闭游标 。
格式:
FOR index_variable IN cursor_name[value[, value]…]
LOOP
游标数据处理代码
END LOOP;
index_variable 为游标 FOR 循环语句隐含声明的索引变量,该变量为记录变量 ,其结构与游标查询语句返回的结构集合的结构相同。

--游标
--需求:打印业主类型为1的价格表
select * from t_pricetable ;
select * from t_pricetable where ownertypeid=1;

--游标 输出结果集
DECLARE
    --声明游标
    cursor cur_pricetable is select * from t_pricetable where ownertypeid=1; 
    v_pricetable t_pricetable%rowtype;
BEGIN
  open cur_pricetable;--打开游标
  loop
    fetch cur_pricetable into v_pricetable;--提取游标
    exit when cur_pricetable%notfound;--退出循环游标
    dbms_output.put_line('价格:'||v_pricetable.price||
    '  吨位:'||v_pricetable.minnum||'-'||v_pricetable.maxnum);
  end loop;
  close cur_pricetable;--关闭游标
  
END;

--带参数的游标
DECLARE
    --声明带参游标
    cursor cur_pricetable(v_ownertype number)  is select * from t_pricetable where ownertypeid=v_ownertype; 
    v_pricetable t_pricetable%rowtype;
BEGIN
  --打开游标时指定参数值
  --方式一:
  --open cur_pricetable(v_ownertype=>3);
  --方式二:
  open cur_pricetable(3);
  --错误的
  --open cur_pricetable(v_ownertype=3);
  
  loop
    fetch cur_pricetable into v_pricetable;--提取游标
    exit when cur_pricetable%notfound;--退出循环游标
    dbms_output.put_line('价格:'||v_pricetable.price||
    '  吨位:'||v_pricetable.minnum||'-'||v_pricetable.maxnum);
  end loop;
  close cur_pricetable;--关闭游标
  
END;

--for循环 带参数的游标
DECLARE
    --声明带参游标
    cursor cur_pricetable(v_ownertype number)  is select * from t_pricetable where ownertypeid=v_ownertype; 
    --变量的声明也可以省略
    --v_pricetable t_pricetable%rowtype;
BEGIN

    for v_pricetable in cur_pricetable(2)
    loop
   
    dbms_output.put_line('价格:'||v_pricetable.price||
    '  吨位:'||v_pricetable.minnum||'-'||v_pricetable.maxnum);
  
    end loop;
 
END;

存储函数

ORACLE 提供可以把 PL/SQL 程序存储在数据库中,并可以在任何地方来运行它。这样就叫存储过程或函数 。过程和函数统称为 PL/SQL 子程序,他们是被命名的 PL/SQL 块,均存 储在数据库中,并通过输入、输出参数或输入 输出参数与其调用者交换信息。 过程和函数的唯一区别是函数总向调用者返回数据,而过程则不返回数据 。

创建函数
语法如下:
CREATE [OR REPLACE ] FUNCTION function_name
[ (argment [ {IN | IN OUT }]Type,
argment [ { IN | OUT | IN OUT } ] Type
[ AUTHID DEFINER | CURRENT_USER]
RETURN return_type
{IS | AS}
<类型 变量的说明>
BEGIN
FUNCTION_body
EXCEPTION
其它语句
END

说明

  1. OR REPLACE 为可选 . 有了它 , 可以或者创建一个新函数或者替换相同名字的函数 , 而不会出现冲突
  2. 函数名后面是一个可选的参数列表 , 其中包含 IN, OUT 或 IN OUT 标记 . 参数之间用逗号隔开。
    IN模式:只读。在模块里面,实参的数值只能被引用,而这个参数不能被改变。
    OUT模式:只写。 不能接收传入的实参值。标记表示一个值在函数中进行计算并通过该参数传递给调用语句 ;
    IN OUT模式:可读写。 标记表示传递给函数的值可以变化并传递给调用语句。
    若省略标记 , 则参数隐含为 IN 。
  3. 因为函数需要返回一个值 , 所以 RETURN 包含返回结果的数据类型

在创建存储过程 时 , 可使用 AUTHID CURRENT_USER 或 AUTHID DEFINER 选项 以表明在执行该过程时Oracle 使用的权限。

  1. 如果使用 AUTHID CURRENT_USER 选项创建一个过程 , 则 Oracle 用调用该过程的用户权限执行该过程 。为了成功执行该过程调用者 必须具有访问该存储过程体中引用的所有数据库对象所必须的权限
  2. 如果用默认的 AUTHID DEFINER 选项创建过程选项创建过程 , 则 Oracle 使用过程所有者的特权执行该过程.为了成功执行该过程为了成功执行该过程, 过程的所有者必须具有访问该存储过程体中引用的所有数据库对象所必须的权限. 想要简化应用程序用户的特权管理, 在创建存储过程时, 一般选择 AUTHID DEFINER选项 ,这样就不必授权给需要调用的此过程的所有用户了。
--存储函数  创建
create or replace function fn_getaddress(v_id number)
return varchar2
is
  --声明变量
  v_name varchar2(30);
begin
  --查询地址表
  select name into v_name from t_address where id=v_id;
  return v_name;

end;

--自定义存储函数测试
select fn_getaddress(3) from dual;

--存储函数的应用
select id,name,fn_getaddress(addressid) from t_owners;

--out型参数的示例
/*
要求: 定义一个函数: 获取给定部门的工资总和 和 该部门的员工总数(定义为 OUT 类型的参数).
要求: 部门号定义为参数, 工资总额定义为返回值.
*/

create or replace function sum_sal(dept_id number, total_count out number)
       return number
       is
      
       cursor sal_cursor is select salary from employees 
       where department_id = dept_id;
       v_sum_sal number(8) := 0;   
begin
       total_count := 0;

       for c in sal_cursor 
       loop
           v_sum_sal := v_sum_sal + c.salary;
           total_count := total_count + 1;
       end loop;       

       --dbms_output.put_line('sum salary: ' || v_sum_sal);
       return v_sum_sal;
end;   

--执行函数:
delare 
  v_total number(3) := 0;

begin
    dbms_output.put_line(sum_sal(80, v_total));
    --返回的是函数执行后v_total的值
    dbms_output.put_line(v_total);
end;

存储过程

建立存储过程
在 ORACLE SERVER 上建立存储过程可以被多个应用程序调用可以向存储过程传递参数 也可以向存储过程传回参数
创建过程语法
CREATE [OR REPLACE ] PROCEDURE Procedure_name
[ (argment [ {IN | IN OU T }] Type,
argment [ { IN | OUT | IN OUT } ] Type]
[ AUTHID DEFINER | CURRENT_USER]
{IS | AS}
<类型 变量的说明>
BEGIN
<执行部分>
EXCEPTION
<可选的异常错误处理程序>
END

1 、 存储函数中有返回值,且必须返回而存储过程没有返回值 ,可以通过传出参数返回多个值 。
2 、 存储函数可以在 select 语句 中直接使用,而存储过程不能。过程多数是被应用程序所调用。
3 、 存储函数一般都是封装一个查询结果,而 存储过程一般都封装一段事务代码。

--业主序列
create sequence seq_owners
start with 11;
--存储过程
--不带传出参数的存储过程
create or replace procedure pro_owners_add
(--默认in传入参数
v_name varchar2,--名称
v_addressid number,--地址编号
v_housenumber varchar2,--门牌号
v_watermeter varchar2,--水表号
v_ownertypeid number--业主类型
)
is

begin
  insert into t_owners 
  values(seq_owners.nextval ,v_name,v_addressid,v_housenumber,v_watermeter,sysdate,v_ownertypeid);
  commit;
end;

--调用不带参数的存储过程
call pro_owners_add('雷震子',2,'2333','234',1);

begin
  pro_owners_add('黄天化',2,'2233','1234',1);
end;


--创建带传出参数的存储过程
create or replace procedure pro_owners_add
(
v_name varchar2,--名称
v_addressid number,--地址编号
v_housenumber varchar2,--门牌号
v_watermeter varchar2,--水表号
v_ownertypeid number,--业主类型
v_id out number 
)
is

begin
  --对传出参数赋值
  select seq_owners.nextval into v_id from dual;
  --新增业主 
  insert into t_owners 
  values(v_id ,v_name,v_addressid,v_housenumber,v_watermeter,sysdate,v_ownertypeid);
  commit;
end;

--调用传出参数的存储过程
declare
  v_id number;
begin
  pro_owners_add('杨戬',2,'2332','1234321',1,v_id);
  dbms_output.put_line(v_id);
end;

触发器

触发器在数据库里以独立的对象存储 ,它与存储过程不同的是,存储过程通过其它程序来启动运行或直接启动运行,而 触发器是由一个事件来启动运行 。 即触发器是当某个事件发生时自动地隐式运行 。并且,触发器不能接收参数 。所以 运行触发器就叫触发或点火(firing)。 ORACLE 事件指的是对数据库的表进行的INSERT、UPDATE 及 DELETE 操作或对视图进行类似的操作。ORACLE将触发器的功能扩展到了 触发 ORACLE如数据库的启动与关闭等。

创建触发器
创建触发器的一般语法是
CREATE [OR REPLACE ] TRIGGER trigger_name
{
BEFORE | AFTER
{
INSERT | DELETE | UPDATE OF column [, column …]]}
ON [schema.] table_name
[FOR EACH ROW]
[WHEN condition]
trigger_body;

触发器触发次序

  1. 执行 BEFORE 语句级 触发器
  2. 对与受语句影响的每一行:
    执行 BEFORE 行级 触发器
    执行 DML 语句
    执行 AFTER 行级 触发器
  3. 执行 AFTER 语句级 触发器

触发器的限制

  1. CREATE TRIGGER 语句文本的字符长度不能超过 32KB
  2. 触发器体内的 SELECT 语句只能为 SELECT … INTO … 结构,或者为定义游标所使用的 SELECT 语句 。
  3. 触发器中不能使用数据库事务控制语句 COMMIT; ROLLBACK, SVAEPOINT 语句;
  4. 由触发器所调用的过程或函数也不能使用数据库事务控制语句;

:NEW 修饰符访问操作完成后列的值
:OLD 修饰符访问操作完成前列的值

触发语句:old:new
INSERT所有字段都是空(null)将要插入的数据
UPDATE更新以前该行的值更新后的值
DELETE删除以前该行的值所有字段都是空(null)

:语句级触发器无:old 和 :new

--触发器
--前置触发器
create or replace trigger tri_account_num1
before 
update of num1
on t_account
for each row
declare
    
begin
  --通过伪记录变量修改usenum字段的值
  :new.usenum:= :new.num1-:new.num0;
  
end;

--测试前置触发器
--查询之前的usenum为:13808
select usenum from t_account where id=3;
update t_account 
set  num1=8888
where id=3;
--修改后查询usenum为:-51415 事务提交之前就执行了
select usenum from t_account where id=3;
commit;

--10180
select usenum from t_account where id=2;
update t_account 
set  num1=8888
where id=2;
---41235
select usenum from t_account where id=2;
rollback;
--10180
select usenum from t_account where id=2;

--改后置触发器不能创建 
--因为不能改:new的值,但是能看
create or replace trigger tri_account_num1
after 
update of num1
on t_account
for each row
declare
    
begin
  --通过伪记录变量修改usenum字段的值
  :new.usenum:= :new.num1-:new.num0;
  
end;

--后置触发器
--创建日志表,记录业主名称修改前和修改后的名称
create table t_owners_log(
       updatetime date,
       ownerid number,
       oldname varchar2(30),
       newname varchar2(30)
       
);

create or replace trigger tri_owners_log
after
update of name
on t_owners
for each row
declare
  
begin
  --向日志表插入记录
  insert into t_owners_log values(sysdate,:new.id,:old.name,:new.name); 
  --触发器不用commit;存储过程得commit;
end;

--测试后置触发器
update t_owners set name='Naruto' where id=4;
commit;

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
学好Oracle的六条总结 1、如果有一定的数据库基础,知道SQL是怎么回事,即使写不出来简单的SQL, 但可以看懂它们,你就可以跳到2。否则请先学习一下数据库基础和SQL语言, 不需要很深,更不需要去记忆那些复杂的SQL命令,这些可以留在以后边应用 边学习、记忆。2 、要想学好ORACLE,首先要学习ORACLE的体系结构,现在你不需要深入 理解它们,但要分清几个关键的概念: instance (实例)、数据文件、日志文件、参数文件、数据文件与表空间的关系 3、2是有关ORACLE的一些基本概念,下面要学习的是一些简单的的实际操作 ,就是如何去管理ORACLE数据库,当然不是管理全部的ORACLE。在此过程 中你将对SQLORACLE体系结构有个更深入的了解。 4、到了这一步你基本上算是初步掌握了ORACLE,下面将要根据你的方向来具 体学习其它的ORACLE知识了。如果你是开发人员,则需要更多地去学习 PL/SQL以及DEVELOPER,而这将是一门新的课程。如果你是一名DBA, 请继续。 5、可以根据自己的实际情况,进行有选择的学习,也就是说下面的内 没有特别顺序要求。可以选择深入学习ORACLE的管理、备份与恢复、性能 调整、网络等。当然在学习这些知识的过程中,如果有实际的工作更好,这样 可以在实际中成长,学会TROUBLE SHOOTING 目录 1.1 数据库基本知识 1.2 关系数据库 1.3 数据库设计基础 1.4 SQL基本命令 1.5 Oracle简介 1.6 启动和关闭Oracle 1.7 Oracle 命令复习

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值