现在的位置: 首页 > 综合 > 正文

PL/SQL基础总结

2018年04月28日 ⁄ 综合 ⁄ 共 14285字 ⁄ 字号 评论关闭

---- 第一章 PL/SQL 简介 ----

1. Oracle应用编辑方法概览
    1) Pro*C/C++/... : C语言和数据库打交道的方法,比OCI更常用;
    2) ODBC
    3) OCI: C语言和数据库打交道的方法,和Pro*C很相似,更底层,很少用 只适合ORACLE;
    4) SQLJ: 很新的一种用Java访问Oracle数据库的方法,会的人不多;
    5) JDBC
    6) PL/SQL: 存储在数据库内运行, 其他方法为在数据库外对数据库访问,只适合ORACLE;

2. PL/SQL
    1) PL/SQL(Procedual language/SQL)是在标准SQL的基础上增加了过程化处理的语言;
    2) Oracle客户端工具访问Oracle服务器的操作语言;
    3) Oracle对SQL的扩充;

4. PL/SQL的优缺点
    优点1) 结构化模块化编程,不是面向对象;
        2) 良好的可移植性(不管Oracle运行在何种操作系统);
        3) 良好的可维护性(编译通过后存储在数据库里);
        4) 提升系统性能;

    缺点 1) 不便于向异构数据库移植应用程序(只能用于Oracle);

5. SQL与PL/SQL的区别
    SQL:1) 第四代语言(智能语言);
        2) 做什么,不管怎么做;
        3) 缺少过程与控制语句;
        4) 无算法
    PL/SQL: (相对SQL扩展部分)
        1) 扩展变量和类型;
        2) 扩展控制结构;
        3) 扩展过程与函数;
        4) 扩展对象类型与方法

---- 第二章 PL/SQL程序结构 ----

1. PL/SQL块
    1) 申明部分, DECLARE (如果语句不需要声明任何变量,可以不写);
    2) 执行部分, BEGIN <---------> END;
    3) 异常处理,EXCEPTION(可以没有);

2. PL/SQL开发环境
    可以运用任何纯文本的编辑器编辑,例如:VI

3. PL/SQL字符集
    字母: A-Z, a-z;
    数字: 0-9;
    空白: TAB , SPACE , 回车;
    符号: +_)(*&^%$#@!~ ;

    PL/SQL对大小写不敏感(注意)
   
4. 标识符命名规则答:
    1) 字母开头;
    2) 后跟任意的 非空格字符  数字  货币符号( $ )  下划线( _ ) 或 # ;
    3) 最大长度为30个字符(八个字符左右最合适);
     用来给对象命名(潜规则):
    变量: 以v_开头
    游标: 以c_开头
    类型:
    子程序:
   
5. 分界符
    1) 运算符  + - * / **(指数操作符)
    2) 关系   =(相当于JAVA中的==)  >  <  <>  !=  ~=  ^=  <=  >= 
    3) 赋值   := 例子a:=2   
    4) 连接     || 例: 'abc' || 123
    5) 标号     << 需要的标记 >>
    6) 注释      --(单行)   /*   */(段落)
    7) 替代     <scape> <tab> <enter>

6. 文字
    1)字符型文字(字符串)
        'tom' (单引号)
        'tom''s pen'  ''为2个单引号(标识转义) 为tom's pen
    2)数字型
        123 -4 +56 0 9.0 1.23E5 9.8e-3
    3)布尔型
        TRUE FALSE NULL

7. 变量声明
    语法 Var_name [CONSTANT](标识常量,可选) type [NOT NULL](标识为not-null后必须在后面初始化) [:=value](赋值,初始化);
        Var_name [CONSTANT](标识常量,可选) type [NOT NULL] [ default value](赋值,初始化)等同于上面的语句;

    注:1) 申明时可以有默认值也可以没有;
        2) 如有[CONSTANT][NOT NULL], 变量一定要有一个初始值;
        3) 赋值语句为“:=”;
        4) 变量可以认为是数据库里一个字段;
        5) 规定没有初始化的变量为NULL;

