Oracle的PL/SQL、過程、函數、遊標、觸發器

1 PL/SQL

1.1簡介

PL/SQL是oracle的核心。

①PL/SQL 是過程語言(Procedural Language)與結構化查詢語言(SQL)結合而成的編程語言;
(oracle自身提供了很多程序包,也可實現郵件發送、校驗等)
②PL/SQL 是對 SQL 的擴展;
③支持多種數據類型,如大對象和集合類型,可使用條件和循環等控制結構;
④可用於創建存儲過程、觸發器和程序包,給SQL語句的執行添加程序邏輯;
⑤與 Oracle 服務器和 Oracle 工具緊密集成,具備可移植性、靈活性和安全性。

1.1.1 優點

支持 SQL,在 PL/SQL 中可以使用:

數據操縱命令
事務控制命令
遊標控制

SQL 函數和 SQL 運算符;
用戶把PL/SQL塊整個發送到服務器端,oracle服務器端編譯、運行,再把結果返回給用戶(可節省網絡流量);
可移植性,可運行在任何操作系統和平臺上的Oralce 數據庫;
更佳的性能,PL/SQL 經過編譯執行;
安全性,可以通過存儲過程限制用戶對數據的訪問;
與 SQL 緊密集成,簡化數據處理。

支持所有 SQL 數據類型
支持 NULL 值
支持 %TYPE 和 %ROWTYPE 屬性類型

1.1.2 體系結構

PL/SQL 引擎駐留在 Oracle 服務器中,該引擎接受 PL/SQL 塊並對其進行編譯執行。

將PL/SQL 塊發送給 Oracle 服務器->Oracle 服務器{[PL/SQL引擎(過程語言執行器)],[SQL引擎(SQL語句執行器)]}->將結果發送給用戶

1.2 PL/SQL 塊簡介

PL/SQL 塊是構成 PL/SQL 程序的基本單元,將邏輯上相關的聲明和語句組合在一起。
PL/SQL 分爲三個部分,聲明部分、可執行部分和異常處理部分。

[DECLARE 
declarations]
BEGIN
executable statements
[EXCEPTION 
handlers]
END;

1.2.1 常量和變量

PL/SQL 塊中可以使用變量和常量

在聲明部分聲明,使用前必須先聲明
聲明時必須指定數據類型,每行聲明一個標識符
在可執行部分的 SQL語句和過程語句中使用

聲明變量和常量的語法:
identifier [CONSTANT] datatype [NOT NULL] [:= | DEFAULT expr];

給變量賦值有兩種方法:
>
使用賦值語句 :=
使用 SELECT INTO 語句

  • 給變量賦值的區別:
T/SQL
select @a=3
set    @a=3
select @a = count(*) from student;

PL/SQL
a := 3
select count(*) into a from student;

1.2.2 PL/SQL 支持的內置數據類型

  • PL/SQL 支持的內置數據類型
    {標量類型[數字、字符、布爾型、日期時間]、
    LOB類型(存儲非結構化數據塊)[BFILE、BLOB、CLOB、NCLOB]、
    屬性類型[%TYPE(提供某個變量或數據庫表列的數據類型
    )、%ROWTYPE(提供表示表中一行的記錄類型 )]}

1.2.2.1 數字數據類型

**BINARY_INTEGER** (存儲有符號整數,所需存儲空間少於NUMBER類型值)->NATURAL、NATURALLN、POSITIVE、POSITIVEN、SIGNTYPE **NUMBER**(存儲整數、實數和浮點數)->DEMICAL、FLOAT、INTEGER、REAL **PLS_INTEGER** (存儲有符號整數,可使算術計算快速而有效)

②字符數據類型

CHAR
VARCHAR2
LONG
RAW
LONG RAW

③日期時間類型

存儲日期和時間數據 常用的兩種日期時間類型

DATE
TIMESTAMP

④布爾數據類型

此類別只有一種類型,即BOOLEAN類型
用於存儲邏輯值(TRUE、FALSE和NULL)
不能向數據庫中插入BOOLEAN數據
不能將列值保存到BOOLEAN變量中
只能對BOOLEAN變量執行邏輯操作

1.2.2.2、LOB數據類型

用於存儲大文本、圖像、視頻剪輯和聲音剪輯等非結構化數據。 LOB數據類型可存儲最大4GB的數據。 LOB類型包括:

