zoukankan      html  css  js  c++  java
  • Oracle翻译注意事项

     

     

    1.   Oracle翻译注意事项

    说明:我们将采取对比原有sql的语句来介绍和解释Oracle语句和编码要求

    1.1.   Oracle常用函数

    4.1.1 INSTR 函数的使用

    概述:oracle的INSTR 函数相当于sql中的CHARINDEX函数

    Sql用法格式CHARINDEX (目标字符串 , 源字符串 [ , 起始位置 ])

    例子1:SELECT CHARINDEX('C','ABCDE'

    输出结果为:3

    说明:在源字符串中查找目标字符串的位置。

    例子2:SELECT CHARINDEX('C','ABCDEFXYZCQA',4)  

    输出结果为:10

    说明:从“源字符串”的第4个字符(包含第4个字符)中查找“目标字符串”的位置。

    Oracle用法格式INSTR(源字符串, 目标字符串[,起始位置] [,匹配序号])

           例子1:SELECT INSTR('CORPORATE FLOOR','OR', 3, 2)   FROM DUAL;    

                  输出结果:14

    说明:目标字符串为'OR',起始位置为3,取第2个匹配项的位置。

    默认查找顺序为从左到右。

    例子2:SELECT INSTR('CSORPORATE FLOOR','OR', 3, 2)   FROM DUAL;

            输出结果:6

    例子3:SELECT INSTR('CORPORATE FLOOR', 'OR', -1, 2) FROM DUAL;

            输出结果:5

     说明:当起始位置为负数的时候,从右边开始查找。

    例子4:SELECT INSTR('CORPORATE FLOOR','OR')   FROM DUAL; 

            输出结果:2

     说明:此时默认起始位置1,匹配序号为1

     

    4.1.2 SUBSTR 函数的使用

         概述:oracle的SUBSTR函数相当于sql中的 SUBSTRING函数      

     Sql用法格式SUBSTRING ( expression , start , length )

     例子1:SELECT SUBSTRING('ABCDEFXYZCQA',4,3 

                   输出结果:DEF

           说明:SELECT SUBSTRING('ABCDEFXYZCQA',4) 将报错:substring 函数要求有 3 个参数。

          Oracle用法格式  substr( string, start_position [, length ] )

           例子1:SELECT SUBSTR('THISISATEST', 6, 2) FROM DUAL;

    输出结果:SA

    说明:从第6个字符(包含第6个字符)开始取2位

    例子 2:SELECT SUBSTR('THISISATEST', 6) FROM DUAL; 

    输出结果:SATEST 

    说明:从第6个字符(包含第6个字符)开始取到结束

    例子3:SELECT SUBSTR('TECHONTHENET', -8, 5) FROM DUAL;

    输出结果:ONTHE

    说明:当起始位置为负数的时候,从右边开始查找。然后再从左往右取5位

     

    4.1.3 NVL 函数的使用

        概述:oracle的NVL函数相当于sql中的 ISNULL函数

    Sql用法格式ISNULL ( check_expression , replacement_value )

    说明:在 check_expression 为 NULL时将返回replacement_value,否则返回check_expression 的值,replacement_value 必须与 check_expresssion 具有相同的类型

    Oracle用法格式NVL ( check_expression , replacement_value )

    说明用法同上

     

    4.1.4 CAST 函数的使用

    概述:oracle的CAST函数与sql中的相同,将某种数据类型的表达式显式转换为另一种数据类型。

         说明:对于将某种数据类型的表达式显式转换为另一种数据类型,sql中提供了cast

    和convert两种函数,但是oracle中没有convert函数而是提供其他的函数,

    具体创建如下的TO_DATE、TO_CHAR、TO_NUMBER

     

    4.1.5 TO_DATE 函数的使用

     概述:是把字符串转换为数据库中日期类型

           例子:

    当我们在翻译的时候定义变量V_FIELDVALUE 是一个 VARCAR2(20)的数据类型时,但是该变量需要作为一个过滤条件的值时如:

    OPEN RCT1 FOR SELECT * FROM AIR_CC_HEADER A WHERE A.FLIGHT_TIME >= V_FLIGHTFROM;

    这时必须把V_FLIGHTFROM变换为 Date类型:

           V_FLIGHTFROM := TO_DATE(V_FIELDVALUE,'YYYY-MM-DD ,HH24:MI:SS')

           

    4.1.6 TO_CHAR和 TO_NCHAR函数的使用

    概述:是把日期或数字转换为字符串

          例子1:

          同样我们定义了变量V_FIELDVALUE的数据类型为VARCAR2(20),此时我想对该日期加上一天,再拼凑到动态的oracle语句中,我们该这么做:

    OPEN RCT1 FOR 'SELECT * FROM AIR_CC_HEADER WHERE EXPIRE_DATE

                   <= TO_DATE(''' || TO_CHAR((TO_DATE(V_FIELDVALUE, 'YYYY-MM-DD HH24:MI:SS') + 1),'YYYY-MM-DD HH24:MI:SS') || ''',''YYYY-MM-DD HH24:MI:SS'')';       

    或者 

            OPEN RCT1 FOR 'SELECT * FROM AIR_CC_HEADER WHERE EXPIRE_DATE

                   <= TO_DATE(''' || V_FIELDVALUE || ''',''YYYY-MM-DD HH24:MI:SS'') + 1';                                                           

    说明:Oracle中没有像sql中有CONVERT函数,所以在翻译过程中如果有遇到类似这样的sql语句:

               CONVERT(VARCHAR(20), CTN_MADE_DATE, 120)

               使用TO_DATE函数将其转换为如下写法:

               TO_CHAR (CTN_MADE_DATE , 'YYYY-MM-DD HH24:MI:SS') 

    4.1.7 TO_NUMBER函数的使用 

    概述:是将字符转换为数字

     

    4.1.8 LENGTH 函数的使用

    概述:Oracle的LENGTH函数相当于Sql的LEN函数,用于计算字符串长度。

     

    4.1.9 RTRIM和LTRIM 函数

    概述:Oracle的RTRIMLTRIM函数与Sql相同,RTRIM 删除字符变量中的尾随空格LTRIM 字符删除字符变量中的起始空格。

     

    4.1.10 REPLACE 函数的使用

    概述:REPLACE('STRING','S1','S2'),STRING希望被替换的字符或变量,

    S1被替换的字符串,S2要替换的字符串。

    例子:SELECT REPLACE('ABC,DEF,GHI',',',':') FROM DUAL

    输出结果:ABC:DEF:GHI

     

    4.1.11 SYSDATE 函数的使用

    概述:oracle的SYSDATE类似与sql的GETDATE()函数的功能,用户获取当前时间。

    Sql用法格式

    例子1SELECT  GETDATE()

    输出结果:2008-07-10 01:28:10.637

    Oracle用法格式

    例子1:SELECT SYSDATE FROM DUAL

    输出结果:2008-7-10 1:28:42

     

    4.1.12 ADD_MONTHS()函数的使用

    概述:ADD_MONTHS(X,Y)函数用于计算X加上Y个月的结果。如果Y是负数,就从X中减去Y个月。

    例子1:SELECT ADD_MONTHS(TO_DATE('2007-7-7','YYYY-MM-DD'),2) FROM DUAL

    输出结果:2007-9-7

    例子2:SELECT ADD_MONTHS(TO_DATE('2007-7-7','YYYY-MM-DD'),-2) FROM DUAL

    输出结果:2007-5-7

     

    4.1.13 LAST_DAY()函数的使用

    概述:LAST_DAY(X)函数用于计算包含X的月的最后一天。

          例子1:SELECT LAST_DAY(TO_DATE('2007-7-7','YYYY-MM-DD')) FROM DUAL;

    输出结果:2007-7-31

     

    4.1.14 NEXT_DAY()函数的使用

    概述:NEXT_DAY(X,DAY)函数用于计算从X开始,下一个DAY的日期;参数DAY是一个文本字符串,

    例如:星期一

    例子1:SELECT NEXT_DAY(TO_DATE('2008-7-19','YYYY-MM-DD'),'星期一') FROM DUAL;

    输出结果:2008-7-21

    4.1.15 ROUND()函数的使用

    概述:ROUND(X[,UNIT])函数用于对X进行取整。默认情况下,X取整为最近的一天。UNIT是一个可选字符串参数,它指明要取整的单元。

    例子1:SELECT ROUND(TO_DATE('2007-5-7','YYYY-MM-DD'),'YY') FROM DUAL;

    输出结果:2007-1-1

    例子2:SELECT ROUND(TO_DATE('2007-8-7','YYYY-MM-DD'),'YY') FROM DUAL;

    输出结果:2008-1-1

    例子3:SELECT ROUND(TO_DATE('2007-5-7','YYYY-MM-DD'),'MM') FROM DUAL;

    输出结果:2007-5-1

    例子4:SELECT ROUND(TO_DATE('2007-5-17','YYYY-MM-DD'),'MM') FROM DUAL;

    输出结果:2007-6-1

    例子5:SELECT ROUND(TO_DATE('2007-5-7 11:10:23','YYYY-MM-DD HH24:MI:SS'),'DD') FROM DUAL;

    输出结果:2007-5-7

    例子6:SELECT ROUND(TO_DATE('2007-5-7 13:10:23','YYYY-MM-DD HH24:MI:SS'),'DD') FROM DUAL;

    输出结果:2007-5-8     

    例子7:SELECT ROUND(TO_DATE('2007-5-7 13:10:23','YYYY-MM-DD HH24:MI:SS'),'HH24') FROM DUAL;输出结果:2007-5-7 13:00:00

    例子8:SELECT ROUND(TO_DATE('2007-5-7 13:45:23','YYYY-MM-DD HH24:MI:SS'),'HH24') FROM DUAL;

    输出结果:2007-5-7 14:00:00

     

    4.1.16 TRUNC()函数的使用

     概述:TRUNC(X,UNIT)函数用于对X进行截断。默认情况下,X被截断为当天的开始时间。UNIT是一个可选字符串参数,它指明要取整的单元。

     例子1:SELECT TRUNC(TO_DATE('2007-5-7','YYYY-MM-DD'),'YY') FROM DUAL;

    输出结果:2007-1-1

    例子2:SELECT TRUNC(TO_DATE('2007-8-7','YYYY-MM-DD'),'YY') FROM DUAL;

    输出结果:2007-1-1

    例子3:SELECT TRUNC(TO_DATE('2007-5-7','YYYY-MM-DD'),'MM') FROM DUAL;

    输出结果:2007-5-1

    例子4:SELECT TRUNC(TO_DATE('2007-5-17','YYYY-MM-DD'),'MM') FROM DUAL;

    输出结果:2007-5-1

    例子5:SELECT TRUNC(TO_DATE('2007-5-7 11:10:23','YYYY-MM-DD HH24:MI:SS'),'DD') FROM DUAL;

    输出结果:2007-5-7

    例子6:SELECT TRUNC(TO_DATE('2007-5-7 13:10:23','YYYY-MM-DD HH24:MI:SS'),'DD') FROM DUAL;

    输出结果:2007-5-7

    例子7:SELECT TRUNC(TO_DATE('2007-5-7 13:10:23','YYYY-MM-DD HH24:MI:SS'),'HH24') FROM DUAL;输出结果:2007-5-7 13:00:00

    例子8:SELECT TRUNC(TO_DATE('2007-5-7 13:45:23','YYYY-MM-DD HH24:MI:SS'),'HH24') FROM DUAL;

    输出结果:2007-5-7 13:00:00

    4.1.17 REPLICATE()函数的使用

     Sql用法格式

    概述:REPLICATE([expression],[count])按指定次数重复字符表达式。

    例子 :Select Replicate('abc',2)

    输出结果:abcabc

    例子 :Select Replicate('abc',-2)

    输出结果:null

    例子 :Select Replicate('abc',0)

    输出结果:无

    Oracle用法格式

     DECLARE

        V_COUNT INTEGER := 3;

        V_RESULT VARCHAR(2000);

     BEGIN

        FOR I IN 1 .. V_COUNT LOOP

          V_RESULT := V_RESULT || 'ABC';

        END LOOP;

        DBMS_OUTPUT.PUT_LINE(V_RESULT);

     END;

    4.2. Oracle常用运算符

    4.2.1 变量赋值

       Sql用法   DECLARE   @FRTCUSTNAME NVARCHAR(200),

                             @FRTCUSTTYPE NVARCHAR(20)

    SELECT   @FRTCUSTNAME = N'ABC',

                            @FRTCUSTTYPE = N'DEF'

    PRINT    @FRTCUSTNAME+@FRTCUSTTYPE        

    打印结果:ABCDEF

     

       Oracle用法 :  DECLARE   V_FRTCUSTNAME   VARCHAR2(200);

                                 V_FRTCUSTTYPE    VARCHAR2(20);

                      BEGIN

                                 V_FRTCUSTNAME := 'ABC'; --变量赋值不是用 “=” 号,而是用 “:=”

                                 V_FRTCUSTTYPE := 'DEF';

                                 DBMS_OUTPUT.PUT_LINE(V_FRTCUSTNAME||V_FRTCUSTTYPE);

                       END;

                   

                      或者直接这样赋值:

     

    DECLARE   V_FRTCUSTNAME   VARCHAR2(200) :='ABC';

                                V_FRTCUSTTYPE    VARCHAR2(20) :='DEF';

                      BEGIN

                                DBMS_OUTPUT.PUT_LINE(V_FRTCUSTNAME||V_FRTCUSTTYPE);

                      END;

                 打印结果:ABCDEF

      说明:对于从数据库取出的数据赋值给某个变量我们一般采取:

    SELECT COLNAME INTO V_变量 FROM   TABLENAME WHERE CONDITION ;

    的方式来赋值。

    例子1:SELECT BL_TYPE INTO V_BLTYPE FROM OZ_BK_HEADER WHERE JOB_ORDER_ID = V_JOBORDERID但是这样的赋值方式存在隐患,当WHERE的条件不成立时,查询出空行时,此时的赋值将有异常。

    于是我们在翻译的时候为防止异常的发生我们一般采用以下两种赋值方式:

    方式1采用隐身游标来赋值(建议使用该方法):

    FOR REC IN (SELECT BL_TYPE FROM OZ_BK_HEADER WHERE JOB_ORDER_ID = V_JOBORDERID)

    LOOP

                    V_BL_TYPE := REC.BL_TYPE;

    END LOOP;

    方式 2 采用捕获异常的方式来赋值:     

    BEGIN

    SELECT BL_TYPE INTO V_BLTYPE FROM OZ_BK_HEADER WHERE JOB_ORDER_ID = V_JOBORDERID;

    EXCEPTION WHEN OTHERS THEN

           V_BLTYPE := '赋默认值';

    END;

    但对于聚集函数就可以不用使用上述的方式了。如:

    SELECT COUNT(1) INTO V_TOTALRECORDS FROM TMP_OZ_HEADER_SESSION;

    可以不使用下列形式,因为聚集函数都能返回一行:

    FOR REC IN (SELECT COUNT(1) AS CN INTO V_TOTALRECORDS FROM TMP_OZ_HEADER_SESSION)

    LOOP

                    V_COUNT := REC.CN;

    END LOOP;

     

    4.2.2 字符串连接

    Sql用法:

    SELECT 'ABC' + 'DEF'  

    输出结果:ABCDEF

    Oracle用法:

    SELECT 'ABC' || 'DEF' FROM DUAL         或者

    SELECT CONCAT('ABC','DEF') FROM DUAL

    输出结果:ABCDEF

    4.3. Oracle PL/SQL 基础   

    4.3.1 条件判断语句 IF … THEN… ELSIF … THEN … END IF;

    DECLARE

       NUM INTEGER := 3;

    BEGIN

     IF NUM < 0 THEN

        DBMS_OUTPUT.PUT_LINE('负数');

     ELSE IF NUM > 0 THEN

              DBMS_OUTPUT.PUT_LINE('正数');

            ELSE

              DBMS_OUTPUT.PUT_LINE('0');

            END IF;

     END IF;

    END;

    说明:当有多个的 ELSE  IF 的时候,为了使代码简洁、美观,易于浏览我们建议将 ELSE  IF 替换为:ELSIF。如以上示例可替换如下:

    DECLARE

     NUM INTEGER := 3;

    BEGIN

     IF NUM < 0 THEN

        DBMS_OUTPUT.PUT_LINE('负数');

     ELSIF NUM > 0 THEN

        DBMS_OUTPUT.PUT_LINE('正数');

     ELSE

        DBMS_OUTPUT.PUT_LINE('0');

     END IF;

    END;

     

    4.3.2 循环语句 LOOP....EXIT....END LOOP;

    DECLARE

     V_NUM   INTEGER := 1;

     V_SUM INTEGER := 0;

    BEGIN

     LOOP

         V_SUM := V_SUM + V_NUM;

         DBMS_OUTPUT.PUT_LINE(V_NUM);

         IF V_NUM = 4 THEN

            EXIT;

         END IF; 

         DBMS_OUTPUT.PUT_LINE('+');

         V_NUM := V_NUM + 1;

     END LOOP;

        DBMS_OUTPUT.PUT_LINE('=');

        DBMS_OUTPUT.PUT_LINE(V_SUM);

    END;

    输出结果:1+2+3+4 = 10

     

    4.3.3 循环语句 LOOP....EXIT WHEN ....END LOOP;

    DECLARE

     V_NUM INTEGER := 1;

     V_SUM INTEGER := 0;

    BEGIN

     LOOP

        V_SUM := V_SUM + V_NUM;

        DBMS_OUTPUT.PUT_LINE(V_NUM);

        EXIT WHEN V_NUM = 4;

        DBMS_OUTPUT.PUT_LINE('+');

        V_NUM := V_NUM + 1;

     END LOOP;

     DBMS_OUTPUT.PUT_LINE('=');

     DBMS_OUTPUT.PUT_LINE(V_SUM);

    END;

    输出结果: 1+2+3+4 = 10

     

    4.3.4 循环语句 WHILE...LOOP...END LOOP;

    DECLARE

       V_NUM INTEGER := 1;

       V_SUM INTEGER := 0;

    BEGIN

       WHILE V_NUM <= 4 LOOP

        V_SUM := V_SUM + V_NUM;

        DBMS_OUTPUT.PUT_LINE(V_NUM);

          IF V_NUM < 4 THEN

            DBMS_OUTPUT.PUT_LINE('+');

          END IF;

        V_NUM := V_NUM + 1;

       END LOOP;

       DBMS_OUTPUT.PUT_LINE('=');

       DBMS_OUTPUT.PUT_LINE(V_SUM);

    END;

     输出结果:1+2+3+4 = 10

     

    4.3.5 循环语句 FOR...IN..LOOP....END LOOP;

    DECLARE

     V_NUM INTEGER;

     V_SUM INTEGER := 0;

    BEGIN

     FOR V_NUM IN 1 .. 4 LOOP

        V_SUM := V_SUM + V_NUM;

        DBMS_OUTPUT.PUT_LINE(V_NUM);

        IF V_NUM < 4 THEN

          DBMS_OUTPUT.PUT_LINE('+');

        END IF;

     END LOOP;

     DBMS_OUTPUT.PUT_LINE('=');

     DBMS_OUTPUT.PUT_LINE(V_SUM);

    END;

    输出结果:1+2+3+4 = 10

     

    4.3.6  游标的使用

    1.声明由于保存列值的变量

    2.声明游标

    3.打开游标

    4.从游标中读取数记录

    5.关闭游标

    例子:

    方法一(显式游标)

     --STEP1 : DECLARE THE VARIABLES

     V_PRODUCT_ID   VARCHAR2(20);

     V_TITLE_NAME   VARCHAR2(20);

     --STEP 2:DECLARE THE CURSOR

     CURSOR CUR_PRODUCT IS

        SELECT PRODUCT_ID  FROM PRODUCTS ORDER BY PRODUCT_ID;

     -- STEP 3:OPEN THE CURSOR

     BEGIN

       OPEN CUR_PRODUCT;  

         LOOP

         -- STEP 4:FETCH THE ROWS FOM THE CURSOR

          FETCH CUR_PRODUCT INTO V_PRODUCT_ID;

          EXIT WHEN CUR_PRODUCT%NOTFOUND;

          BEGIN

        SELECT TITLE_NAME INTO V_TITLE_NAME FROM TITLES WHERE PRODUCT_ID = V_PRODUCT_ID;

          END;      

         END LOOP;

        -- STEP 5:CLOSE THE CURSOR

        CLOSE CUR_PRODUCT;

     END;

    方法二(显式游标)

     --STEP1 : DECLARE THE VARIABLES

     V_PRODUCT_ID   VARCHAR2(20);

     V_TITLE_NAME   VARCHAR2(20);

     --STEP 2:DECLARE THE CURSOR

     CURSOR CUR_PRODUCT IS

        SELECT PRODUCT_ID FROM PRODUCTS ORDER BY PRODUCT_ID;

     -- STEP 3:OPEN THE CURSOR

     BEGIN

       OPEN CUR_PRODUCT; 

        -- STEP 4:FETCH THE ROWS FOM THE CURSOR

       FETCH CUR_PRODUCT INTO V_PRODUCT_ID;

       WHILE(CUR_PRODUCT%FOUND) LOOP       

           BEGIN

         SELECT TITLE_NAME INTO V_TITLE_NAME FROM TITLES WHERE PRODUCT_ID = V_PRODUCT_ID;

             FETCH CUR_PRODUCT INTO V_PRODUCT_ID;

           END;      

       END LOOP;

        -- STEP 5:CLOSE THE CURSOR

        CLOSE CUR_PRODUCT;

     END;

     说明:对比方法一和方法二,体会 “%NOTFOUND” 和 “%FOUND” 的属性的用法。游标的另外两个属性为:%ISOPEM, %ROWCOUNT。这四个属性的意思为:

    %ISOPEN判断游标是否被打开,如果打开%ISOPEN等于true,否则等于false;

    %FOUND、%NOTFOUND判断游标所在的行是否有效,如果有效,则%FOUNDD等于true,否则等于false;

    %ROWCOUNT返回当前位置为止游标读取的记录行数。

    方法三(隐式游标):

    V_TITLE_NAME   VARCHAR2(20);

     BEGIN

        FOR REC IN ( SELECT PRODUCT_ID FROM PRODUCTS ORDER BY PRODUCT_ID) LOOP

          BEGIN

              SELECT TITLE_NAME INTO V_TITLE_NAME FROM TITLES WHERE PRODUCT_ID = REC.PRODUCT_ID;

          END;

        END LOOP;

     END;

    说明:利用FOR循环的功能,可以增强在游标访问记录的能力。当使用FOR循环时,可以不显式的打开和关闭游标---FOR循环会自动执行这些操作。

     

    4.3.7  序列的使用

    1.基本语法

    (1) 创建序列命令

    CREATE SEQUENCE [USER.]SEQUENCE_NAME

        [INCREMENT BY N]

        [START WITH N]

        [MAXVALUE N | NOMAXVALUE]

        [MINVALUE N | NOMINVALUE]

        [CYCLE|NOCYCLE]

        [CACHE|NOCACHE]

        [ORDER|NOORDER];

       

        INCREMENT BY: 指定序列号之间的间隔,该值可为正的或负的整数,但不可为0。序列为升序忽略该子句时,缺省值为1。

        START WITH:   指定生成的第一个序列号。在升序时,序列可从比最小值大的值开始,缺省值为序列的最小值。

                       对于降序,序列可由比最大值小的值开始,缺省值为序列的最大值。

        MAXVALUE:     指定序列可生成的最大值。

        NOMAXVALUE:   为升序指定最大值为1027,为降序指定最大值为-1

        MINVALUE:     指定序列的最小值。

        NOMINVALUE:   为升序指定最小值为1。为降序指定最小值为-1026

        CYCLE:        循环使用,用到最大值再返。

        CACHE:        指定CACHE的值。如果指定CACHE值,ORACLE就可以预先在内存里面放置一些SEQUENCE,这样存取的快些。

                       CACHE里面的取完后,ORACLE自动再取一组到CACHE。 使用CACHE或许会跳号,

                           比如数据库突然不正常DOWN掉(SHUTDOWN ABORT)CACHE 中的 SEQUENCE 就会丢失。所以可以在 CREATE SEQUENCE 的时候用 NOCACHE 防止这种情况。

        ORDER:        顺序使用序列值。

     

    (2) 更改序列

        ALTERSEQUENCE [USER.]SEQUENCE_NAME

        [INCREMENT BY N]

        [MAXVALUE     N| NOMAXVALUE ]

        [MINVALUE     N | NOMINVALUE]

        [CYCLE|NOCYCLE]

        [CACHE|NOCACHE]

        [ORDER|NOORDER];   

        修改序列可以:

        A.修改未来序列值的增量。

        B.设置或撤消最小值或最大值。

        C.转变缓冲序列的数目。

        D.指定序列号是否是有序。

     

     

    (3) 删除序列

        DROP SEQUENCE [USER.]SEQUENCE_NAME;

     

    2. 序列的使用

    序列提供两个方法,NEXTVAL CURRVAL

    NEXTVAL:取序列的下一个值,一次 NEXTVAL 会增加一次 SEQUENCE 的值。

    CURRVAL:取序列的当前值。

    但是要注意的是:第一次 NEXTVAL 返回的是初始值;随后的 NEXTVAL 会自动增加你定义的 INCREMENT BY 值,然后返回增加后的值。CURRVAL 总是返回当前 SEQUENCE 的值,但是在第一次 NEXTVAL 初始化之后才能使用 CURRVAL,否则会出错。

     

    4.4. 存储过程翻译注意事项

    4.4.1 原Sql的存储过程与Oracle存储过程的代码格式比较

     Sql定义存储过程方式

    CREATE PROCEDURE SP_NAME

    (参数1    IN/OUT 类型(长度), --这里的长度是指像VARCHAR(20)这样的类型,

    而如果是INT就不需要了

     参数2    IN/OUT 类型(长度)...)

    AS

    BEGIN

       --变量声明

       DECLARE @变量1   类型(长度)

               @变量2   类型(长度)

               ......

       --临时表声明          

       --变量初始化

       SELECT @变量1 = ?  

              @变量2 = ?  

               ......     

       --游标声明

       --逻辑处理

       --异常处理  

    END

    Oracle定义存储过程方式

    CREATE OR REPLACE PROCEDURE SP_NAME(

        S_参数1   IN/OUT   类型, --类型不允许带长度,如不允许写VARCHAR2(20),

                                    只能写VARCHAR2,是与sql不同的一个地方

        S_参数2   IN/OUT   类型......,      

        RCT1      OUT      PACKAGE_FRTNET.refCursor, --结果集输出统一使用游标,只能为OUT

        RCT2      OUT      PACKAGE_FRTNET.refCursor......

    )

    AS

        --变量声明,Oracle变量声明全部放在这个位置,是与sql不同的第二个地方

        V_变量1     类型(长度);

        V_变量2     类型(长度); 

        ......; 

    --游标初始化

     CURSOR CUR_游标名 IS SELECT ......;

    BEGIN

       --变量初始化

        V_变量1 := ?;

        V_变量2 := ?;

        ......;   

       BEGIN

        --逻辑处理   

         EXCEPTION

            WHEN OTHERS THEN

            --异常处理

       END;

    END SP_NAME;

     

    4.4.2 原Sql临时表中有自增字段的处理方式

    原Sql存储过程中临时表包含自增字段:

    CREATE TABLE #TEMPTABLE

    (CODE INT IDENTITY ,

     CUST_ID NVARCHAR(40))

    INSERT INTO #TEMPTABLE(CUST_ID)

    SELECT CUST_ID FROM SB_CREDIT_CUSOTMER

    GROUP BY CUST_ID

    比如遇到以上有自增字段的临时表,在Oracle使用嵌套子查询的方式解决:  

    CREATE GLOBAL TEMPORARY TABLE TMP_OZ_SEARCH_CREDIT

    (

     CODE    INT,

     CUST_ID NVARCHAR2 (40)

    )

    ON COMMIT DELETE ROWS;

     INSERT INTO TMP_OZ_SEARCH_CREDIT(CODE,CUST_ID) 

     SELECT ROWNUM,CUST_ID FROM

     (SELECT CUST_ID

      FROM SB_CREDIT_CUSOTMER

        GROUP BY CUST_ID);

     

    4.4.3 Sql中使用Top N 语句在Oracle中的处理方式

    原sql语句使用Top N:

    SELECT TOP 30 SELECT A.BK_PANEL_ID, A.BK_PANEL_NO, A.FLIGHT_NO, A.CARRIER_CODE, A.POD_CODE, A.FLIGHT_TIME

    FROM AIR_BK_PANEL AS A           --注意:在Oracle中给表定义表别名时,不允许使用AS

    WHERE A.FLIGHT_NO LIKE '1%'

    ORDER BY A.FLIGHT_TIME DESC

    比如以上的sql语句,在Oracle使用嵌套子查询的方式解决:

    SELECT BK_PANEL_ID, BK_PANEL_NO, FLIGHT_NO, CARRIER_CODE, POD_CODE, FLIGHT_TIME

    FROM (SELECT A.BK_PANEL_ID, A.BK_PANEL_NO, A.FLIGHT_NO, A.CARRIER_CODE, A.POD_CODE, A.FLIGHT_TIME FROM AIR_BK_PANEL A   --直接在表后面跟上表别名,不允许使用AS

           WHERE A.FLIGHT_NO LIKE '1%' ORDER BY FLIGHT_TIME DESC)

    WHERE ROWNUM <=30

    说明:想了解更多的ROWNUM的使用可以参见:

    http://blog.csdn.net/zhenyucheung/archive/2008/05/15/2449954.aspx

     

    4.4.4 Sql中使用UPDATE FROM 语句在Oracle中的处理方式

    原sql语句使用UPDATE FROM:

       UPDATE #AIRBKHEADER

        SET    SHIPPER = B.PARTNER_ID ,CONSIGNEE_NAME = B.CONSIGNEE_NAME

        FROM   #AIRBKHEADER AS A

        JOIN   AIR_BK_PARTNER AS B    ON A.JOB_ORDER_ID = B.JOB_ORDER_ID

          WHERE A.IO_ID = 'O' AND B.PARTNER_TYPE = 'SH'

     比如以上的sql语句,在Oracle有一下两种解决方案:

     方案一:使用游标(不推荐使用)

    CURSOR G1_CURSOR IS

    SELECT R.ROWID ,B.PARTNER_ID, B.CONSIGNEE_NAME

    FROM TMP_AIR_ARRANGE_TRUCK A, AIR_BK_PARTNER B 

    WHERE A.JOB_ORDER_ID = B.JOB_ORDER_ID AND A.IO_ID = 'O' AND B.PARTNER_TYPE = 'SH';

     OPEN G1_CURSOR;

        LOOP

         FETCH G1_CURSOR INTO G1_ROWID,G1_COL1,G1_COL2;

         EXIT WHEN G1_CURSOR%NOTFOUND;

         BEGIN

           UPDATE TEM_AIR_BKHEADER

           SET SHIPPER = G1_COL1, CONSIGNEE_NAME = G1_COL2

           WHERE ROWID = G1_ROWID;

         END;

        END LOOP;

         CLOSE G1_CURSOR;

    方案二:使用子查询(翻译过程中尽量使用该方法,除非该方法行不通才考虑使用游标)

    UPDATE TMP_AIR_ARRANGE_TRUCK A SET (SHIPPER,CONSIGNEE_NAME) =

        (SELECT B.PARTNER_ID,B.CONSIGNEE_NAME

         FROM AIR_BK_PARTNER B

         WHERE B.JOB_ORDER_ID = A.JOB_ORDER_ID 

         AND B.PARTNER_TYPE = 'SH')

         WHERE A.IO_ID = 'O' AND

    EXISTS(SELECT 1 FROM AIR_BK_PARTNER C WHERE 

         C.JOB_ORDER_ID = A.JOB_ORDER_ID   AND C.PARTNER_TYPE = 'SH');

     

    4.4.5 事物临时表和会话临时表的区别和注意事项

    可参见文章:

    Oracle临时表的使用:

    http://blog.csdn.net/yuzhic/archive/2008/01/20/2054491.aspx 

    Oracle数据库临时表管理心得:

    http://www.bitscn.com/oracle/exploiture/200806/144601_2.html

     

    4.4.6 对原Sql分页在Oracle中处理

    原sql的处理方式:

    方式一:使用包含自增字段的临时表处理分页

    DECLARE

    @PAGENUM    INT,

    @PAGESIZE   INT

    BEGIN

    CREATE TABLE #AIRBKHEADER (NUM              INT IDENTITY,

                               JOB_ORDER_ID     NVARCHAR(20),

                               HAWB_NO          NVARCHAR(20),

                               MAWB_NO          NVARCHAR(20) )

    CREATE TABLE #AIRBKHEADERTEMP (JOB_ORDER_ID   NVARCHAR(20),

                                   HAWB_NO        NVARCHAR(20),

                                   MAWB_NO        NVARCHAR(20) )

                                    

    INSERT #AIRBKHEADERTEMP(JOB_ORDER_ID,HAWB_NO,MAWB_NO)

    SELECT   A.JOB_ORDER_ID,A.HAWB_NO,A.MAWB_NO

    FROM AIR_BK_HEADER A LEFT JOIN VW_AIRBK_PARTNER B

    ON A.JOB_ORDER_ID = B.JOB_ORDER_ID ORDER BY A.JOB_ORDER_ID   

     

    INSERT #AIRBKHEADER(JOB_ORDER_ID,HAWB_NO,MAWB_NO)

    SELECT * FROM #AIRBKHEADERTEMP

     

    SET @FIRSTRECORDNUM = (@PAGENUM - 1) * @PAGESIZE + 1

    SELECT   NUM,JOB_ORDER_ID,HAWB_NO,MAWB_NO           

    FROM #AIRBKHEADER WHERE NUM >= @FIRSTRECORDNUM AND NUM < @FIRSTRECORDNUM + @PAGESIZE

    END

     方式二:使用Top N 处理分页

     SELECT TOP @PAGE_SIZE JOB_ORDER_ID,HAWB_NO,MAWB_NO FROM AIR_BK_HEADER

    WHERE JOB_ORDER_ID NOT IN

    (SELECT TOP (@PAGESIZE*(@PAGEINDEX-1)) JOB_ORDER_ID FROM AIR_BK_HEADER)

       

    Oracle处理方式:

    方式一:使用临时表处理分页

    CREATE GLOBAL TEMPORARY TABLE TMP_AIR_ARRANGE_TRUCK

    (NUM            INTEGER,

     JOB_ORDER_ID   VARCHAR2(20),

     BK_NO          VARCHAR2(20),

     MAWB_NO        VARCHAR2(20))

    ON COMMIT DELETE ROWS;

    INSERT INTO TMP_AIR_ARRANGE_TRUCK(NUM,JOB_ORDER_ID,BK_NO,MAWB_NO)

       SELECT ROWNUM,JOB_ORDER_ID,BK_NO,MAWB_NO FROM

     (SELECT A.JOB_ORDER_ID,A.BK_NO,A.MAWB_NO

      FROM   AIR_BK_HEADER A LEFT JOIN VW_AIRBK_PARTNER B

    ON    A.JOB_ORDER_ID = B.JOB_ORDER_ID ORDER BY A.JOB_ORDER_ID) ;

     

    --遇到ORDER BY 或者 GROUD BY 或者 DISTINCT 关键字一定要再嵌套一次,不建议直接写成:

    INSERT INTO TMP_AIR_ARRANGE_TRUCK(NUM,JOB_ORDER_ID,BK_NO,MAWB_NO)     

        SELECT ROWNUM, A.JOB_ORDER_ID,A.BK_NO,A.MAWB_NO

           FROM   AIR_BK_HEADER A LEFT JOIN VW_AIRBK_PARTNER B

     ON    A.JOB_ORDER_ID = B.JOB_ORDER_ID ORDER BY A.JOB_ORDER_ID;

    最后进行分页:

    V_FIRSTRECORDNUM = (V_PAGENUM - 1) * V_PAGESIZE + 1;

    SELECT   NUM,JOB_ORDER_ID,HAWB_NO,MAWB_NO           

    FROM TMP_AIR_ARRANGE_TRUCK WHERE NUM >= V_FIRSTRECORDNUM AND NUM < V_FIRSTRECORDNUM + V_PAGESIZE;      

    方式二:使用ROWNUM处理分页

    情景一:

    SELECT COLS FROM

    (SELECT ROWNUM R_N, COLS

     FROM TABLE_NAME

     WHERE FILTERS AND ROWNUM <= V_PAGEINDEX * V_PAGESIZE ) T

    WHERE T.R_N > (V_PAGEINDEX - 1) * V_PAGESIZE;

    情景二:

    V_FIRSTRECORDNUM := (V_PAGEINDEX - 1) * V_PAGESIZE + 1;

    SELECT COLS FROM

    (SELECT ROWNUM R_N, COLS

     FROM TABLE_NAME

     WHERE FILTERS AND ROWNUM < V_FIRSTRECORDNUM + V_PAGESIZE) T

    WHERE T.R_N >= V_FIRSTRECORDNUM;

    4.4.7 输入参数的处理

    对于输入参数我们一般做如下处理:

     CREATE OR REPLACE PROCEDURE SPAIR_LIST_BOOKING_PANEL

    (

            S_FILTERSTR      IN        VARCHAR2 DEFAULT NULL,

            RCT1              OUT       PACKAGE_FRTNET.REFCURSOR

    )

    AS

    V_FILTERSTR  VARCHAR2(2000) := S_FILTERSTR;

    V_INDEX       INTEGER;

    V_START       INTEGER;

    V_SUBSTRING   VARCHAR2(2000);

    V_UNITSTART   INTEGER;

    V_FIELDNAME   VARCHAR2(2000);

    V_FIELDVALUE VARCHAR2(2000);

    BEGIN

             V_START := 1;

             V_FILTERSTR := TRIM(V_FILTERSTR);

             WHILE(V_FILTERSTR IS NOT NULL) LOOP

            BEGIN

               V_INDEX := INSTR(V_FILTERSTR,';',V_START);

               IF(V_INDEX = 0) THEN

                  BEGIN

                    V_SUBSTRING := SUBSTR(V_FILTERSTR,V_START,LENGTH(V_FILTERSTR) - V_START +1);               

                  END;

               ELSE

                  BEGIN

                    V_SUBSTRING := SUBSTR(V_FILTERSTR,V_START,V_INDEX - V_START);

                  END;

               END IF;

               V_UNITSTART := 1;

               V_UNITINDEX := INSTR(V_SUBSTRING,'|',V_UNITSTART);

               V_FIELDNAME := UPPER(SUBSTR(V_SUBSTRING,V_UNITSTART,V_UNITINDEX-V_UNITSTART));

    --对于V_FIELDNAME一定要进行UPPER操作

               V_FIELDVALUE := SUBSTR(V_SUBSTRING,V_UNITINDEX+1,LENGTH(V_SUBSTRING));          

               IF V_FIELDNAME = 'ISALLOCATION' THEN

               BEGIN

                  V_ISALLOCATION := V_FIELDVALUE;

               END;

               END IF;          

               IF(V_INDEX = 0) THEN

               BEGIN

                  EXIT;

               END;

               END IF;          

               V_START := V_INDEX + 1;          

            END;

            END LOOP;

    END;

    说明:1.V_FILTERSTR   VARCHAR2(2000) := S_FILTERSTR;

    这步处理因为输入参数不允许对本身进行值变更操作,如下列使用有误:

          S_FILTERSTR := TRIM (S_FILTERSTR);但是输出参数允许这样操作。

    2.V_FIELDNAME := UPPER(SUBSTR(V_SUBSTRING,V_UNITSTART,V_UNITINDEX-V_UNITSTART));

    这步操作是因为后面的比较字段为大写的,为防止输入参数可能为小写的情况发生,对于

    V_FIELDNAME必须进行UPPER操作。

    4.4.8 原Sql中空和非空的判断的处理

     原sql的空判断:

    DECLARE @A VARCHAR(20)

     SET @A = NULL

     IF (ISNULL(@A,'') = '')

     PRINT 'A'

     ELSE

     PRINT 'B'

     或者 SET @A = '',以上的执行结果都是打印出: A  

    但是对于Oracle来说不允许使用以上方式做非空判断,因为

    DECLARE V_A VARCHAR2(20) := NULL ;

    BEGIN

     IF (NVL(V_A,'') = '') THEN

       DBMS_OUTPUT.put_line('A');

     ELSE

       DBMS_OUTPUT.put_line('B');

     END IF;

    END;

    或者 DECLARE V_A VARCHAR2(20) := '' ;

    以上的执行结果都是打印出: B  

    同理在对非空判断也不允许使用(NVL(V_A,'') <> '')

    总之:在Oracle中,对于空和非空的判断只允许使用 V_A IS NULL 或者 V_A IS NOT NULL

    因为在Oracle中   ''   也就是 NULL ,NULL跟任何数做比较(不管是 =<>><

    作为判断条件都为False

    4.4.9 原Sql的左连接

     原sql语句:

    SELECT B.MBL_NO, B.HBL_NO, B.BL_TYPE, LINE_NAME = C.ABBREV, A.CONTAINER_NO,

                 A.SEAL_NO, A.CONTAINER_SIZE_TYPE, A.CONTAINER_STATUS

        FROM OZ_BK_CONTAINER AS A

        JOIN #BKHEADER AS TMP ON (TMP.JOB_ORDER_ID = A.JOB_ORDER_ID)

        LEFT JOIN OZ_BK_HEADER AS B ON A.JOB_ORDER_ID = B.JOB_ORDER_ID

         LEFT JOIN OB_LINE AS C ON B.LINEDEF_ID = C.LINEDEF_ID

    ORACLE除了以上写法外还有另外一种独有的写法:

     SELECT B.MBL_NO,B.HBL_NO,B.BL_TYPE,C.ABBREV LINE_NAME,A.CONTAINER_NO,A.SEAL_NO,

             A.CONTAINER_SIZE_TYPE,A.CONTAINER_STATUS

        FROM OZ_BK_CONTAINER A,TMP_OZ_HEADER_SESSION TMP,OZ_BK_HEADER B,OB_LINE C

        WHERE (TMP.JOB_ORDER_ID = A.JOB_ORDER_ID)

        AND (A.JOB_ORDER_ID = B.JOB_ORDER_ID (+))

          AND (B.LINEDEF_ID = C.LINEDEF_ID (+));

     

    4.4.10 动态语句的执行

    原sql方式:

    DECLARE @USER_NAME='XIAO' 

    EXEC 'SELECT * FROM SB_USER WHERE USR_NAME LIKE'''+@USER_NAME+'%'''

    Oracle处理方式:

    V_USER_NAME :='XIAO';

    EXECUTE IMMEDIATE 'SELECT * FROM USER WHERE USR_NAME LIKE''' || V_USER_NAME || '%''';

    建议:尽量避免使用动态语句,以提高性能

    4.4.11  Oracle中结果集游标使用的注意事项

    首先看下面的例子:

     CREATE OR REPLACE PROCEDURE SP_S_CITY_SEARCH

    (

     S_FILTERSTR   IN VARCHAR2,

     S_RECORDCOUNT OUT INT,

     RCT1          OUT PACKAGE_FRTNET.REFCURSOR,

     RCT2          OUT PACKAGE_FRTNET.REFCURSOR

    ) AS

     V_STARTRECORD   INT := 1;

    BEGIN

     OPEN RCT1 FOR

        SELECT A.*    FROM   SB_CITY A   

        JOIN   TMP_COM_TLBCITY B ON (A.CITY_ID = B.CITY_ID)   

        WHERE B.NUM >= V_STARTRECORD AND B.NUM < V_MAXRECORDS + V_STARTRECORD;

    IF V_STARTRECORD := 0 THEN

     OPEN RCT2 FOR

        SELECT S_RECORDCOUNT FROM DUAL;

    END IF;

    END;

    对于以上情况 当 IF 条件不成立时,游标RCT2 在Oracle测试用例中将报以下错误。

    该错误是会抛到我们freightnet客户端的。错误信息为:

    "ORA-06550: 第 1 行, 第 7 列: "nPLS-00306: 调用 'SP_S_CITY_SEARCH' 时参数个数或类型错误"nORA-06550: 第 1 行, 第 7 列: "nPL/SQL: Statement ignored"

    或者:

    "未将对象引用设置到对象的实例。"

    于是我们做如下规定:遇到类似上面的IF语句,我们这样处理:

    IF V_STARTRECORD := 0 THEN

          OPEN RCT2 FOR

             SELECT S_RECORDCOUNT FROM DUAL;

       ELSE

          OPEN RCT2 FOR

             SELECT * FROM DUAL;

    END IF;

     注意这里统一使用 SELECT * FROM DUAL; 因为该语句返回的结果是:

     低层框架会自动过滤 包含DUMMY字段的表,使之返回的整个DataSet与Sql版本一致。

     

     

    同时这里再强调下:

    对于Oracle中的每个返回结果集的 游标一定要使用到(也就是千万不要出现“未执行语句句柄”bug),如果没使用到千万不要定义,或者因条件不成立而没执行的结果集游标就按上面的方法进行处理,让它返回字段名为:DUMMY的表,让框架自动过滤掉该表!

    还有要防止结果集游标的滥用,我们看如下的例子其实只需定义一个返回结果集游标即可。

    CREATE OR REPLACE PROCEDURE SP_S_TEST

    (

     S_OFFICEID IN VARCHAR2,

     S_SYSTEMNO IN VARCHAR2,

     RCT1       OUT PACKAGE_FRTNET.REFCURSOR

    ) AS

     V_HASOFFICE        INTEGER;

     V_SYSTEMNOCOUNT    INTEGER;

     V_SELECTSTRING     VARCHAR(4000);

    BEGIN

     SELECT COUNT(1) INTO   V_HASOFFICE FROM   SB_OFFICE;

       IF (V_HASOFFICE <= 0) THEN

            BEGIN

                 OPEN RCT1 FOR SELECT * FROM TABLE1;

                 RETURN;  

            END;

        ELSE

           BEGIN

                OPEN RCT1 FOR SELECT * FROM DUAL;

                RETURN;

           END;

     END IF;

     IF (S_SYSTEMNO IS NULL) THEN

            IF (V_SYSTEMNOCOUNT > 0) THEN

                   OPEN RCT1 FOR    SELECT * FROM TABLE2;

            ELSE

                   OPEN RCT1 FOR    SELECT * FROM   TABLE3;

            END IF;

     ELSE

            IF (V_SYSTEMNOCOUNT > 0) THEN

                 OPEN RCT1 FOR   SELECT * FROM   TABLE4;

            ELSE

                 OPEN RCT1 FOR   SELECT * FROM   TABLE5;

            END IF;

     END IF;

    END;

     

    4.4.12  触发器使用注意事项

    现在我们整个FR系统使用的Oracle数据库的触发器主要用于包含时间戳字段的表。

    我们约定如果某个表包含时间戳字段,那么该字段名称为:TIMESTAMP

    同时为该表建立如下统一格式的触发器:

    CREATE OR REPLACE TRIGGER TR_TABLENAME

    BEFORE INSERT OR UPDATE ON TABLENAME

    FOR EACH ROW

    BEGIN

    IF INSERTING THEN

     :NEW.TIMESTAMP := 0;

    ELSE

       :NEW.TIMESTAMP := :OLD.TIMESTAMP + 1;

    END IF;

    END;

    4.4.13  使用GOTO语句替换SQL的CONTINUE语句

    由于Oracle中不能使用CONTINUE语句,类似于SQL中的CONTINUE则转化为GOTO语句

    原SQL处理方式:

    DECLARE @V_NUM INT

    DECLARE @V_SUM INT

    SELECT @V_NUM = 1,@V_SUM =0;

    BEGIN

       WHILE @V_NUM <= 4

       BEGIN

        IF (@V_NUM = 3)

        BEGIN

           SET @V_NUM = @V_NUM + 1;

           CONTINUE

        END

        SET @V_SUM = @V_SUM + @V_NUM;

        PRINT(@V_NUM);

        IF @V_NUM < 4

        BEGIN

          PRINT('+');  

        END

        SET @V_NUM = @V_NUM + 1;

       END;

     PRINT('=');

     PRINT(@V_SUM);

    END;

    现Oracle处理方式:

    DECLARE

       V_NUM INTEGER := 1;

       V_SUM INTEGER := 0;

    BEGIN

     <<LABEL1>>

       WHILE V_NUM <= 4 LOOP  

       IF V_NUM = 3 THEN

           V_NUM := V_NUM + 1;

           GOTO LABEL1;

       END IF;

      

        V_SUM := V_SUM + V_NUM;

        DBMS_OUTPUT.PUT_LINE(V_NUM);

          IF V_NUM < 4 THEN

            DBMS_OUTPUT.PUT_LINE('+');

          END IF;

        V_NUM := V_NUM + 1;

       END LOOP;

       DBMS_OUTPUT.PUT_LINE('=');

       DBMS_OUTPUT.PUT_LINE(V_SUM);

    END;

     

    4.4.14 其他注意事项

    1.Oracle没有 WITH(NOLOCK)

    2.对于插入语句Sql中允许使用 INSERT "INSERT INTO,

    但Oracle中只允许使用INSERT INTO

    3.Sql的系统表为: SYSOBJECTS ,Oracle的系统表为: DBA_OBJECTS

    4.Oracle不允许有dbo.表名的使用

    5. SQL的跳出循环使用的关键字为:BREAK,ORACLE跳出循环使用的关键字为:EXIT  

    6.执行DROP TABLE TBALENAME TRUNCATE TABLE TBALENAME 时,

    默认帮你执行了COMMIT,所以在使用事务级别的临时表时要小心

    7.原来SQL的 CHAR(10)CHAR(13)  在ORACLE中为 CHR(10和 CHR(13)    

    8.sql@@Rowcount全局变量,在Oracle则是用SQL%ROWCOUNT

    9.sql中的GOTO的标签格式为:  LABEL:  ,Oracle的GOTO的标签格式为:  <<LABEL>>

     调用标签后的语句都为 GOTO LABEL;

    10.动态给变量赋值:

    DECLARE          

                V_COUNT    INT;

                V_USERID   VARCHAR2(50);            

    BEGIN

    EXECUTE IMMEDIATE 'SELECT COUNT(*), MAX(USR_ID) FROM SB_USER ' INTO V_COUNT,V_USERID;

    DBMS_OUTPUT.PUT_LINE(V_COUNT || V_USERID);

    END;

    11.绑定变量的使用:

     DECLARE           

               V_USERNAME    VARCHAR2(50);   

               V_ID          VARCHAR2(50):= '073C0OY3760H0';    

    BEGIN

    EXECUTE IMMEDIATE 'SELECT USR_NAME FROM SB_USER WHERE USR_ID = :ID' INTO V_USERNAME USING V_ID ;

    DBMS_OUTPUT.PUT_LINE(V_USERNAME);

    END;

    12.如果存储过程中包含临时表,最好在 AS  BEGIN 后进行所有临时表数据清空操作。防止事务或者会话没控制好未让Oracle自动清除临时表数据,导致两次调用存储过程,临时表数据累加的情况出现。

    如:

    CREATE OR REPLACE PROCEDURE SP_NAME

    (   S_PARA1   IN       VARCHAR2,

        S_PARA2   IN       VARCHAR2,      

        RCT1      OUT      PACKAGE_FRTNET.refCursor )

    AS   

         V_VARIABLE1     VARCHAR2(20);

    BEGIN

       DELETE FROM TMP_MODULE_TEMPTABLENAME;

       INSERT INTO TMP_MODULE_TEMPTABLENAME SELECT COL1,COL2,COL3 FROM SB_TABLE;

       OPEN RCT1 FOR SELECT TMP_MODULE_TEMPTABLENAME;

    END SP_NAME;

    13.对于以下情况的存储过程要注意结果集输出语句写法

    CREATE OR REPLACE PROCEDURE SP_OZ_ACCESSORIES_LIST

    (S_FILTERSTR_IN IN VARCHAR2,                                           

     S_ROLEID       IN VARCHAR2,

    S_USERID       IN VARCHAR2,

    RCT1           OUT PACKAGE_FRTNET.REFCURSOR )

    AS

       V_RECORDCOUNT             INTEGER;

    BEGIN

      SP_FILTER_DATARIGHT_X(S_ROLEID,

                            S_USERID,

                            'OZ_BK_HEADER',

                            'CC',

                            'QUERY',

                            V_ROLECONDITION); --调用其他存储过程的用法   

     IF (V_ROLECONDITION IS NULL) THEN

         BEGIN

            V_ROLECONDITION := '(1=1)';

         END;

     END IF;

    SELECT COUNT(BLACC_ID) INTO V_RECORDCOUNT FROM TMP_OZ_ACCESSORY_BLACC_ID WHERE || V_ROLECONDITION;

    OPEN RCT1 FOR SELECT V_RECORDCOUNT FROM DUAL;

    END;

    以上结果集输出为: ,但是列名为 :B1   返回到Appserver端无法识别该列名将抛出异常。

    我们必须要输出语句改为:

        OPEN RCT1 FOR 'SELECT''' || V_RECORDCOUNT || ''' AS COLCOUNT FROM DUAL'; 

    也就是说V_RECORDCOUNT是变量,必须使用动态Sql语句。这样的结果集输出为:

  • 相关阅读:
    Principle of Computing (Python)学习笔记(5) BFS Searching + Zombie Apocalypse
    《Java从入门到精通》src9-25
    《Java从入门到精通》src0-8
    windows查看某个端口被谁占用
    css selector: xpath:
    awk 正则表达式
    Centos系统各种日志存详解
    mysql日志文件
    mysql主键设置成auto_increment时,进行并发性能測试出现主键反复Duplicate entry &#39;xxx&#39; for key &#39;PRIMARY&#39;
    递归函数时间复杂度分析
  • 原文地址:https://www.cnblogs.com/kenchell/p/1367433.html
Copyright © 2011-2022 走看看