---- 第三章 变量与数据类型 ----

1. 数据类型
    1) 标量型:数字型(BINARY_INTEGER,NUMBER)(DEC,FLOAT,REAL... NUMBER的子类型)、
                    NUMBER(P,S) P:精度:整个的有效数位(从左边开始第一个不为0的数字起)   
                                S:刻度,可选(小数点后面的保留位数)
                    BINARY_INTEGER:保存整数. 和NUMBER的底层的保存方式不同,
                        BINARY_INTEGER为2进制保存,NUMBER 需要考虑其他东西不是2进制方式
                        BINARY_INTEGER之间做加法效率快而NUMBER要先转换2进制再计算
                    单纯的计算---->BINARY_INTEGER 考虑和表中其他数据的交互的话一般------->NUMBER
            字符型、CHAR VARCHAR VARCHAR2 STRING
                    LONG
                    一般CHAR VARCHAR2就够了
                    CHAR 定长(例子:CHAR(5) 如果不够5个字符的话就会用空白填充 ) ,可以不带长度规定(默认为1)
                    VARCHAR2 变长((VARCHAR2(5)标识最长可以保存5个字符) 后面的长度规定必须要有
            布尔型、BOOLEAN
            日期型; DATE(后增加 TIMESTAMP(比DATE更精细点(精确到秒)  INTERVAL) 一般用DATE
    2) 组合型:RECORD(常用)、TABLE(常用)、VARRAY(较少用)
    3) 参考型:REF CURSOR(游标)、REF object_type
    4) LOB(Large Object)

2. %TYPE
    [变量名] [表名.字段名] [%TYPE]
    表示变量具有与数据库的表中某一字段相同的类型
    例:v_FirstName s_emp.first_name%TYPE;

3. RECORD类型
    TYPE t_emp IS RECORD(                 /*其中TYPE,IS,RECORD为关键字,record_name为变量名称*/
        field1 type [NOT NULL][:=expr1],         /*每个等价的成员间用逗号分隔*/
        field2 type [NOT NULL][:=expr2],        /*如果一个字段限定NOT NULL,那么它必须拥有一个初始值*/
        ...                                 /*所有没有初始化的字段都会初始为NULL*/
        fieldn type [NOT NULL][:=exprn]
    );

4. %ROWTYPE
    返回一个基于数据库定义的类型
    DECLARE v_emp s_emp%ROWTYPE;         /*s_emp为表的名字*/
    与RECORD类型中定一个record相比,一步就完成,
            而RECORD类型中定义分二步:a. 所有的成员变量都要申明; b. 实例化变量;
    可以代替RECORD类型.

5. TABLE类型
    TYPE tabletype IS TABLE OF type(类型名,要保存成的数据类型) INDEX BY BINARY_INTEGER;
    例:DECLARE
            TYPE t_emp IS TABLE OF s_emp%ROWTYPE INDEX BY BINARY_INTERGER;
            v_emp t_emp;
        BEGIN
            SELECT * INTO v_emp(100) FROM s_emp WHERE id = 1;
            SELECT * INTO v_emp(200) FROM s_emp WHERE id = 2;
                DBMS_OUTPUT.PUT_LINE(v_emp(200).id||' '||v_emp(200).lastname||' '||v_emp(200).salary);
        END;
    注:1) id(索引) 的数目的限制由BINARY_INTEGER的范围决定(-2147483647<----->2147483647);
        2) TABLE类型与map<int,_T>类似;
        3) 表中的元素可以是复合类型;
        4) KEY 没有必要是顺序的;
        5) 当数据被插入表中的时候,表所需的空间就被分配了;

6. 变量的作用域和可见性    <<outer>>
    1) 执行块里可以嵌入执行块;
    2) 里层执行块的变量对外层不可见;
    3) 里层执行块对外层执行块变量的修改会影响外层块变量的值
        (在此里层,对其他里层则不影响,想要不影响此里层的话可以使用标号标注外层);

---- 第四章 PL/SQL控制语句 ----