BLOB 將大型二進制對象存儲在數據庫中
CLOB 將大型字符數據存儲在數據庫中
NCLOB 存儲大型UNICODE字符數據
BFILE 將大型二進制對象存儲在操作系統文件中

LOB類型的數據庫列僅存儲定位符,該定位符指向大型對象的存儲位置

1.2.2.3、屬性類型

用於引用數據庫列的數據類型,以及表示表中一行的記錄類型,屬性類型有兩種:

%TYPE - 引用變量和數據庫列的數據類型
%ROWTYPE - 提供表示表中一行的記錄類型

使用屬性類型的優點:

不需知道被引用的表列具體類型
如被引用對象的數據類型發生改變,PL/SQL 變量的數據類型也隨之改變,健壯性

1.2.3 邏輯比較

邏輯比較用於比較變量和常量的值,這些表達式稱爲布爾表達式 布爾表達式由關係運算符與變量或常量組成 布爾表達式的結果爲TRUE、FALSE或NULL,通常由邏輯運算符AND、OR和NOT連接 布爾表達式有三種類型:

數字布爾型
字符布爾型
日期布爾型

declare 
  sbirth1 student2.sbirthday%type;
begin
  select sbirthday into sbirth1 from student2 where sno =1;
  if sbirth1 < to_date('19900101','yyyymmdd') then
     dbms_output.put_line('大於25歲');
  end if;
  if sbirth1 < to_date('19900101','yyyymmdd') then
     dbms_output.put_line('大於25歲');
  end if;
end;

1.2.4 控制結構

PL/SQL 支持的流程控制結構:

條件控制

IF 語句
CASE 語句

循環控制

LOOP 循環
WHILE 循環
FOR 循環

順序控制

GOTO 語句
NULL 語句

①條件控制

IF語句根據條件執行一系列語句,有三種形式:IF-THEN、IF-THEN-ELSE 和 IF-THEN-ELSIF
CASE 語句用於根據單個變量或表達式與多個值進行比較
執行CASE 語句前,先計算選擇器的值

②循環控制

循環控制用於重複執行一系列語句,循環控制語句包括: > LOOP、EXIT 和 EXIT WHEN 、FOR 、WHILE 循環控制的三種類型:

LOOP - 無條件循環
WHILE - 根據條件循環
FOR - 循環固定的次數

LOOP 
  sequence_of_statements
END LOOP;

WHILE condition LOOP 
  sequence_of_statements
END LOOP;

FOR counter IN [REVERSE] value1..value2
LOOP 
  sequence_of_statements
END LOOP;

③順序控制

順序控制用於按順序執行語句, 順序控制語句包括:

GOTO 語句 - 無條件地轉到標籤指定的語句
NULL 語句 - 什麼也不做的空語句

④動態SQL

動態 SQL 是指在PL/SQL程序執行時生成的 SQL 語句 編譯程序對動態 SQL 不做處理,而是在程序運行時動態構造語句、對語句進行語法分析並執行 DDL 語句命令和會話控制語句不能在 PL/SQL 中直接使用,但是可以通過動態 SQL 來執行 執行動態 SQL 的語法:

EXECUTE IMMEDIATE dynamic_sql_string
[INTO define_variable_list]
[USING bind_argument_list];

含有ddl的時候,要使用動態sql。 eg.
begin 
  execute immediate 'create table T(t1 int)'
end;

1.3 錯誤處理

在運行程序時出現的錯誤叫做異常 發生異常後,語句將停止執行,控制權轉移到 PL/SQL 塊的異常處理部分 異常有兩種類型:

預定義異常 - 當 PL/SQL 程序違反 Oracle 規則或超越系統限制時隱式引發
用戶定義異常 - 用戶可以在 PL/SQL 塊的聲明部分定義異常,自定義的異常通過 RAISE 語句顯式引發

  • RAISE_APPLICATION_ERROR 過程

    用於創建用戶定義的錯誤信息
    可以在可執行部分和異常處理部分使用
    錯誤編號必須介於 –20000 和 –20999 之間
    錯誤消息的長度可長達 2048 個字節

  • 引發應用程序錯誤的語法:
    RAISE_APPLICATION_ERROR(error_number, error_message);

2 存儲過程

命名的 PL/SQL 塊,編譯並存儲在數據庫中。

2.1 子程序

子程序的各個部分:

