ORACLE PL/SQL实例精解笔记

 
1. &与&&的区别:
一个&的意思 是每次碰到这个变量,都问问你是啥
两个&,那么只问你一次,以后这个变量都按这个值处理
2.声明常量
   eg: declare  testConstant  CONSTANT NUMBER :=300
         begin
         end;
3. IF语句
   IF  CONDITION1  THEN
          STATEMENT 1;
   ELSIF  CONDITION2  THEN
          STATEMENT2;
   ELSIF  CONDITION3  THEN
          STATEMENT3;
   ELSE
          STATEMENT4;
   END  IF;
4.CASE语句
   a.CASE
            CASE  selector
                   WHEN  EXPRESSION 1 THEN  STATEMENT  1;
                   WHEN  EXPRESSION 2 THEN  STATEMENT  2;
                   ...
                   WHEN  EXPRESSION N THEN  STATEMENT  N;
                   ELSE  STATEMENT  N+1;
            END  CASE;
           eg:
                 case  v_num_flg
                       when   0   then
                               dbms_output.put_line('.........');
                       else
                               dbms_output.put_line('......');
                 end  case;
   b.搜索式CASE语句
              CASE
                     WHEN  SEARCH  CONDITION 1  THEN STATEMENT1;
                     WHEN  SEARCH  CONDITION 2  THEN STATEMENT2;
                     WHEN  SEARCH  CONDITION 3   THEN  STATEMENT3;
                      ..........
                     ELSE
                                    STATEMENT N+1;
             END CASE;
  c.CASE表达式:与CASE语句的差别是:END CASE改为END即可
5.NULLIF与COALESCE
   NULLIF(expression1,expression2):如果expression1等于expression2,则NULLIF返回NULL。如果expression1不等于expression2,NULLIF函数返回expression1;
   NULLIF函数存在一个限制:不能把字面值NULL赋予expression1.
    nvl()将空值转换为指定的值nvl(exp1,exp2),第一个为null,取第二个
   nvl2()将空值转换为指定的值nvl2(exp1,exp2,exp3)  ,第一个为null,取第二个,第二个也为null,取第三个
   COALESCE(expression1,expression2,.....,expressionN)

6.迭代控制--------LOOP
   a. LOOP(方式一:通过EXIT语句)
         LOOP
                 STATEMENT1;
                 STATEMENT2;
                 IF  CONDITION  THEN
                        EXIT;
                 END IF;
         END  LOOP;
  b.LOOP(方式二:通过EXIT  WHEN 语句)
          LOOP
                STATEMENT 1;
                STATEMENT 2;
                EXIT  WHEN  CONDITION;
          END  LOOP;
7.迭代控制--------WHILE
   a.普通WHILE语句
     WHILE  CONDITION  LOOP
                STATEMENT1;
                STATEMENT2;
                ...
                STATEMENTN;
     END  LOOP;
   b.含EXIT的while语句
     WHILE  TEST_CONDITION  LOOP
            STATEMENT1;
            STATEMENT2;
            
            IF  EXIT_CONDITION  THEN
                  EXIT;
            END  IF;
    END  LOOP;
  c.含EXIT  WHEN的WHILE语句
      WHILE TEST_CONDITION   LOOP
             STATEMENT1;
             STATEMENT2;
             
             EXIT  WHEN  EXIT_CONDITION;
      END  LOOP;
8.迭代控制------数值型FOR循环
      其中:REVERSE为从大到小,默认为从小到大,另:  loop_counter不能被其他语句使用,它只在循环时作为一个计数器
      a. 普通的数值型for循环
        FOR  loop_counter  IN [REVERSE]  lower_limit..upper_limit   LOOP
              STATEMENT1;
              ...
              STATEMENTN;
        END LOOP;
     b.含EXIT语句的数值型for循环
          FOR  loop_counter  IN [REVERSE]  lower_limit..upper_limit   LOOP
              STATEMENT1;
              STATEMENT2;
              IF  EXIT_CONDITION  THEN
                   EXIT;
              END  IF;
        END LOOP;
     c.含EXIT语句的数值型for循环
          FOR  loop_counter  IN [REVERSE]  lower_limit..upper_limit   LOOP
              STATEMENT1;
              STATEMENT2;
              EXIT  WHEN  EXIT_CONDITION;
        END LOOP;