1. 条件语句
    IF boolean_expression1(条件1) THEN
        ...
        ELSIF boolean_expression2(条件2) THEN     /*注意是ELSIF,而不是ELSEIF*/
            ...                                 /*ELSE语句(ELSIF)不是必须的,但END IF;是必须的*/
        ELSE
            ...
    END IF;
   
    注意:1)有多个BOOLEAN表达式时候  AND(与),OR(或),NOT(非)
        2)条件为FALSE与TRUE 相同;

2. 循环语句
    1) Loop 循环
        Loop
             ... (循环体)
             IF boolean_expr(条件) THEN        /* 加条件语句,当满足条件时候退出循环*/
                EXIT;                    /* EXIT WHEN boolean_expr */
            END IF;                  
        END LOOP;

    2) WHILE 循环
        WHILE boolean_expr(条件) LOOP         /* boolean_expr 循环条件*/
            ... (循环体)
           END LOOP;
    3) FOR循环
        FOR loop_counter IN [REVERSE] low_bound..high_bound LOOP        
            /* 范围中间用2个点表示 从 low_blound 到 high_bound */
            ... (循环体)
        END LOOP;
        例:    FOR v_cnt IN 1..5 LOOP
                SELECT * INTO v_emp FROM s_emp WHERE id = v_cnt;
        注:a. 加上REVERSE关键字 表示递减,从结束边界到起始边界,递减步长为一;
              不加为递增,从起始边界到结束边界,递减步长为一;
            b. low_blound 起始边界; high_bound 结束边界;

3. GOTO语句
    GOTO label_name;
    1) 只能由内部块跳往外部块;
    2) 设置标签:<< >> 
    3) 示例: LOOP
                ...
                IF D%ROWCOUNT = 50 THEN
                    GOTO l_close;
                END IF;
                ...
            END LOOP;
            <<l_close>>: ...

4. NULL语句
    在语句块中加空语句,用于补充语句的完整性。
    例:IF boolean_expr THEN
            ...
            ELSE NULL;
        END IF;

5. SQL in PL/SQL
    1) 只有DML SQL和transaction Control SQL可以直接在PL/SQL中使用;
    2) PL/SQL中的动态SQL可以使用所有有效的SQL语句,包括DDL;
    3) 动态SQL在运行时动态生成SQL语句,然后分析语句并执行;
    4) PL/SQL中的动态SQL有两种:本地动态SQL和DBMS_SQL包;

---- 第五章 PL/SQL游标 ----

1. 游标(CURSOR)
    游标是从数据表中提取出来的数据,以临时表的形式存放在内存中,在游标中有一个数
    据指针,在初始状态下指向的是首记录,利用 fetch 语句可以移动该指针,从而对游标中的数
    据进行各种操作,然后将操作结果写回数据表中。
    1)分类:     a)显式游标:程序员可以操作控制,是针对select 语句的,指向select 语句的结束集
            b)隐式游标:程序员不可控制,但可以有限制的应用
    2)作用:用于处理查询语句的结果,提取多行数据集;
    3)使用步骤:
        a) 声明游标:
            a. 普通声明:    DELCARE
                            v_emp s_emp%ROWTYPE;
                            v_did s_dept.id%TYPE;
                            CURSOR cur_emp IS select * FROM s_emp WHERE dept_id =v_did;     
                            /* CURSOR的内容必须是一条查询语句 */
            b. 带参数声明明:DELCARE            
                              CURSOR c_emp(v_did s_emp.ID%TYPE) SELECT * FROM s_emp WHERE dept_id = v_did;
        b) 为查询打开游标:
            OPEN cur_emp;     /* 相当于执行select语句,且把执行结果存入CURSOR;
        c) 从游标中取结果,存入PL/SQL变量中:
            a. FETCH cur_emp INTO var1, var2, ...(变量名 1, 变量名 2,.......);     /* 变量的数量、类型、顺序要和Table中字段一致; */
            b. FETCH cur_emp INTO record_var(记录型变量名);
            注:将值从CURSOR取出放入变量中,每FETCH一次取一条记录;
        d) 关闭游标:
            CLOSE cur_emp;
        注:a. 游标使用后应该关闭;
            b. 关闭后的游标不能FETCH和再次CLOSE;
            c. 关闭游标相当于将内存中CURSOR的内容清空;