聲明部分
可執行部分
異常處理部分(可選)

子程序的分類:

過程 - 執行某些操作
函數 - 執行操作並返回值
  • 子程序的優點:
    模塊化:將程序分解爲邏輯模塊;
    可重用性:可以被任意數目的程序調用;
    可維護性:簡化維護操作;
    安全性:通過設置權限,使數據更安全.

2.2 過程

創建過程的語法(和C語言很相似。or replace可以省略。):
CREATE [OR REPLACE] PROCEDURE 
   <procedure name> [(<parameter list>)]
IS|AS 
   <local variable declaration>
BEGIN
   <executable statements>
[EXCEPTION
   <exception handlers>]
END;
  • 過程參數的三種模式:

    IN:用於接受調用程序的值,默認的參數模式;
    OUT:用於向調用程序返回值;
    IN OUT:用於接受調用程序的值,並向調用程序返回更新的值。

  • 執行過程的語法:
    EXECUTE procedure_name(parameters_list);

-- IN示範
create or replace procedure proc1(i in number)
as
  a varchar2(50);
begin
  a := '';
  for j in 1..i loop
    a := a || '*';
    dbms_output.put_line(a);
  end loop;
end;
/

exec proc1(6);
---------------------------------------------------------------------
-- OUT示範
create or replace procedure proc2(j out int)
as
begin
  j := 100;
  dbms_output.put_line(j);
end;

--只能在另外一個pl/sql段調用:
declare
  k number;
begin
  proc2(k);
end;

--在sql*plus運行存儲過程,要加‘exec’,而在pl/sql中可以直接調用。
---------------------------------------------------------------------
-- IN OUT示範
create or replace procedure proc3(p1 in out number, p2 in out number)
as
  v_temp number;
begin
  v_temp := p1;
  p1 := p2;
  p2 := v_temp;
end;

declare
  num1 number := 100;
  num2 number := 200;
begin
  proc3(num1,num2);
  dbms_output.put_line(num1);
  dbms_output.put_line(num2);
end;
---------------------------------------------------------------------
show user
exec scott.proc1(6)沒有權限
賦權限
grant execute on proc1 to zsr
  • 將過程的執行權限授予其他用戶:
GRANT EXECUTE ON find_emp TO MARTIN;
GRANT EXECUTE ON swap TO PUBLIC;
  • 刪除過程:
DROP PROCEDURE find_emp;

2.3 自主事務處理

  • 自主事務處理

    主事務處理啓動獨立事務處理;
    然後主事務處理被暫停;
    自主事務處理子程序內的 SQL 操作;
    然後終止自主事務處理;
    恢復主事務處理.
    PRAGMA AUTONOMOUS_TRANSACTION 用於標記子程序爲自主事務處理。

  • 自主事務處理的特徵:

    與主事務處理的狀態無關;
    提交或回滾操作不影響主事務處理;
    自主事務處理的結果對其他事務是可見的;
    能夠啓動其他自主事務處理.

-- 自主事務處理
create or replace procedure p2
as
  a varchar2(50);
  -- 自主事務處理,p1的個更改不影響p2
  PRAGMA AUTONOMOUS_TRANSACTION;
begin
  select sname into a from scott.student where sno=2;
  dbms_output.put_line(a);
end;

create or replace procedure p1
as
  n varchar2(50);
begin
  update scott.student set sname = 'ZSR' where sno=2;
  p2();
  select sname into b from scott.student where sno=2;
  dbms_output.put_line(b);
end;

3 函數

3.1 簡介

函數是可以返回值的命名的 PL/SQL 子程序。
創建函數的語法:

CREATE [OR REPLACE] FUNCTION 
  <function name> [(param1,param2)]
RETURN <datatype>  IS|AS 
  [local declarations]
BEGIN
  Executable Statements;
  RETURN result;
EXCEPTION
  Exception handlers;
END;


  • 定義函數的限制:


函數只能接受 IN 參數,而不能接受 IN OUT 或 OUT 參數;
形參不能是 PL/SQL 類型,只能是數據庫類型;
函數的返回類型也必須是數據庫類型.
訪問函數的兩種方式:

使用 PL/SQL 塊;
使用 SQL 語句.
-- 創建函數
create or replace function fun_hell return varchar2
is
begin
  return '你好,朋友';
end;

--調用函數;
sql*plus 
select fun_hello from dual;