9.迭代控制------CONTINUE语句
    只有当处于循环中时,CONTINUE和CONTINUE  WHEN语句才会有效,当处于循环之外时,会带来语法错误。为避免这个错误,可以使用RETURN语句。
    CONTINUE和CONTINUE  WHEN语句适用于所有类型的循环
     a. 与EXIT类似的:
           IF  CONTINUE_CONDITION  THEN
                 CONTINUE;
           END  IF;
     b.与EXIT  WHEN类似:
           CONTINUE  WHEN  CONTINUE_CONDITION;
10.显式游标--低级
      处理显式游标的步骤:
        a.声明游标:在内存中建立游标的初始化环境
                eg:
                     DECLARE  CURSOR  c_student  is   select  firstname||'   '||last_name   name   FROM  student 
                 注:声明记录类型: vr_student   c_student%ROWTYPE   .与游标c_student的类型一致
       b.打开游标:打开被声明的游标,并分配内存
                eg:
                     OPEN  c_student
       c.检索游标:从被声明与打开的游标检索数据
                eg: 
                   方式一:
                      LOOP
                            FETCH  c_student  INTO  vr_student;
                            DBMS_OUTPUT.PUTLINE(vr_student.name);
                            EXIT  WHEN  c_student%NOTFOUND;
                      END LOOP;
                  方式二:
                      FOR  vr_student  IN  c_student
                      LOOP
                              ...
                      END  LOOP;
       d.关闭游标:释放所分配的内存
                    CLOSE  c_student;
     显式游标属性:
           %NOTFOUND   cursor_name%NOTFOUND   boolean类型
           %FOUND         cursor_name%FOUND         boolean类型
           %ROWCOUNT  cursor_name%ROWCOUNT  从游标中所检索的记录数量 
           %ISOPEN         cursor_name%ISOPEN        boolean类型

11.显式游标----高级
     a.传参
      eg: 
          CURSOR c_zip(p_state   IN  zipcode.state%TYPE)  is
          SELECT ZIP,CITY,STATE
          FROM  ZIPCODE
          WHERE STATE=p_state
         传参方式:
             OPEN  c_zip('NY')
              或者
             FOR  r_zip  IN  c_zip('NY')
             LOOP
              .....
     b. FOR UPDATE:当希望使用游标来更新数据库的表时,只能使用FOR UPDATE字句。目的是锁定希望更新的数据库表中数据行
          语法: FOR UPDATE  OF <item_name>
                  eg:
                      1.declare  cusrsor c_course   is   select   course_no,cost    from   course   for  update
                      2. declare  cusrsor c_course   is   select   course_no,cost    from   course   for  update  of phone    只更新表course中的phone字段
     c.WHERE CURRENT  OF  与  FOR  CURRENT OF
           当希望更新最新检索的数据行时,可以使用FOR  CURRENT OF。只能在FOR  UPDATE  OF 游标中使用WHERE  CURRENT  OF 。WHERE CURRENT  OF字句的好处是,免于在UPADATE语句中使用WHERE字句。
         eg:
               DECLARE   CURSOR  c_stud_zip  IS  select  s.student_id,z.city   FROM  student  s, zipcode  z  WHERE z.city='BROOKLYN'  AND  s.zip=z.zip  FOR  UPDATE  OF  phone
               BEGIN
                        FOR  r_stud_zip  IN  c_stud_zip
                        LOOP
                               UPDATE  STUDENT  SET  PHONE='123'||SUBSTR(phone,4)
                               WHERE  CURRENT  OF  c_stud_zip;
                        END LOOP;
                END;
13.引用游标
     DECLARE
            TYPE cusor_type  IS  REF  CURSOR  [RETURN  return_type];
            cursor_variable  cursor_type
            single_record  return_type;
     BEGIN
            OPEN  cursor_variable  FOR  query_definition (eg:select * from empdfn) [USING bind_argument1,bind_argument2,...];
            LOOP
                   FETCH  cursor_variable;
                   EXIT WHEN cursor_variable%NOTFOUND;
                   ...
            END LOOP;
            CLOSE  cursor_variable;
    END;