2. 游标的属性
    游标名%属性名
    1) %FOUND: 是否有值; 有则返回TRUE,否则返回FALSE;
    2) %NOTFOUND: 是否没有值; 如果没有值则返回TRUE,否则返回FALSE;
    3) %ISOPEN: 是否是处于打开状态; 处于打开状态就返回TRUE,否则返回FALSE;
    4) %ROWCOUNT: CURSOR当前的记录号(当前游标的指针位移量,表示在此之前,游标所处理的数据量(多少条记录));

3. 游标的FETCH循环
    1)     LOOP FETCH 游标名 INTO 定义的变量
            EXIT WHEN 游标名%NOTFOUND; /* 当游标没取道记录后退出 要及时的做出判断 */
        END LOOP;
    2)     WHILE 游标名%FOUND LOOP FETCH 游标名 INTO 定义的变量;
        END LOOP;
    3)     FOR 保存数据的变量(不用事先定义,是根据游标声明的时候SELECT 的类型来确定)
        IN 游标名 LOOP (FETCH 游标名 INTO ...)
        (可以不用FETCH 语句)
        END LOOP;

4.带参数的游标CURSOR
    DECLARE
        v_emp s_emp%ROWTYPE
        CURSOR cur_emp(p_did  s_emp.dept_id%TYPE) IS     /* 定义参数p_did的类型 */
            SELECT * FROM s_emp WHERE dept_id= p_did
            FOR UPDATE OF salary;     /*FOR UPDATE OF salary; 加行级锁,在我修改这些数据的时候,
                                    *其他人无法修改数据,直到游标被CLOSE后 */
    BEGIN
        OPEN cur_emp(31);        /*带的参数值 31 就是赋给参数p_did 的 */   
        LOOP
            FETCH cur_emp INTO v_emp;
            EXIT WHEN cur_emp%NOTFOUND;

            DBMS_OUTPUT.PUT_LINE(v_emp.id||'  '||v_emp.first_name);
        END LOOP;
        CLOSE cur_emp;
    END

5.显式游标主要是用于对查询语句的处理,尤其是在查询结果为多条记录的情况下;
而对于非查询语句,如修改、删除操作,则由ORACLE 系统自动地为这些操作设置游标并创建其工作区,这些由系统隐含创建的游标称为隐式游标,隐式游标的名字为SQL,这是由ORACLE 系统定义的。
对于隐式游标的操作,如定义、打开、取值及关闭操作,都由ORACLE 系统自动地完成,无需用户进行处理。
用户只能通过隐式游标的相关属性,来完成相应的操作。
隐式游标的工作区中,所存放的数据是与用户自定义的显示游标无关的、最新处理的一条SQL 语句所包含的数据。
格式调用为: SQL%
 
注:INSERT, UPDATE, DELETE, SELECT 语句中不必明确定义游标。
 
隐式游标属性
 SQL%FOUND       布尔型属性,当最近一次读记录时成功返回,则值为true;
 SQL%NOTFOUND   布尔型属性,与%found相反;
 SQL %ROWCOUNT 数字型属性, 返回已从游标中读取得记录数;
 SQL %ISOPEN    布尔型属性, 取值总是FALSE。SQL命令执行完毕立即关闭隐式游标。


========== day 2 ==========

---- 第六章 HANDLE EXCEPTION ----

1.异常
    分类:1) ORACLE预定义,ORACLE公司对常见的异常都做了预定义
        2) 自定义异常

2.用户自定义异常
    DECLARE
        ...
        e_TooManyStudents EXCEPTION;         /* 申明异常 EXCEPTION关键字 */
        ...
    BEGIN
        ...
        RAISE e_TooManyStudents;             /* 触发异常,抛出异常 RAISE关键字 */
        ...
    EXCEPTION
        WHEN e_TooManyStudents THEN         /* 捕捉和处理异常 */
            ... (异常处理代码块)
        WHEN OTHERS THEN             /* 捕捉和处理所有其他异常 */
            ... (异常处理代码块)
    END;