pl/sql
declare
  ss varchar2(20);
begin
  ss := fun_hello;
  dbms_output.put_line(ss);
end;

3.2 函數練習

create table 分數表 (student_no number(3),name varchar2(10), score number(3));

insert into  分數表  values (1,'張一', 56);
insert into  分數表 values(2,'張二', 82);
insert into  分數表 values  (3,'張三', 90);

要求:創建一個函數,可以接受用戶輸入的學號,得到該學生的名次,並輸出這個名次。

create or replace function fun1(sno1 int) return int
is
  score1 number;
  mingci1 number;
begin
  select score into score1 from 分數表 where student_no = sno1;
  select count(*) into mingci1 from 分數表 where score > score1;
  mingci1 := mingci1 + 1;
  return mingci1;
end;
/

--編譯錯誤,查看錯誤
show error

--修改
declare
 mc number;
begin
 mc := func1(2);
 dbms_output.put_line('第' || mc || '名');
end;

3.3 過程和函數的比較

過程 函數
作爲 PL/SQL 語句執行 作爲表達式的一部分調用
在規格說明中不包含 RETURN 子句 必須在規格說明中包含 RETURN 子句
不返回任何值 必須返回單個值
可以包含 RETURN 語句,但是與函數不同,它不能用於返回值 必須包含至少一條 RETURN語句

4 遊標

4.1 簡介

什麼情況下,一定要使用遊標,什麼情況下,不使用遊標也行。能夠根據不同情況,選取不同的遊標進行使用。
顯式遊標是用的最廣泛的。
oracle在進行取行記錄的時候,實際上內部使用了遊標。
只要進行select操作,內部使用遊標,相當於指針。

oracle服務器->執行PL/SQL程序->檢索行->保存到遊標中(內存單元)->提取行->一次處理一行

不使用遊標,沒有辦法單獨的一行一行控制。

eg.需求:A表存儲了郵件地址,B表是從網上爬的郵件地址(內含一些錯誤郵箱),要實現從B表剔除不合法的郵箱,當A表不含有該郵箱記錄,則插入A表的需求。

逐行處理查詢結果,以編程的方式訪問數據。

4.2 遊標的類型:

1,隱式遊標:在 PL/SQL 程序中執行DML SQL 語句時自動創建隱式遊標,名字固定叫sql;
2,顯式遊標:顯式遊標用於處理返回多行的查詢;
3,REF 遊標:REF 遊標用於處理運行時才能確定的動態 SQL 查詢的結果。

4.2.1 隱式遊標

①在PL/SQL中使用DML語句時自動創建隱式遊標;
②隱式遊標自動聲明、打開和關閉,其名爲 SQL;
③通過檢查隱式遊標的屬性可以獲得最近執行的DML 語句的信息;
④隱式遊標的屬性有:

   %FOUND – SQL 語句影響了一行或多行時爲 TRUE;
    %NOTFOUND – SQL 語句沒有影響任何行時爲TRUE;
    %ROWCOUNT – SQL 語句影響的行數;
    %ISOPEN  - 遊標是否打開,始終爲FALSE。

4.2.2 顯示遊標

顯式遊標在 PL/SQL塊的聲明部分定義查詢,該查詢可以返回多行。
顯式遊標的操作過程:
數據庫->打開遊標->select *from student->提取行->變量->關閉遊標

聲明遊標、打開遊標、使用遊標取出記錄、關閉遊標。

SET SERVER OUTPUT ON
<!--聲明遊標-->
DECLARE
   my_toy_price  toys.toyprice%TYPE;                  CURSOR toy_cur IS
   SELECT toyprice FROM toys
   WHERE toyprice<250;
BEGIN
   <!--打開遊標-->
   OPEN toy_cur;  
     LOOP
        <!--提取行-->
         FETCH toy_cur INTO my_toy_price;
         EXIT WHEN toy_cur%NOTFOUND;
         DBMS_OUTPUT.PUT_LINE 
      ('TOYPRICE=:玩具單價=:'||my_toy_price);
     END LOOP;
     <!--關閉遊標-->
     CLOSE toy_cur;
END;

declare
  stu1 student%rowtype;
  cursor mycursor is select * from student;
begin
  open mycursor;
  fetch mycursor into stu1;
  while mycursor%found loop
    dbms_output.put_line('學號是:'||stu1.sno||',姓名是:'||stu1.sname);
    fetch mycursor into stu1;
  end loop;
  close mycursor;