12.触发器
        CREATE [OR REPLACE]  TRIGGER  Trigger_name
        {BEFORE|AFTER} Triggering_event  ON table_name
        [REFERENCING NEW|OLD  AS  NEW_RECORD|OLD_RECORD]
        [FOR  EACH  ROW]
        [FOLLOWS  another_trigger]
        [ENABLE/DISABLE]
        [WHEN  condition]
        DECLARE
               declaration  statements
        BEGIN
               executable  statements
         EXCEPTION
               exception-handling  statements
        END;
      :NEW为引用最新的列值
      :OLD为引用以前的列值
      以上两个变量只有在使用了FOR EACH  ROW的时候才有效,UPDATE可以使用:NEW与:OLD,INSERT只可以使用:NEW,DELETE只可以使用:OLD
      ----
      两类:
             行触发器和语句触发器
             使用INSTEAD OF 触发器:定义与数据库视图的
                     eg:
                 CREATE OR REPLACE  TRIGGER  instrustructor_sum_del
                 INSTEAD  OF  DELETE  ON instructor_sum_view
                 FOR EACH ROW
                 BEGIN
                       DELETE  FROM instructor  WHERE instructor_id= :OLD.instructor_id;
                 END;
13.复合触发器
         eg:
            CREATE  OR  REPLACE  TRIGGER  student_compound
            FOR  INSERT  ON  STUDENT
            COMPOUND   TRIGGER
                   v_day   VARCHAR2(12);
                 BEFORE   STATEMENT  IS
                 BEGIN
                    ...
                           --语句级触发器,不能用:OLD与:NEW
                 END  BEFORE  STATEMENT;
                 BEFORE  EACH  ROW  IS
                 BEGIN
                   ...     --行触发器,能够使用:OLD与:NEW
                 END  BEFORE EACH  ROW;
            END  student_compound;
14.集合
      a.联合数组
       TYPE  type_name  IS  TABLE  OF  element_type  [NOT NULL]  INDEX  BY  element_type;
       table_name  TYPE_NAME;
       eg:
           DECLARE
               TYPE last_name_type IS TABLE  OF  student.last_name%TYPE  INDEX  BY  BINARY_INTERGE;
                last_name_tab  last_name_type;
     b.嵌套数组
        TYPE  type_name  IS  TABLE  OF  element_type  [NOT  NULL];
        table_name TYPE_NAME;
        注:必须先初始化嵌套表
        eg:
            DECLARE
                TYPE last_name_type  IS  TABLE  OF  student.last_name%TYPE;
                last_name_tab  last_name_type  := last_name_type();  --初始化嵌套表
     c.集合的方法
         如果某特定元素存在于集合中,则EXISTS会返回TRUE。该方法可用于避免SUBSCRIPT_OUTSIDE_LIMIT异常
         COUNT返回集合中元素的数量
         EXTEND会扩展集合的规模
         DELETE会删除集合中所有元素,指定范围的元素,或者特定元素。注意,PL/SQL会保存删除元素的占位符
         FIRST 和 LAST 会返回集合中第一个和最后一个元素的下标。注意,如果嵌套表的第一个元素被删除,则FIRST方法会返回大于1的值。如果嵌套表删除
               一个中间元素,则LAST方法的返回值会大于COUNT方法的返回值
         PRIOR和NEXT会返回指定集合下标的前序和后续下标。
         TRIM会从集合的末尾删除一个,或者指定数量的元素。注意,PL/SQL不会保存被删除元素的占位符。
       eg:
          DECLARE
              TYPE index_by_type  IS  TABLE  OF  NUMBER  INDEX  BY  BINARY_INTEGER;
              index_by_table  index_by_type;
              TYPE  nested_type  IS  TABLE  OF  NUMBER;
               nested_table  nested_type := nested_type(1,2,3,4,5,6,7,8,9,10);
          BEGIN
              FOR i  IN  1..10 LOOP
                   index_by_table(i) := i;
              END  LOOP; 
              IF  index_by_table.EXISTS(3)  THEN
                  DBMS_OUTPUT.PUT_LINE ('......');
              END IF;
              nested_table.DELETE(10);       
              nested_table.DELETE(1,3);
              index_by_table.DELETE(10);
              DBMS_OUTPUT.PUT_LINE('nested_table.LAST='||nested_table.LAST);
               DBMS_OUTPUT.PUT_LINE('nested_table.PRIOR(2)='||nested_table.PRIOR(2));
               DBMS_OUTPUT.PUT_LINE('nested_table.NEXT(2)='||nested_table.NEXT(2));
     d.变长数组
          TYPE  type_name  IS  {VARRAY | VARYING  ARRAY}  (size_limit)  OF  element_type  [NOT  NULL];
          varray_name  TYPE_NAME;
          注:类似于嵌套表,当变长数组被声明时,自动设置为NULL。必须在引用单个元素之前,初始化变长数组。
                不能对变长数组使用DELETE方法
          eg:
              DECLARE
                 CURSOR  name_cur  IS
                     SELECT  last_name
                     FROM  student
                     WHERE  rownum<=10;
                 TYPE  last_name_type  IS   VARRAY(10)  OF  student.last_name%TYPE;
                 last_name_varray  last_name_type :=last_name_type();
                 v_counter  INTEGER := 0;
             BEGIN
                 FOR  name_rec  IN name_cur  LOOP
                     v_counter := v_counter+1;
                     last_name_varray.EXTEND;
                     last_name_varray(v_counter):=name_rec.last_name;
                 END  LOOP;
             END;
     e.多层集合
          eg:
               DECLARE
                   TYPE  varray_type1  IS  VARRAY(4)  OF  INTEGER;
                   TYPE  varray_type2  IS  VARRAY(3)  OF  varray_type1;
                   varray1  varray_type1 := varray_type1(2,4,6,8);
                   varray2  varray_type2 := varray_type2(varray1);