3.ORACLE 的预定义异常
    1) ORA-0001
        DUP_VAL_ON_INDEX
    2) ORA-0051
        TIMEOUT_ON_RESOURCE
    3) ORA-1001
        INVALID_CURSOR 无效的游标的异常 ( NO_DATA_FOUND异常 )
    4) ORA-6533
        SUBSCRIPT_BEYOND_COUNT
    5) ......

4.处理所有的异常
    EXCEPTION
        ... ;
        WHEN OTHERS THEN
            v_errorCode := SQLCODE;
            v_errorText := SUBSTR(SQLERRM,1,200);
            INSERT INTO log_file(code,message,info) VALUES(v_errorCode,v_errorText,'ORACLE Error');
    END

---- 第七章 SUB PROGRAM ----

1. SUB-PROGRAM
    1) 匿名块 不存在于数据库中,每次运行,数据库都要再编译,再运行,不能在其他块中相互调用
    2) 带名块 储存在数据库中,可以在任何需要的地方调用,可以做到代码重用 (procedure(程序) function(函数) package(包) trigger(触发器))

2. 存储过程(PROCEDURE)
    创建过程: CREATE [OR REPLACE] PROCEDURE proc_name(代码块名)
                [ (arg_name [ {IN|OUT|IN OUT} ] TYPE, arg_name [ {IN|OUT|IN OUT} ] TYPE ) ]
                {IS|AS}
                PROCEDURE_BODY(过程主体)
    1) [OR REPLACE] :如果数据库中存在这个名字就先DROP 再创建(覆盖)
    2) [(arg_name[{IN|OUT|IN OUT}]TYPE, arg_name[{IN|OUT|IN OUT}]TYPE)] 参数列表;
        其格式:(参数名1 {IN|OUT|IN OUT} 类型,参数名2 {IN|OUT|IN OUT} 类型 , ...)
    3) {IS|AS} 关键字,二者必须要选择其一 .
    参数列表:
        1) IN模式: 表示该参数不能被过程赋值(只能位于等号右边), 只能由调用者在调用时输入值;
        2) OUT模式:表示该参数只能被过程赋值(只能位于等号左边), 调用者不用传递参数值;
        3) IN OUT模式: 表示该类型既能被过程赋值也能被调用者传值;
        4) 参数缺省为IN模式
    PROCEDURE_BODY
        1) 过程主体是一个拥有声明,执行和异常处理的完整的PL/SQL块
        2) 声明部分在IS或AS关键字与BEGIN关键字之间
        3) 执行部分在BEGIN和EXCEPTION之间
        4) 异常处理在EXCEPTION和END 之间

3. 存储过程例子
    CREATE OR REPLACE PROCEDURE ModeTest
        ( p_InParm IN NUMBER, p_OutParm OUT NUMBER, p_InOutParm IN OUT NUMBER)
        IS v_LocalVar NUMBER;     /* 声明部分 */
    BEGIN
        v_LocalVar:=p_InParm;         /* 执行部分 */
        p_OutParm:=7;
        p_InOutParm:=7;
        ...
    EXCEPTION
        ...                     /* 异常处理部分 */
    END ModeTest;

4. 调用PROCEDURE的例子
    1) 匿名块可以调;
    2) 其他PROCDEURE可以调用;
    例:DECLARE
            v_var1 NUMBER;
        BEGIN
            ModeTest(12, v_var1, 10); /* 调用3中的ModeTest块 */
        END;
    注:此时v_var1等于7