end;
/

4.2.2.1 帶參數的顯示遊標

①聲明顯式遊標時可以帶參數以提高靈活性;
②聲明帶參數的顯式遊標的語法如下:
CURSOR <cursor_name>(<param_name> <param_type>)
IS select_statement;

③允許使用遊標刪除或更新活動集中的行;
④聲明遊標時必須使用 SELECT … FOR UPDATE語句。

declare
  stu1 student%rowtype;
  sno1 student.sno%type;
  cursor mycursor(input_no number) is select * from student where sno > input_no;
begin
  <!--從鍵盤輸入-->
  sno1 := &學生學號:
  open mycursor;
  fetch mycursor into stu1;
  while mycursor%found loop
    dbms_output.put_line('學號是:'||stu1.sno||',姓名是:'||stu1.sname);
    fetch mycursor into stu1;
  end loop;
  close mycursor;
end;
/

4.2.2.2 使用顯示遊標更新行

CURSOR <cursor_name> IS SELECT statement FOR UPDATE;

UPDATE <table_name>
SET <set_clause>
WHERE CURRENT OF <cursor_name>

DELETE FROM <table_name>
WHERE CURRENT OF <cursor_name>
declare
  stu1 student%rowtype;
  cursor mycursor is select * from student where sno=2 or sno=3 for update;
begin
  open mycursor;
  fetch mycursor into stu1;
  while mycursor%found loop
    update student set sno=sno+100 where current of mycursor;
    fetch mycursor into stu1;
  end loop;
  close mycursor;
end;

4.2.2.3 循環遊標

①循環遊標用於簡化遊標處理代碼;
②當用戶需要從遊標中提取所有記錄時使用;
③循環遊標的語法如下:

    FOR <record_index> IN <cursor_name>
    LOOP
    <executable statements>
    END LOOP;

循環遊標只能用於查詢,而不能用於更新。

declare
  stu1 student%rowtype;
  cursor mycursor is select * from student;
begin
  for cur_2 in mycursor loop
    dbms_output.put_line('學號是:'||stu1.sno||',姓名是:'||stu1.sname);
  end loop;
end;
/

fetch … bulk collect into

適用於大數據量,速度遠遠快於普通的fetch … into。

4.2.3 REF 遊標

REF 遊標和遊標變量用於處理運行時動態執行的 SQL 查詢。
- 創建遊標變量需要兩個步驟:
①聲明 REF 遊標類型;
②聲明 REF 遊標類型的變量。
- 用於聲明 REF 遊標類型的語法爲:
TYPE <ref_cursor_name> IS REF CURSOR
[RETURN <return_type>];

- 打開遊標變量的語法如下:
OPEN cursor_name FOR select_statement;

declare 
  type refcur is ref cursor;
  cursor2 refcur;
  tab varchar2(50);
  tb_name varchar2(50);
  sno2 student.sno%type;
  name2 student.sname%type;
begin
  tb_name := '&tab';
  if tb_name='student' then
    open cursor2 for select sno,sname from student;
    fetch cursor2 into no2,name2;
    while cursor2%found
    loop
      dbms_output.put_line(cursor2%rowcount||'. 學號是'||no2||',姓名是:'||sname2);
      fetch cursor2 into no2,name2;
    end loop;
    close cursor2;
  else
    dbms_output.put_line('不是正確的表的名字');
  end if;
end;
/

5 觸發器

5.1 簡介

觸發器是當特定事件出現時自動執行的存儲過程;
特定事件可以是執行更新的DML語句和DDL語句;
觸發器不能被顯式調用;
觸發器的功能:

    ①自動生成數據;
    ②自定義複雜的安全權限;
    ③提供審計和日誌記錄;
    ④啓用複雜的業務邏輯.

5.1.1 觸發器語法

CREATE [OR REPLACE] TRIGGER trigger_name
AFTER | BEFORE | INSTEAD OF
[INSERT] [[OR] UPDATE [OF column_list]] 
[[OR] DELETE]
ON table_or_view_name
[REFERENCING {OLD [AS] old / NEW [AS] new}]
[FOR EACH ROW]
[WHEN (condition)]
pl/sql_block;

5.1.2 組成部分