15.记录
    a.基于表的记录      使用%ROWTYPE属性可以创建基于表和基于游标的记录
       eg: 
           DECLARE
               course_rec  course%ROWTYPE;
           BEGIN
               SELECT *  INTO course_rec  FROM  course  WHERE  course_no=25;
           END
    b.基于游标的记录
          注:基于游标的记录依赖于特定的游标,不能在游标之前声明
       eg:
           DECLARE
                CURSOR  student_cur  IS  SELECT first_name,last_name  FROM student  WHERE  rownum<=4;
                student_rec  student_cur%ROWTYPE;
    c.用户定义的记录
          语法如下:
             TYPE  type_name  IS  RECORD
                   (filed_name1  datatype1 [NOT NULL]  [ := DEFAULT  EXPRESSION],
                    filed_name2  datatype2 [NOT NULL] [ := DEFAULT  EXPRESSION],
                    ...
                     filed_nameN  datatypeN [NOT NULL] [ := DEFAULT  EXPRESSION]);
            record_name  TYPE_NAME;
    d.记录兼容性
        i>.对于用户定义的记录
            eg:
                DECLARE
                    TYPE  name_type1  IS  RECORD(first_name  VARCHAR2(12),last_name VARCHAR2(15));
                    TYPE  name_type2  IS  RECORD(first_name  VARCHAR2(12),last_name VARCHAR2(15));
                    name_rec1  name_type1;
                    name_rec2  name_type2;
                解释:虽然name_type1与name_type2结构一样但是不能直接将name_rec1的值赋给name_rec2(即不可:name_rec2=name_rec1),应该通过但值赋值(即:name_rec2.first_name=name_rec1.first_name)
      ii>.对于基于表与游标的记录
            对于基于表与游标的记录赋予用户定义类型,只要两者具有相同的结构即可
   e.嵌套记录   记录中含有记录或者集合
       eg:
           DECLARE
                TYPE name_type  IS  RECORD(first_name  VARCHAR2(15),last_name  VARCHAR2(30));
                TYPE person_type IS  RECORD(name  name_type,zip  VARCHAR2(5));
                person_rec  person_type;
           BEGIN
                SELECT  first_name,last_name,zip  INTO  person_rec.name.first_name,person_rec.name.last_name,person_rec.zip  FROM  student  where  rownum<2;
           END;
   f.记录的集合
        eg:
         DECLARE
             CURSOR  name_cur  IS  SELECT first_name,last_name  FROM  student  WHERE rownum<=4;
             TYPE  name_type  IS  TABLE  OF  name_cur%ROWTYPE  INDEX  BY  BINARY_INTEGER;
             name_tab  name_type;
             v_counter  INTEGER :=0;
        BEGIN
             FOR  name_rec  IN  name_cur  LOOP
                 v_counter := v_counter+1;
                 name_tab(v_counter).first_name:=name_rec.first_name;
                 ...
             END  LOOP;          
       END;