5. 指定实参的模式
    1) 位置标示法:调用时添入所有参数,实参与形参按顺序一一对应;
        ModeTest(12, v_var1, 10);    /* 顺序不能错 */
    2) 名字标示法:调用时给出形参名字,并给出实参
        ModeTest(p_InParm=>12, p_OutParm=>v_var1, p_Inout=>10);    /* 4 中的调用方法 */
        p_OutParm=>v_var1 形参 => 实参        /* 这样方法可以不考虑参数的位置 */
    注:a. 两种方法可以混用, 但混用时第一个参数必须通过位置来指定。
        b. 名字标记法对于参数很多的时候可提高程序的可读性

6. 使用缺省参数
    1) 形参可以指明缺省值
        parm_name [mode] type { := | DEFAULT } init_value
    2) 位置标记法时,所有的缺省值都放在最后面,使用名字标示法则无所谓
    3) 如果使用的缺省值,尽量将缺省值放在参数表的末尾

7. 函数(Function)与过程(Procedure)的区别
    函数在所有的地方都与过程相似,都有名字,都有统一的形式: 声明,执行与异常处理
    都可以存储在数据库中,也都可以声明在无名块的内部,函数可以看做是过程的一种特殊情况.
    差别:
    1) 过程调用本身是一个PL/SQL语句(可以在命令行中通过exec语句直接调用);
    2) 函数调用是表达式的一部分;

8. 函数的声明
    CREATE [OR REPLACE] PROCEDURE proc_name
        [(arg_name[{IN|OUT|IN OUT}]TYPE, arg_name[{IN|OUT|IN OUT}]TYPE)]
        RETURN TYPE
        {IS|AS}
        procedure_body        
    注:1) 没有返回语句的函数将是一个错误;
        2) 在函数的主体内部,return语句用来将控制通过一个数值返回给调用环境
            RETURN <表达式>
        3) 在一个函数的主体中,可以使用多个RETURN返回语句

9. 删除过程与函数
    DROP PROCEDURE proc_name;
    DROP FUNCTION func_name;

10. 子程序
    1) 位置:
        a. Store subprogram 通过CREATE OR REPLACE 命令创建,以编译后的形式存放在数据库中
        b. 本地子程序 没有CREATE OR REPLACE关键字,不由CREATE FUNCTION 开头
                    子程序的定义放在无名块的声明部分且本地子程序只能是本地调用,其他块不能调用
    2) 例:
        DECLARE
            v_var VARCHAR2;
            FUNCTION func
            (p_Fname IN VARCHAR2, p_Lname IN VARCHAR2)
            RETURN VARCHAR2 IS
            BEGIN
                ....(本地子程序主体)
            END func ;
        BEGIN
            v_var := func('First Name' , 'Last Name' );
            .... ;
        END;

---- 第八章 PACKAGE ----

1. 包
    包可分为包规范(声明部分)PACKAGE和包主体(实现部分)PACKAGE BODY
    包规范和包主体在数据库中放在不同的文件中
    包规范先创建,包主体倚赖于包规范
    1) 包是可以将相关对象存储在一起的PL/SQL的结构;
    2) 包只能存储在数据库中,不能是本地的;
    3) 包是一个带有名字的声明;
    4) 相当于一个PL/SQL块的声明部分;
    5) 在块的声明部分出现的任何东西都能出现在包中;
    6) 包中可以包含过程、函数、游标与变量;
    7) 可以从其他PL/SQL块中引用包,包提供了可用于PL/SQL的全局变量。
    8) 包有包头和包主体,如包头中没有任何函数与过程,则包主体可以不需要。

2. 包头(包规范)
    1) 包头包含了有关包的内容的信息,包头不含任何过程的代码。
    2) 语法: CREATE [OR REPLACE] PACKAGE pack_name
                {IS|AS}
                procedure_specification | function_specification | variable_declaration |
                type_definition | exception_declaration | cursor_declaration
            END pack_name;
    3) 示例:CREATE OR REPLACE PACKAGE pak_test
                AS PROCEDURE RemoveStudent
                (p_StuID IN students.id%TYPE);
            TYPE t_StuIDTable IS TABLE OF students.id%TYPE
                INDEX BY BINARY_INTEGER;
            END pak_test;
    4) 包的部件可以按任意次序出现,但对象必须在被引用之前就声明
        所有的过程或函数的代码不能出现在包头中