>
觸發器由三部分組成:
觸發器語句(事件)
定義激活觸發器的 DML 事件和 DDL 事件.
觸發器限制
執行觸發器的條件,該條件必須爲真才能激活觸發器
觸發器操作(主體)
包含一些 SQL 語句和代碼,它們在發出了觸發器語句且觸發限制的值爲真時運行

5.1.3 觸發器操作

當用戶插入、更新成績表中的記錄時候,就輸出一個提示“觸發器響應了”。

--針對整張表的
create or replace trigger trig1 before insert or update on grade
begin 
  dbms_output.put_line('觸發器 trig1 響應了');
end;
/

--針對每一行的
create or replace trigger trig1 before insert or update on grade for each row
begin 
  dbms_output.put_line('觸發器 trig1 響應了');
end;
/

有了for each row,就是行級觸發器,沒有for each row就是表級觸發器。行級觸發器,對於每一行都做觸發器的動作。

:new:用戶即將插入的記錄;
:old:用戶即將刪除的記錄。

觸發器不能使用:rollback、commit、create、drop、alter、saveopint等內容。

5.2 after和before觸發器

after觸發器工作原理: 更新->表->保存更新->oracle數據庫->激活->觸發器
before觸發器工作原理: 更新->表->激活->觸發器->保存更新->oracle數據庫

保證學生的sno列,不能爲負值,我們用觸發器解決。
當用戶插入記錄到student時,不能插入sno是負值的記錄。

create or replace trigger trig2 before insert on student for each row
begin 
  if :new.sno < 0 then
    raise_application_error(-20001,'學號錯誤,不能插入表中');
  end if;
  dbms_output.put_line('觸發器 trig1 響應了');
end;
/

5.3 觸發器類型

觸發器類型->模式(DDL)觸發器、數據庫級觸發器、DML觸發器。
DML觸發器包括:行級、語句級、istead of觸發器

類型 備註
DDL觸發器 在模式中執行DDL語句時執行
數據庫級觸發器 在發生打開、關閉、登錄和退出數據庫等系統事件時執行
DML 觸發器 在對錶或視圖執行DML語句時執行
語句級觸發器 無論受影響的行數是多少,都只執行一次
行級觸發器 對DML語句修改的每個行執行一次
INSTEAD OF 觸發器 用於用戶不能直接使用 DML 語句修改的視圖

行級觸發器:有for each row語句,在begin代碼
段中可以使用:new和:old;
語句級觸發器:沒有有for each row語句,在begin代碼段中不可以使用:new和:old。

如果在觸發器的plsql內使用:new :old,就必須是行級觸發器,就是要有for each row。

當執行insert的時候,:new存在,:old沒有;
當執行delete的時候,:new不存在,:old存在;
當執行update的時候,:new存在,:old存在。

oracle要更新某行時,是先刪除原來的記錄,然後插入新的記錄。

平時用的最多的是DML觸發器。

5.4 系統常用變量

變量 備註
Ora_client_ip_address 返回客戶端的ip地址
Ora_database_name 返回當前數據庫名
Ora_login_user 返回登錄用戶名
Ora_dict_obj_name 返回ddl操作所對應的數據庫對象名
Ora_dict_obj_type 返回ddl操作所對應的數據庫對象的類型

啓用、禁用和刪除觸發器

  • 啓動和禁用觸發器
ALTER TRIGGER aiu_itemfile DISABLE;
ALTER TRIGGER aiu_itemfile ENABLE;
  • 刪除觸發器
DROP TRIGGER aiu_itemfile;
  • 當用戶對成績表進行增刪改時,把當時的情況輸出
create or replace trigger trig3 before insert or update or delete on grade for each row
begin
  if inserting then
    dbms_output.put_line('插入學生學號:'||:new.code||',姓名:'||:new.name||',成績:'||:new.score);
  end if;
  if updating then
    dbms_output.put_line('原學生學號:'||:old.code||',姓名:'||:old.name||',成績:'||:old.score||',新學生學號:'||:new.code||',姓名:'||:new.name||',成績:'||:new.score);
  end if;
  if deleting then
    dbms_output.put_line('刪除的學生學號:'||:old.code||',姓名:'||:old.name||',成績:'||:old.score);
  end if; 
end
/
  • 模式觸發器是一種特殊的觸發器。
    只要滿足該模式,就會在我們的模式觸發器表,生成記錄。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章