16.动态SQL
    语法结构:
      EXECUTE IMMEDIATE  dynamic_SQL_string
      [INTO  defined_variable1,defined_variable2,...]
      [USING [IN | OUT |IN OUT] bind_argument1,bind_argument2,...]
      [{RETURNING | RETURN} field1,field2,... INTO bind_argument1,bind_argument2,...]
      注:如果不指定USING的参数的任何模式,USING子句中所列出的所有绑定参数都是IN模式的。
            当EXECUTE IMMEDIATE语句包含USING和RETURNING INTO子句时,USING子句只指定IN参数
            动态SQL语句的结尾不应该是分号(;),类似地,动态PL/SQL语句块的结尾不能是右斜线(/)
17.批量SQL
     a. FORALL语句
         FORALL  loop_counter  IN  bounds_clause   
               SQL_STATEMENT [SAVE  EXCEPTION];
         其中,bounds_clause是下面形式之一:
                lower_limit..upper_limit
                INDICES OF  collection_name  BETWEEN  lower_limit..upper_limit
                VALUES  OF  collection_name
        注:INDICES OF子句所引用的集合也许是稀疏的,即有些元素可能已经被删除
              如果VALUES  OF子句中所使用的集合是联合数组,它必须使用PLS_INTEGER和BINARY_INTEGER进行索引
              VALUES  OF子句中所使用集合的元素必须是PLS_INTEGER或者BINARY_INTEGER
              当VALUES OF子句所引用的集合是空时,FORALL语句会异常
       eg:
             DECLARE
                      TYPE row_num_type IS TABLE  OF  NUMBER  INDEX  BY  PLS_INTEGER;
                       row_num_tab  row_num_type;
             BEGIN
                      FOR i  IN 1..10 LOOP
                         row_num_tab(i):=i;
                      END LOOP;
                      FOR ALL i IN 1..10
                          INSERT  INTO TEST(row_num)VALUES(row_num_tab(i));
                      COMMIT;
             END;
       i>.SAVE  EXCEPTION选项
            此选项能够实现:即使当对应的SQL语句导致异常,FORALL语句仍旧能够继续执行。所产生的异常被存储在名为SQL%BULK_EXCEPTIONS的游标属性中。SQL%BULK_EXCEPTION游标属性是一个记录集合,
              有两个字段组成:ERROR_INDEX和ERROR_CODE。ERROR_INDEX字段会存储发生异常的FORALL语句的迭代编号,ERROR_CODE会存储对应于所抛出异常的ORACLE错误代码,可以根据SQLERRM函数查询
              错误码对应的错误信息
           eg: FOR i  in 1.. SQL%BULK_EXCEPTIONS.COUNT LOOP
                     DBMS_OUTPUT.PUT_LINE('RECORD' || SQL%BULK_EXCEPTIONS(i).error_index ||'caused error'||i||':'||SQL%BULK_EXCEPTIONS(i).ERROR_CODE||' '||SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
                 END LOOP;
      ii>.INDICES OF选项
              FOR i  IN 1..10 LOOP
                         row_num_tab(i):=i;
             END LOOP;
              row_num_tab.DELETE(1);
              row_num_tab.DELETE(5);
              row_num_tab.DELETE(7);
             FORALL i IN  INDICES  OF  row_num_tab
                 INSERT INTO TEST(ROW_NUM) VALUES(row_num_tab(i));        
             COMMIT;
           由于删除1,5,7三个元素,故FORALL会迭代7次
     iii>.VALUES OF 选项   VALUES OF 可指明FORALL语句中循环计数器的值来自于所指定集合中元素的值
   b.BULK  COLLECT语句  BULK  COLLECT会检索多行数据,这些数据行存储在集合变量中
         eg:
             DECLARE
                       TYPE  first_name_type  IS  TABLE  OF  student.first_name%TYPE;
                        TYPE  last_name_type  IS  TABLE  OF  student.last_name%TYPE;
                       first_name_tab  first_name_type;
                       last _name_tab  last_name_type;
             BEGIN
                    select  first_name,last_name  BULK  COLLECT  INTO  first_name_tab ,last_name_tab  FROM  student;   
                    FOR  i  IN  first_name_tab.FIRST..first_name_tab.LAST
                    LOOP
                           DBMS_OUTPUT.PUT_LINE('fist_name:'||first_name_tab(i)); 
                    END LOOP;
             END;
17.存储过程
    语法如下:
          CREATE  [OR  REPLACE]  PROCEDURE  name
                [(parameter[,parameter,...])]
          AS
                [local  declarations]
          BEGIN
                executable  statements
          [EXCEPTION
                exception  handlers]
          END  [name];
18.函数
    语法如下:
         CREATE [OR REPLACE]  FUNCTION  function_name
                [parameter...]
                     RETURN  datatype
         IS
         BEGIN
            <body>
            RETURN  [return_value]
         END;
19.包
       a.包规范语法:
          CREATE OR REPLACE  PACKAGE package_name
          IS
          [declarations  of  variables  and types]
          [specifications  of  cursors]
          [specifications  of  modules]
          END  [package_name];
       b.包体语法:
          CREATE  OR  REPLACE  PACKAGE  BODY  package_name
          IS
          [declarations  of  variables  and types]  注:只在包体中声明,但在包规范中未声明的变量、函数、存储过程作为私有变量(即只能被包体内的函数、存储过程调用)
          [specifications  of  cursors]
          [specifications  of  modules]
          [BEGIN  executable  statements]
          [EXCEPTION 
                      exception  handlers]
          END  [package_name];
      eg:
          CREATE  OR REPLACE  PACKAGE test_pkg
          AS
              PROCEDURE  find_name(i_student_id  IN  student.student_id%TYPE);
              FUNCTION  id_is_good(i_student_id  IN  student.studend_id%TYPE)
                   RETURN  BOOLEAN;
          END  test_pkg;
          
         CREATE  OR REPLACE  PACKAGE BODY test_pkg
           AS
           PROCEDURE  find_name(i_student_id  IN  student.student_id%TYPE)
           IS 
                  ...
           BEGIN
                  ...
           END find_name;
           FUNCTION  id_is_good(i_student_id  IN  student.studend_id%TYPE)
                   RETURN  BOOLEAN
           IS 
                 ...
           BEGIN
                    ...
           END  id_is_good;
          END  test_pkg;
20.使用RESTRICT_REFERENCES编译指令实现纯度等级
       语法如下:
       PRAGMA  RESTRICT_REFERENCES( function_name,WNDS [,WNPS] [,RNDS] [,RNPS])
       注:该函数必须存储在数据库中,而不是存储在ORACLE工具的库中
             函数必须是行函数,而不是列函数或分组函数
             对于所有函数(不管是否在SQL语句中使用),参数必须属于IN模式
        eg:
             CREATE  OR  REPLACE  PACKAGE  school_api  
             AS
                  FUNCTION  new_id
                  RETURN NUMBER;
                  PRAGMA  RESTRICT_REFERENCES(new_id,WNDS,WNPS,RNDS,RNPS);
             END  school  api;
        WNDS:write no database  state,不会修改数据库表
        WNPS:write no package  state,不会修改任何包变量的值
        RNPS:read  no  package state,不会读取任何包变量
        RNDS:read  no  database  state,不会读取任何数据库表
21.在包中重载:
        规则如下:
               a.形参必须在参数数量、顺序或者数据类型等方面存在区别
               b.不能重载独立模块的名称
               c.只有return数据类型存在差别的函数不能重载
22.对象类型
       a.语法如下:
            CREATE [OR  REPLACE]  TYPE  type_name  AS   OBJECT
              (attribute_name1  attribute_type,
               attribute_name2   attribute_type,
                ...
                attribute_nameN   attribute_type,
               [method1  specification],
               [method2  specification],
                ...
               [methodN  specification],
              );
             [CREATE  [OR  REPLACE]  TYPE  BODY  type_name   AS
                method1  body;
                method2  body;
                ...
                methodN  body;]
            END;
           eg1:
                 CREATE  OR REPLACE  TYPE test_type  AS  OBJECT
                     (no  varchar2(1),name varchar2(30),grade  number(2));
                 调用:
                      DECLARE  
                          v_test_type   test_type;
                      BEGIN
                          select  test_type(no,name,null)   into  v_test_type   FROM  student;  
                      END;
                   另对于未初始化对象,对象实例及其属性都是null,在使用默认构造器对该对象实例进行初始化之后,就不再是NULL,尽管单个值可能仍旧是NULL,eg:v_test_type :=v_test_type(null,null,null)
          eg2:
                CREATE  OR  REPLACE  TYPE  test_tab_type  IS  TABLE  OF test_type;
        b.对象类型方法
               对象类型有个内置参数SELF,这个参数表示对象类型的特定实例。
               对象比较的两种方式:映射方法与排序方法(二选一)
               构造器方法,成员方法,静态方法
               eg:
                   CREATE  OR  REPLACE  TYPE  zipcode_obj_type  AS  OBJECT
                      ( zip  VARCHAR2(5),city  VARCHAR2(20),state   VARCHAR2(2),
                         --构造器方法,需要两个参数
                         CONSTRUCTOR  FUNCTION  zipcode_obj_type
                               (  SELF  IN  OUT  NOCOPY  zipcode_obj_type,zip  VARCHAR2)
                         RETURN SELF  AS  RESULT,
                         --成员方法
                         MEMBER  PROCEDURE  get_zipcode_info
                            (out_zip  OUT  varchar2,out_city  OUT VARCHAR2),
                         ---静态方法
                         STATIC  PROCEDURE  display_zipcode_info
                             (in_zip_obj   IN  ZIPCODE_OBJ_TYPE),
                         --映射方法
                         MAP  MEMBER  FUNCTION  zipcode  RETURN  VARCHAR2,
                         --排序方法
                          ORDER MEMBER  FUNCTION  zipcode1(zip_obj  ZIPCODE_OBJ_TYPE)  RETURN  INTEGER
                      );
                   /
                CREATE  OR  REPLACE  TYPE  BODY  zipcode_obj_type  AS
                    CONSTRUCTOR   FUNCTION  zipcode_obj_type
                        (SELF  IN  OUT  NOCOPY  zipcode_obj_type,zip  VARCHAR2)
                   RETURN  SELF  AS  RESULT
                   IS
                   BEGIN
                        SELF.zip:=zip;
                        SELECT city  INTO  SELF.city  where zip=SELF.zip;
                        RETURN;
                   EXCEPTION
                        WHEN  NO_DATA_FOUND  THEN
                              RETURN;
                   END;
                   MEMBER  PROCEDURE  get_zipcode_info
                       ( out_zip  OUT  varchar2,out_city  OUT VARCHAR2)
                   IS
                   BEGIN
                         out_zip := SELF.zip;
                          out_city :=SELF.city;
                   END;
                     STATIC  PROCEDURE  display_zipcode_info
                             (in_zip_obj   IN  ZIPCODE_OBJ_TYPE)
                    IS
                    BEGIN
                         DBMS_OUTPUT.PUT_LINE('ZIP: '||in_zip_obj.zip);
                    END;

                     MAP  MEMBER  FUNCTION  zipcode  RETURN  VARCHAR2
                    IS
                    BEGIN
                          RETURN (zip)
                    END;
                     ORDER MEMBER  FUNCTION  zipcode1(zip_obj  ZIPCODE_OBJ_TYPE)  RETURN  INTEGER
                    IS
                    BEGIN
                       IF  zip<zip_obj.zip  THEN RETURN -1;
                       ELSIF   zip=zip_obj.zip  THEN RETURN 0;
                       ELSIF   zip>zip_obj.zip  THEN RETURN 1;
                       END IF;
                    END;
                 END;
                 /

               另: i>.调用   MAP  MEMBER  FUNCTION  zipcode的方式为: IF v_zip_obj1 >v_zip_obj2  THEN ... END IF;
                      ii>.调用   ORDER MEMBER  FUNCTION  zipcode1的方式为 v_result :=v_zip_obj1.zipcode1(v_zip_obj2);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值