3. 包主体
    1) 包主体是可选的,如包头中没有任何函数与过程,则包主体可以不需要。
    2) 包主体与包头存放在不同的数据字典中。
    3) 如包头编译不成功,包主体无法正确编译。
    4) 包主体包含了所有在包头中声明的所有过程与函数的代码。
    5) 示例:CREATE OR REPLACE PACKAGE BODY pak_test
                AS PROCEDURE RemoveStudent
                (p_StuID IN students.id%TYPE)
                IS
                    BEGIN
                        ...
                    END RemoveStudent;
                TYPE t_StuIDTable
                    IS TABLE OF students.id%TYPE
                    INDEX BY BINARY_INTEGER;
            END pak_test;

4. 包的作用域
    1) 在包外调用包中过程(需加包名):
        pak_test.AddStudent(100010, 'CS', 101);
    2) 在包主体中可以直接使用包头中声明的对象和过程(不需加包名);

5. 包中子程序的重载
    1) 同一个包中的过程与函数都可以重载;
    2) 相同的过程或函数名字,但参数不同;
    3) 重载不能仅仅依据是参数名字或模式不同;
    4) 重载不能仅仅一举函数的返回类型;
    5) 重载的参数必须是不同的类型族;
    6) 重载要求参数类型必须不同而且是不同类型族的;
    注: 无法区分CHAR和VARCHAR2

6. 包的初始化
    1) 包存放在数据库中;
    2) 在第一次被调用的时候,包从数据库中调入内存并被初始化;
    3) 包中定义的所有变量都被分配内存;
    4) 每个会话都将拥有自己的包内变量的副本。
    5) 可以指定包的初始化代码 :
        CREATE OR REPLACE PACKAGE BODY pac_name { is | as }
            . . .
        BEGIN
            . . . ( Initialization code )
        END pac_name ;

---- 第九章 TRIGGER ----

1. 触发器
    通过数据表的记录更改来执行一些审计功能,
        当表被修改的时候自动给其他需要执行操作的程序发信号
    用于维护数据的完整性,有些复杂的数据完整性约束
        无法在创建表的时候通过声明性约束解决
    1) 触发器与过程/函数的相同点
        a. 都是带有名字的执行块;
        b. 都有声明、执行体和异常部分;
    2) 触发器与过程/函数的不同点
        a. 触发器必须存储在数据库中;
        b. 触发器由触发事件自动激发(INSERT,UPDATE,DELETE)
        对于过程/函数来说,必须显式地由另一个运行块调用

2. 创建触发器
    1) 语法: CREATE [OR REPLACE] TRIGGER trigger_name
                {BEFORE|AFTER} triggering_event        
                    ON table_reference
                    [FOR EACH ROW [WHEN trigger_condition]]
                trigger_body;
    2) 范例:CREATE OR REPLACE TRIGGER UpdateMajorStats
                AFTER INSERT OR DELETE OR UPDATE
                ON students DECLARE CURSOR c_Statistics
                IS SELECT * FROM students GROUP BY major;
            BEGIN
                ...
            END Up;

3. 触发器
    1) 三个语句(INSERT/UPDATE/DELETE);
    2) 二种类型(之前/之后);
    3) 二种级别(row-level/statement-level);
        所以一个表最多可以定义的触发器数量一共有 3 X 2 X 2 = 12,
        这也使触发器的类型数量

4. 触发器的限制
    触发器的主体是PL/SQL语句块,所有能出现在PL/SQL块中的语句
    在触发器主体中都是合法的限制
    1) 不应该使用事务控制语句( COMMIT , ROLLBACK , SAVEPOINT )
    2) 不能声明任何LONG或LONG RAW变量;
    3) 可以访问的表有限。

5. 触发器的主体可以访问的表
    1) 不可以读取或修改任何变化表(被DML语句正在修改的表);
    2) 不可以读取或修改限制表(带有约束的表)的主键、唯一值、外键列。

【上篇】
【下篇】

抱歉!评论已关闭.