SQL PL/SQL語法手冊


SQL  PL/SQL語法手冊

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

目   錄

 

第一部分  SQL語法部分 3

一、 CREATE TABLE 語句 3

二、 CREATE SEQUENCE語句 5

三、 CREATE VIEW語句 6

四、 INSERT語句: 7

五、 UPDATE語句: 9

六、 DELETE語句: 10

七、 TRUNCATE語句: 11

八、 各類FUNCTIONS: 12

1. 轉換函數: 12

2. 日期函數 16

3. 字符函數 20

4. 數值函數 28

5. 單行函數: 33

6. 多行函數 35

第二部分  PL/SQL語法部分 41

一、 PL/SQL語言簡介 41

二、 變量說明 48

三、 PL/SQL控制程序流 52

四、 存儲過程 54

五、 存儲函數 54

六、 PACKAGE 54

七、 觸發器 56

八、 應用實例 58

 

 

 

 

 


第一部分  SQL語法部分

 

 

一、 Create table 語句

 

語句:   CREATE TABLE [schema.]table_name

     ( { column datatype [DEFAULT expr] [column_constraint] ...

       | table_constraint}

    [, { column datatype [DEFAULT expr] [column_constraint] ...

       | table_constraint} ]...)

    [ [PCTFREE  integer] [PCTUSED  integer]

      [INITRANS integer] [MAXTRANS integer]

      [TABLESPACE tablespace]

      [STORAGE storage_clause]

      [ RECOVERABLE | UNRECOVERABLE ]

    [  PARALLEL ( [ DEGREE { integer | DEFAULT } ]

                  [ INSTANCES { integer | DEFAULT } ]

                )

     | NOPARALLEL ]

    [  CACHE | NOCACHE  ]

    | [CLUSTER cluster (column [, column]...)] ]

    [ ENABLE   enable_clause

    | DISABLE disable_clause ] ...

[AS subquery]

表是Oracle中最重要的數據庫對象,表存儲一些相似的數據集合,這些數據描述成若干列或字段.create table 語句的基本形式用來在數據庫中創建容納數據行的表.create table 語句的簡單形式接收表名,列名,列數據類型和大小.除了列名和描述外,還可以指定約束條件,存儲參數和該表是否是個cluster的一部分.

Schema 用來指定所建表的owner,如不指定則為當前登錄的用戶.

Table_name 用來指定所創建的表名,最長為30個字符,但不可以數字開頭(可為下划線),但不可同其它對象或Oracle的保留字沖突.

   Column 用來指定表中的列名,最多254個.

Datatype 用來指定列中存儲什么類型的數據,並保證只有有效的數據才可以輸入.

column_constraint 用來指定列約束,如某一列不可為空,則可指定為not null.

table_constraint 用來指定表約束,如表的主鍵,外鍵等.

Pctfree 用來指定表中數據增長而在Oracle塊中預留的空間. DEFAULT為10%,也就是說該表的每個塊只能使用90%,10%給數據行的增大時使用.

Pctused 用來指定一個水平線,當塊中使用的空間低於該水平線時才可以向該中加入新數據行.

Parallel 用來指定為加速該表的全表掃描可以使用的並行查詢進程個數.

Cache 用來指定該表為最應該緩存在SGA數據庫緩沖池中的候選項.

Cluster 用來指定該表所存儲的 cluster.

Tablespace 用來指定用數據庫的那個分區來存儲該表的數據.

Recoverable|Unrecoverable 用來決定是否把對本表數據所作的變動寫入Redo 文件.以恢復對數據的操作.

As 當不指定表的各列時,可利用As子句的查詢結果來產生數據庫結構和數據.

例:

   1) create table mytab1e(mydec decimal,

                       myint inteter)

                 tablespace user_data

                 pctfree   5

                 pctused   30;

   2) create table mytable2

             as ( select * from mytable1);

二、 
create sequence語句

 

語句:  CREATE SEQUENCE [schema.]sequence_name

[INCREMENT BY integer] 

    [START WITH integer]

    [MAXVALUE integer | NOMAXVALUE]

    [MINVALUE integer | NOMINVALUE]

    [CYCLE | NOCYCLE]

    [CACHE integer | NOCACHE]

    [ORDER | NOORDER]

序列用來為表的主鍵生成唯一的序列值.

Increment by 指定序列值每次增長的值

Start with 指定序列的第一個值

Maxvalue 指定產生的序列的最大值

Minvalue 指定產生的序列的最小值

Cycle 指定當序列值逵到最大或最小值時,該序列是否循環.

Cache 指定序列生成器一次緩存的值的個數

Order 指定序列中的數值是否按訪問順序排序.

例:

    1) create sequence myseq

         increment by 4

         start with 50

         maxvalue 60

         minvalue 50

         cycle 

         cache 3;

2)

   sql> create sequence new_s;

   sql>insert into new (new_id,last_name,first_name)

       values(new_s.nextval,daur,permit);

 

 

 

 

 

三、 
create view語句 

 

語句: CREATE [OR REPLACE] [FORCE | NOFORCE] VIEW [schema.]view_name

    [(alias [,alias]...)]

    AS subquery

    [WITH CHECK OPTION [CONSTRAINT constraint]]

視圖實際上是存儲在數據庫上旳 select語句.每次在sql語句中使用視圖時,表示該視圖的select語句就用來得到需要的數據.

Or replace 創建視圖時如果視圖已存在,有此選項,新視圖會覆蓋舊的

           視圖.

Force 如有此選項,當視圖基於的表不存在或在該模式中沒有創建視圖的權限時,也可以建立視圖.

As subquery 產生視圖的select查詢語句

With check option 如果視圖是基於單表的且表中所有的非空列都包含在視圖中時,該視圖可用於insert和update語句中,本                選項保證在每次插入或更新數據后,該數據可以在視                  圖中查到

例:

1) create or place view new_v 

as

   select substr(d.d_last_name,1,3),

      d.d_lastname,d.d_firstname,b.b_start_date,b.b_location

   from new1 d,

        new2 b

   where d.d_lastname=b.b_lastname;

四、 
INSERT語句:

1. 語法

INSERT INTO [schema.]{table | view | subquery }[@dblink]

    [ (column [, column] ...) ]

    {VALUES (expr [, expr] ...) | subquery}

    [WHERE condition]

 

2. 插入單行

使用VALUES關鍵詞為新行的每一列指定一個值.如果不知道某列的值,可以使用NULL關鍵詞將其值設為空值(兩個連續的逗號也可以表示空值,也可使用NULL關鍵詞)

插入一行時試圖為那些NOT NULL的列提供一個NULL值,會返回錯誤信息.

 

舉例:

插入一條記錄到DEPARTMENT表中

 

 

INSERT INTO DEPARTMENT

       (DEPARTMENT_ID,NAME,LOCATION_ID)

VALUES (01,COMPUTER,167)

 

3. 插入多行

將SELECT語句檢索出來的所有數據行都插入到表中.這條語句通常在從一個表向另一個表快速復制數據行.

 

舉例:

INSERT INTO ORDER_TEMP

SELECT A.ORDER_ID,B.ITEM_ID,C.NAME,E.FIRST_NAME||'.'||E.LAST_NAME,

       A.ORDER_DATE,A.SHIP_DATE,D.DESCRIPTION,B.ACTUAL_PRICE,

       B.QUANTITY,B.TOTAL

  FROM SALES_ORDER A,    ITEM B,  CUSTOMER C,

       PRODUCT D,        EMPLOYEE E

 WHERE MONTHS_BETWEEN(TO_DATE(A.ORDER_DATE),TO_DATE('01-7月-91'))>0

       AND A.CUSTOMER_ID=C.CUSTOMER_ID

       AND C.SALESPERSON_ID=E.EMPLOYEE_ID

       AND A.ORDER_ID=B.ORDER_ID

       AND B.PRODUCT_ID=D.PRODUCT_ID

 

4. 從其它表復制數據:

要快速地從一個表向另一個尚不存在的表復制數據,可以使用CREATE TABLE語句定義該表並同時將SELECT語句檢索的結果復制到新表中.

CREATE TABLE EMPLOYEE_COPY

      AS

      SELECT * 

        FROM EMPLOYEE

五、 
UPDATE語句:

1. 語法

UPDATE [schema.]{table | view | subquery}[@dblink] [alias]

    SET { (column [, column] ...) = (subquery)

        |  column = { expr | (subquery) } }

     [,    { (column [, column] ...) = (subquery)

        |  column = { expr | (subquery) } } ] ...

    [WHERE condition]

 

UPDATE語句更新所有滿足WHERE子句條件的數據行.同樣,該語句可以用SELECT語句檢索得到.但SELECT必須只檢索到一行數據值.否則報錯.而且每更新一行數據,均要執行一次SELECT語句.

 

舉例:

UPDATE EMPLOYEE_COP

   SET SALARY=

       SALARY-400

 WHERE TO_NUMBER(TO_CHAR(HIRE_DATE,'YYMMDD'))<850101

 

 UPDATE ITEM_COP A

    SET A.ACTUAL_PRICE=

      (

      SELECT B.LIST_PRICE

        FROM PRICE B,SALES_ORDER C

       WHERE A.PRODUCT_ID=B.PRODUCT_ID AND

             A.ORDER_ID=C.ORDER_ID AND

             TO_NUMBER(TO_CHAR(C.ORDER_DATE,'YYYYMMDD')) BETWEEN

             TO_NUMBER(TO_CHAR(B.START_DATE,'YYYYMMDD')) AND

             NVL(TO_NUMBER(TO_CHAR(END_DATE,'YYYYMMDD')),29991231)

      )

六、 
DELETE語句:

1. 語法

DELETE [FROM] [schema.]{table | view}[@dblink] [alias]

    [WHERE condition]

 

DELETE語句刪除所有滿足WHERE子句條件的數據行.

 

舉例:

DELETE FROM item

WHERE ORDER_ID=510

七、 
TRUNCATE語句:

1. 語法

TRUNCATE [schema.]table

 

 

八、 
各類Functions:

 

1. 轉換函數:

 

1.1. 函數:TO_CHAR

語法:

    TO_CHAR(number[,format])

 

用途:

將一個數值轉換成與之等價的字符串.如果不指定格式,將轉換成最簡單的字符串形式.如果為負數就在前面加一個減號.

 

Oracle為數值提供了很多格式,下表列出了部分可接受的格式:

元素

描述

示例

結果

9

返回指定位數的數值,前面為0,顯示為空格

99999

784

-578

1234567

45.895

‘   784

‘  -578

######

‘    46

插入小數點

9999.99

784

45.3482

784.00

45.35

在結果串的指定位置插入逗號

9,999,999

784

1234567

0.44

‘       784

‘ 1,234,567

‘         0

$

返回值前面加一個元符號

$99,999

784

-578

‘    $784

‘   -$578

B

結果的整數部分如果是0,就顯示成空格

B9999.9

784

0.44

‘  784.0

‘     .4

S

返回 有正負號的數值

S9999

784

+784

EEEE

以科 計數法表示數值

9.9EEEE

45

0.0666

‘  4.5E+01

‘  6.7E-02

 

 

 

 

1.2. 
函數:TO_CHAR

 

語法:

    TO_CHAR(date[,format])

 

用途:

將按format參數指定的格式將日期值轉換成相應的字符串形式.同樣,Oracle提供許多的格式模型,用戶可以用它們的組合來表示最終的輸出格式.唯一限制就是最終的掩碼不能超過22個字符.下表列出了部分日期格式化元素.

 

Oracle為數值提供了很多格式,下表列出了部分可接受的格式:

 

格式

意義

D

用數字表示星期幾(1,2,3,4,5,6,7)

DY

用三個字符表示星期幾的縮寫形式(MON)

DAY

星期幾的完整表示(MONDAY)

DD

用數字表示一月中的幾號

DDD

用數字表示年份中的天數

W

一月中的星期數

WW

一年中的星期數

MM

用數字表示月數

MON

用三個字母表示月的縮寫(APR)

MONTH

月的完整英文表示(FEBRUARY)

Y

年份中的最后一個數字(9)

YY

年份中的最后二個數字(99)

YYY

年份中的最后三個數字(999)

YYYY

年份用四個數字表示(1999)

YEAR

年份的字母全部拼寫(NINETEEN-NINETY-NINE)

AM或PM

午前或午后表示符

HH

用小時表示日期

MI

分鍾表示小時

SS

秒鍾表示分鍾

SSSS

自午夜以來的秒數(這個數字經常在0-86399之間)

 

 

 

 

 

 

1.3. 
函數:TO_DATE

 

語法:

    TO_DATE(string,format)

 

用途:

根據給定的格式將一個字符串轉換成Oracle的日期值.

該函數的主要用途是用來驗證輸入的日期值.在應用程序中,用戶必須驗證輸入日期是否有效,如月份是否在1~12之間和日期中的天數是否在指定月份的天數內.

 

1.4. 
函數:TO_NUMBER

 

語法:

    TO_NUMBER(string[,format])

 

用途:

該函數將一個字符串轉換成相應的數值.對於簡單的字符串轉換數值(例如幾位數字加上小數點).格式是可選的.

 

 

2. 
日期函數

 

2.1. 函數:ADD_MONTHS

 

語法:

    ADD_MONTHS(date,number)

 

用途:

在日期date上加指定的月數,返回一個新日期.如果給定為負數,返回值為日期date之前幾個月的日期.number應當是個整數,如果是小數,正數被截為小於該數的最大整數,負數被截為大於該數的最小整數.

 

例如:

    SELECT TO_CHAR(ADD_MONTHS(sysdate,1),

               'DD-MON-YYYY') "Next month"

      FROM dual

 

Next month

-----------

19-FEB-2000

 

 

2.2. 函數:LAST_DAY

 

語法:

    LAST_DAY(date)

 

用途:

返回日期date所在月份的最后一天的日期.

 

例如:

    SELECT SYSDATE, LAST_DAY(SYSDATE) "Last",

           LAST_DAY(SYSDATE) - SYSDATE "Days Left"

      FROM DUAL

 

SYSDATE   Last       Days Left

--------- --------- ----------

19-JAN-00 31-JAN-00         12

 

2.3. 函數:MONTHS_BETWEEN

 

語法:

    MONTHS_BETWEEN(date1,date2)

 

用途:

返回兩個日期之間的月份.如果兩個日期月份內的天數相同(或者都是某個月的最后一天),返回值是整數.否則,返回值是小數,每於1/31月來計算月中剩余天數.如果第二個日期比第一個日期還早,則返回值是負數.

 

例如:

    SELECT MONTHS_BETWEEN(TO_DATE('02-02-1992', 'MM-DD-YYYY'),

                      TO_DATE('01-01-1992', 'MM-DD-YYYY'))

    "Months"

         FROM DUAL

 

        Months

    ----------

    1.03225806

 

    SELECT MONTHS_BETWEEN(TO_DATE('02-29-1992', 'MM-DD-YYYY'),

                        TO_DATE('01-31-1992', 'MM-DD-YYYY'))

    "Months"

    FROM DUAL

 

    Months

----------

         1

 

 

 

 

 

 

 

 

2.4. 函數:NEXT_DAY

 

語法:

    NEXT_DAY(date,day)

 

用途:

該函數返回日期date指定若天后的日期.注意:參數day必須為星期,可以星期幾的英文完整拼寫,或前三個字母縮寫,或數字1,2,3,4,5,6,7分別表示星期日到星期六.例如,查詢返回本月最后一個星期五的日期.

 

例如:

    SELECT NEXT_DAY((last_day(sysdate)-7),'FRIDAY')

      FROM dual

 

NEXT_DAY(

---------

28-JAN-00

 

 

2.5. 函數:ROUND

 

語法:

    NEXT_DAY(date[,format])

 

用途:

該函數把一個日期四舍五入到最接近格式元素指定的形式.如果省略format,只返回date的日期部分.例如,如果想把時間(24/01/00 14:58:41)四舍五入到最近的小時.下表顯示了所有可用格式元素對日期的影響.

 

Format Element

Result

SS

24/01/00 14:58:41

MI

24/01/00 14:59:00

HH

24/01/00 15:00:00

DD

25/01/00 00:00:00

MM

01/02/01 00:00:00

YY

01/01/00 00:00:00

CC

01/01/00 00:00:00

 

例如:

    SELECT to_char(ROUND(sysdate,'HH'),'DD-MON-YY HH24:MI:SS')

      FROM dual

 

TO_CHAR(ROUND(SYSDATE,'HH'),'DD-MON-YYHH24:MI:SS')

-----------------------------------------------------------------

24-JAN-00 15:00:00

 

2.6. 函數:TRUNC

 

語法:

    TRUNC(date[,format])

 

用途:

TRUNC函數與ROUND很相似,它根據指定的格式掩碼元素,只返回輸入日期用戶所關心的那部分,與ROUND有所不同,它刪除更精確的時間部分,而不是將其四舍五入.

 

例如:

    SELECT TRUNC(sysdate)

      FROM dual

 

TRUNC(SYS

---------

24-JAN-00

 

FLOOR函數:求兩個日期之間的天數用;

select floor(sysdate - to_date('20080805','yyyymmdd')) from dual;

 

 

3. 
字符函數

3.1. 函數:ASCII

 

語法:

ASCII(character)

 

用途:

返回指定字符的ASCII碼值.如果為字符串時,返回第一個字符的ASCII碼值.

 

例如:

   SELECT ASCII('Z')

     FROM dual

 

ASCII('Z')

----------

        90

 

 

3.2. 函數:CHR

 

語法:

CHR(number)

 

用途:

該函數執行ASCII函數的反操作,返回其ASCII碼值等於數值number的字符.該函數通常用於向字符串中添加不可打印字符.

 

例如:

    SELECT CHR(65)||'BCDEF'

      FROM dual

 

CHR(65

------

ABCDEF

 

 

3.3. 
函數:CONCAT

 

語法:

CONCAT(string1,string2)

 

用途:

該函數用於連接兩個字符串,將string2跟在string1后面返回,它等價於連接操作符(||).

 

例如:

    SELECT CONCAT(This is a,’ computer)

      FROM dual

 

CONCAT('THISISA','

------------------

This is a computer

它也可以寫成這樣:

    SELECT This is a||’ computer

      FROM dual

 

'THISISA'||'COMPUT

------------------

This is a computer

這兩個語句的結果是完全相同的,但應盡可能地使用||操作符.

 

 

3.4. 函數:INITCAP

 

語法:

INITCAP(string)

 

用途:

該函數將字符串string中每個單詞的第1個字母變成大寫字母,其它字符為小寫字母.

 

 

 

 

 

例如:

    SELECT INITCAP(first_name||'.'||last_name)

      FROM employee

     WHERE department_id=12

 

INITCAP(FIRST_NAME||'.'||LAST_N

-------------------------------

Chris.Alberts

Matthew.Fisher

Grace.Roberts

Michael.Douglas

 

 

3.5. 函數:INSTR

 

語法:

INSTR(input_string,search_string[,n[,m]])

 

用途:

該函數是從字符串input_string的第n個字符開始查找搜索字符串的第m次出現,如果沒有找到搜索的字符串,函數將返回0.如果找到,函數將返回位置.

 

例如:

    SELECT INSTR('the quick sly fox jumped over the 

           lazy brown dog','the',2,1)

      FROM dual

 

INSTR('THEQUICKSLYFOXJUMPEDOVERTHELAZYBROWNDOG','THE',2,1)

----------------------------------------------------------

                                                        31

 

 

 

 

 

 

 

 

3.6. 函數:INSTRB

 

語法:

INSTRB(input_string,search_string[,n[,m]])

 

用途:

該函數類似於INSTR函數,不同之處在於INSTRB函數返回搜索字符串出現的字節數,而不是字符數.在NLS字符集中僅包含單字符時,INSTRB函數和INSTR函數是完全相同的.

 

 

3.7. 函數:LENGTH

 

語法:

LENGTH(string)

 

用途:

該函數用於返回輸入字符串的字符數.返回的長度並非字段所定義的長度,而只是字段中占滿字符的部分.以列實例中,字段first_name定義為varchar2(15).

 

語法:

    SELECT first_name,LENGTH(first_name)

      FROM employee

 

FIRST_NAME      LENGTH(FIRST_NAME)

--------------- ------------------

JOHN                             4

KEVIN                            5

 

3.8. 函數:LENGTHB

 

語法:

LENGTHB(string)

 

用途:

該函數用於返回輸入字符串的字節數.對於只包含單字節字符的字符集來說LENGTHB函數和LENGTH函數完全一樣.

 

 

3.9. 函數:LOWER

 

語法:

LOWER(string)

 

用途:

該函數將字符串string全部轉換為小寫字母,對於數字和其它非字母字符,不執行任何轉換.

 

 

3.10. 函數:UPPER

 

語法:

UPPER(string)

 

用途:

該函數將字符串string全部轉換為大寫字母,對於數字和其它非字母字符,不執行任何轉換.

 

 

3.11. 函數:LPAD

 

語法:

LPAD(string,length[,set])

 

用途:

在字符串string的左邊加上一個指定的字符集set,從而使串的長度達到指定的長度length.參數set可以是單個字符,也可以是字符串.如果string的長度小於length時,取string字符串的前length個字符.

 

語法:

    SELECT first_name,LPAD(first_name,20,' ')

      FROM employee

 

FIRST_NAME      LPAD(FIRST_NAME,20,'')

--------------- -----------------------------------------

JOHN                            JOHN

KEVIN                          KEVIN

3.12. 函數:RPAD

 

語法:

RPAD(string,length[,set])

 

用途:

在字符串string的右邊加上一個指定的字符集set,從而使串的長度達到指定的長度length.參數set可以是單個字符,也可以是字符串.如果string的長度小於length時,取string字符串的前length個字符.

 

例如:

    SELECT first_name,rpad(first_name,20,'-')

      FROM employee

 

FIRST_NAME      RPAD(FIRST_NAME,20,'-')

--------------- -----------------------------------------

JOHN            JOHN----------------

KEVIN           KEVIN---------------

 

 

3.13. 函數:LTRIM

 

語法:

LTRIM(string[,set])

 

用途:

該函數從字符串的左邊開始,去掉字符串set中的字符,直到看到第一個不在字符串set中的字符為止.

 

例如:

    SELECT first_name,ltrim(first_name,'BA')

      FROM employee

     WHERE first_name='BARBARA'

 

FIRST_NAME      LTRIM(FIRST_NAM

--------------- ---------------

BARBARA         RBARA

 

3.14. 函數:RTRIM

 

語法:

RTRIM(string[,set])

 

用途:

該函數從字符串的右邊開始,去掉字符串set中的字符,直到看到第一個不在字符串set中的字符為止.具有NULL值的字段不能與具有空白字符的字段相比較.

這是因為空白字符與NULL字符是完全不同的兩種字符.該函數的另外一個用途是當進行字段連接時去掉不需要的字符.

 

3.15. 函數:SUBSTR

 

語法:

SUBSTR(string,start[,length])

 

用途:

該函數從輸入字符串中取出一個子串,從start字符處開始取指定長度的字符串,如果不指定長度,返回從start字符處開始至字符串的末尾.

 

3.16. 函數:REPLACE

 

語法:

REPLACE(string,search_set[,replace_set])

 

用途:

該函數將字符串中所有出現的search_set都替換成replace_set字符串.可以使用該函將字符串中所有出現的符號都替換成某個有效的名字.如果不指定replace_set,則將從字符串string中刪除所有的搜索字符串search_set.

 

例如:

SELECT REPLACE('abcdefbdcdabc,dsssdcdrd','abc','ABC')

  FROM dual

 

REPLACE('ABCDEFBDCDABC,

-----------------------

ABCdefbdcdABC,dsssdcdrd

3.17. 函數:TRANSLATE

 

語法:

TRANSLATE(string,search_set,replace_set)

 

用途:

該函數用於將所有出現在搜索字符集search_set中的字符轉換成替換字符集replace_set中的相應字符.注意:如果字符串string中的某個字符沒有出現在搜索字符集中.則它將原封不動地返回.如果替換字符集replace_set比搜索字符集search_set小,那么搜索字符集search_set中后面的字符串將從字符串string中刪除.

 

例如:

SELECT TRANSLATE('GYK-87M','0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',

                 9999999999xxxxxxxxxxxxxx')

  FROM dual

 

TRANSL

------

xx-99x

 

 

 

 

 

 

 

 

 

 

 

4. 
數值函數

4.1. 函數:ABS

 

語法:

ABS(number)

 

用途:

該函數返回數值number的絕對值.絕對值就是一個數去掉符號的那部分.

 

 

4.2. 函數:SQRT

 

語法:

SQRT(number)

 

用途:

該函數返回數值number的平方根,輸入值必須大於等於0,否則返回錯誤.

 

 

4.3. 函數:CEIL

 

語法:

CEIL(number)

 

用途:

該函數返回大於等於輸入值的下一個整數.

 

 

4.4. 函數:FLOOR

 

語法:

FLOOR(number)

 

用途:

該函數返回小於等於number的最大整數.

4.5. 
函數:MOD

 

語法:

MOD(n,m)

 

用途:

該函數返回n除m的模,結果是n除m的剩余部分.m,n可以是小數,負數.

 

 

4.6. 函數:POWER

 

語法:

POWER(x,y)

 

用途:

該函數執行LOG函數的反操作,返回x的y次方.

 

 

4.7. 函數:ROUND

 

語法:

ROUND(number,decimal_digits)

 

用途:

該函數將數值number四舍五入到指定的小數位.如果decimal_digits為0,則返回整數.decimal_digits可以為負數.

 

4.8. 函數:TRUNC

 

語法:

TRUNC(number[,decimal_pluces])

 

用途:

該函數在指定的小數字上把一個數值截掉.如果不指定精度,函數預設精度為0. decimal_pluces可以為負數.

4.9. 
函數:SIGN

語法:

SIGN(number)

 

用途:

該函數返回number的符號,如果number為正數則返回1,為負數則返回-1,為0則返回0.

 

 

4.10. 函數:SIN

 

語法:

SIN(number)

 

用途:

該函數返回弧度number的正弦值.

 

 

4.11. 函數:SINH

 

語法:

SINH(number)

 

用途:

該函數返回number的返正弦值.

 

4.12. 函數:COS

 

語法:

COS(number)

 

用途:

該函數返回弧度number的三角余弦值.要用角度計算余弦,可以將輸入值乘以0.01745轉換成弧度后再計算.

4.13. 
函數:COSH

 

語法:

COSH(number)

 

用途:

該函數返回輸入值的反余弦值.

 

 

4.14. 函數:TAN

 

語法:

TAN(number)

 

用途:

該函數返回弧度number的正切值.

 

 

4.15. 函數:TANH

 

語法:

TANH(number)

 

用途:

該函數返回數值number的反正切值.

 

 

4.16. 函數:LN

 

語法:

LN(number)

 

用途:

該函數返回number自然對數.

4.17. 
函數:EXP

 

語法:

EXP(number)

 

用途:

該函數返回e(2.71828183)的number次方.該函數執行自然對數的反過程.

 

 

4.18. 函數:LOG

 

語法:

LOG(base,number)

 

用途:

該函數返回base為底,輸入值number的對數.

 

 

5. 
單行函數:

單行函數中可以對任何數據類型的數據進行操作.

 

5.1. 函數:DUMP

語法:

DUMP(expression[,format[,start[,length]]])

 

用途:

該函數按指定的格式顯示輸入數據的內部表示.下表列出了有效的格式.

格式代碼

描述

8

八進制

10

十進制

16

十六進制

17

單字符

 

例如:

    SELECT DUMP('FARRELL',16)

    FROM dual

 

DUMP('FARRELL',16)

----------------------------------

Typ=96 Len=7: 46,41,52,52,45,4c,4c

 

5.2. 函數:GREATEST

語法:

GREATEST(list of values)

 

用途:

該函數返回列表中項的最大值.對數值或日期來說,返回值是最大值或最晚日期,如果列表中包含字符串,返回值是按字母順序列表中的最后一項.

 

例如:

    SELECT GREATEST(123,234,432,112)

      FROM dual

 

GREATEST(123,234,432,112)

-------------------------

                      432

5.3. 函數:LEAST

語法:

LEAST(list of values)

 

用途:

該函數返回列表中項的最小值.對數值或日期來說,返回值是最小值或最早日期,如果列表中包含字符串,返回值是按字母順序列表中的第一項.

 

例如:

    SELECT LEAST(sysdate,sysdate-10)

      FROM dual

 

LEAST(SYS

---------

10-JAN-00

 

5.4. 函數:NVL

 

語法:

NVL(expression,replacement_value)

 

用途:

如果表達式不為空值,函數返回該表達式的值,如果是空值,就返回用來替換的值.

 

例如:

    SELECT last_name, 

           NVL(TO_CHAR(COMMISSION),'NOT APPLICABLE')

      FROM employee

     WHERE department_id=30

LAST_NAME       NVL(TO_CHAR(COMMISSION),'NOTAPPLICABLE')

--------------- ----------------------------------------

ALLEN           300

WARD            500

MARTIN          1400

BLAKE           NOT APPLICABLE

6. 
多行函數

組函數可以對表達式的所有值操作,也可以只對其中不同值進行操作,組函數的語法如下所示:

function[DISTINCT|ALL expression]

如果既不指定DISTINCT,也不指定ALL,函數將對查詢返回的所有數據行進行操作.不能在同一個SELECT語句的選擇列中同時使用組函數和單行函數.

 

6.1. 函數:AVG

語法:

AVG([DISTINCT|ALL] expression)

用途:

對查詢返回的數據行求平均值.

 

例如:

    SELECT AVG(sal) "Average"

      FROM emp

       Average

    ----------

    2073.21429

 

6.2. 函數:COUNT

語法:

COUNT([DISTINCT|ALL] expression)

 

用途:

計算表達式的個數.要計算EMP表中雇員的個數.

例如:

    SELECT COUNT(deptno)

      FROM emp

COUNT(DEPTNO)

-------------

           14

    SELECT COUNT(distinct deptno)

      FROM emp

 

COUNT(DISTINCTDEPTNO)

---------------------

                    3

6.3. 函數:MAX

 

語法:

MAX([DISTINCT|ALL] expression)

 

用途:

對查詢返回的行集求最大值.如果有多個最大值,將所有均返回.要檢索公司中最高工資的雇員.

 

語法:

    SELECT ename,sal

      FROM emp

     WHERE sal=(select max(sal)

           FROM emp)

 

ENAME            SAL

---------- ---------

KING            5000

 

6.4. 函數:MIN

 

語法:

MIN([DISTINCT|ALL] expression)

 

用途:

對查詢返回的行集求最小值.如果有多個最小值,將所有均返回.

 

例如:

    SELECT MIN(last_name)

      FROM employee

 

MIN(LAST_NAME)

---------------

ADAMS

 

 

 

 

6.5. 函數:SUM

 

語法:

SUM([DISTINCT|ALL] expression)

 

用途:

計算查詢返回的所有非空數值的總和.如果返回的數據都是空值,則該函數也返回空值.

 

例如:

    SELECT SUM(salary)"Total"

      FROM employee

     WHERE department_id=10

 

    Total

---------

     8750

 

6.6. 函數:VARIANCE

 

語法:

VARIANCE([DISTINCT|ALL] expression)

 

用途:

該函數計算返回所有行的統計方差.

 

例如:

    SELECT VARIANCE(salary)

      FROM employee

 

VARIANCE(SALARY)

----------------

       973659.27

 

 

 

 

 

 

偽列

返回值

Sequence.CURRVAL

上一次由序列產生器產生的序列名值.只有在當前實例會話中從該序列選擇過一次值,這個偽列才會有效.

LEVEL

查詣的深度,LEVEL適用於特殊的樹查詢.

Sequence.NEXTVAL

選擇這個偽列將導致序列發生器返回該序列的下一個值.一旦選擇了該值,它就不能被重用,因為以后的每次檢索都將返回下一個值.

ROWID

這個偽列表示數據行確切的存儲位置.ROWID的格式是一個三個16進制數的結構AAAAAAAA.BBBB.CCCC,這里AAAAAAAA表示數據庫文件中包含該行的塊號,BBBB是數據塊內部的行號,而CCCC則是數據中的文件ID.

ROWNUM

被檢索數據行的序列號.

SYSDATE

當前日期和時間.

UID

當前用戶的標識ID.

USER

用戶登錄進數據庫的名字.

 

 

 


 TABLE: LOCATION                                部門地址表

 -------------------- -------- ----

 LOCATION_ID          NOT NULL NUMBER(3)        地址ID

 REGIONAL_GROUP                VARCHAR2(20)     地址名

 

 TABLE: DEPARTMENT                              部門名稱表

 -------------------- -------- ----

 DEPARTMENT_ID        NOT NULL NUMBER(2)        部門ID

 NAME                          VARCHAR2(14)     部門名稱

 LOCATION_ID                   NUMBER(3)        地址ID(LOCATION.LOCATION_ID)

 

 TABLE: JOB                                     工種表

 -------------------- -------- ----

 JOB_ID               NOT NULL NUMBER(3)        工種ID

 FUNCTION                      VARCHAR2(30)     工種名稱

 

 TABLE: EMPLOYEE                                雇員信息表

 -------------------- -------- ---- 

 EMPLOYEE_ID          NOT NULL NUMBER(4)        雇員ID

 LAST_NAME                     VARCHAR2(15)

 FIRST_NAME                    VARCHAR2(15)

 MIDDLE_INITIAL                VARCHAR2(1)      

 JOB_ID                        NUMBER(3)        工種ID(JOB.JOB_ID)

 MANAGER_ID                    NUMBER(4)        領導ID(EMPLOYEE.EMPLOYEE_ID)

 HIRE_DATE                     DATE             雇佣日期

 SALARY                        NUMBER(7,2)      薪水

 COMMISSION                    NUMBER(7,2)      佣金

 DEPARTMENT_ID                 NUMBER(2)        部門ID(DEPARTMENT.DEPARTMENT_ID)

 

 TABLE: SALARY_GRADE                            薪資等級表

 -------------------- -------- ----

 GRADE_ID             NOT NULL NUMBER(3)        等級ID

 LOWER_BOUND                   NUMBER(7,2)      最低工資

 UPPER_BOUND                   NUMBER(7,2)      最高工資

 

 TABLE: PRODUCT                                 產品信息表

 -------------------- -------- ----

 PRODUCT_ID           NOT NULL NUMBER(6)        品號

 DESCRIPTION                   VARCHAR2(30)     品名

 

 TABLE: PRICE                                   產品價格表

 -------------------- -------- ----

 PRODUCT_ID           NOT NULL NUMBER(6)        品號(PRODUCT.PRODUCT_ID)

 LIST_PRICE                    NUMBER(8,2)      價格

 MIN_PRICE                     NUMBER(8,2)      最低價格

 START_DATE           NOT NULL DATE             生效日期

 END_DATE                      DATE             失效日期

 

 TABLE: CUSTOMER                                客戶信息表

 -------------------- -------- ----

 CUSTOMER_ID          NOT NULL NUMBER(6)        客戶ID(CUSTOMER.CUSTOMER_ID)

 NAME                          VARCHAR2(45)     客戶名

 ADDRESS                       VARCHAR2(40)     客戶地址

 CITY                          VARCHAR2(30)     城市

 STATE                         VARCHAR2(2)      州

 ZIP_CODE                      VARCHAR2(9)      郵編

 AREA_CODE                     NUMBER(3)        區號

 PHONE_NUMBER                  NUMBER(7)        電話號碼

 SALESPERSON_ID                NUMBER(4)        銷售員ID(EMPLOYEE.EMPLOYEE_ID)

 CREDIT_LIMIT                  NUMBER(9,2)      信用限制

 COMMENTS                      LONG             備注

 

 TABLE: SALES_ORDER                             訂單單頭表

 -------------------- -------- ----

 ORDER_ID             NOT NULL NUMBER(4)        訂單ID

 ORDER_DATE                    DATE             訂單日期

 CUSTOMER_ID                   NUMBER(6)        客戶ID(CUSTOMER.CUSTOMER_ID)

 SHIP_DATE                     DATE             出貨日期

 TOTAL                         NUMBER(8,2)      總金額

 

 TABLE: ITEM                                    訂單單身表

 -------------------- -------- ----

 ORDER_ID             NOT NULL NUMBER(4)        訂單ID(SALES_ORDER.ORDER_ID)

 ITEM_ID              NOT NULL NUMBER(4)        訂單行號

 PRODUCT_ID                    NUMBER(6)        品號(PRODUCT.PRODUCT_ID)

 ACTUAL_PRICE                  NUMBER(8,2)      實際價格

 QUANTITY                      NUMBER(8)        訂單數量

 TOTAL                         NUMBER(8,2)      總金額

 

 

 

 

 

第二部分  PL/SQL語法部分

 

一、 PL/SQL語言簡介

(本講義之所有程序均調式通過)

首先我們看一個簡單之例子,下面這個例子是統計從1至100的總和.

declare

i number:=0;          /*聲明變量井給初值*/

t number:=1;

error_message exception;  /*聲明一個出錯處理*/

begin

  for t in 1..100 loop

    i:=i+t;

  end loop;

  if i>=5050 then

    raise error_message;  /*引發錯誤處理*/ 

  else

    insert into c_nt(c_t) values(i);

  end if;

exception

  when error_message then

  insert into c_nt(c_t) values(0);

end;

² 從上例中可以看出PL/SQL語法的一般規則.

­ PL/SQL中語句以分號(;)結尾.

­ 開始程序塊的PL/SQL語句(如IF或BEGIN語句)沒有分句.

­ 文本值括在單引號(‘ ‘)內,而不是(“ “).

­ 過程只允許最后有一個出口..

² PL/SQL程序可以分為三個部分

­ DECLARE部分用於變量、常量、函數、過程、Cursor.

­ BEGIN部分包含PL/SQL塊中要執行的代碼 用於程序處理,其中可以調用函數、過程.

­ Exception 部分用於出錯處理.

下面我們再看一個例子:

declare

i number :=1;

t number :=1;

p number :=1;

/*create table c_ny(c_t number,cou_t number);*/

function aa(xx number)return number is     /* define function*/

   tt number;

   ct number:=1;

    j number:=1;

begin

   while j<=xx loop

   ct:=ct+j;

   j:=j+1;

   end loop;

   return ct;

end aa;

begin

  /*create table c_nt(c_t number,cou_t number);*/

  commit;

  while i<=200 loop 

    t:=t+i;

    i:=i+1;

    p:=aa(i);      /* calling function*/

    insert into c_nt values(t,p);

    commit;

  end loop;

end;

/

 

 

 

 

 

說明:

1.在定義變量可以賦初值,賦初值有兩種方法,一為上程序所示,另一種為如下所示:

Declare 

I number default 92;

T number default 0;

 

2.定義常量

Declare

I constant number:=1;

T constant number:=9;

 

3.定義函數

function function_name(parameter type)return type is

  …declare variant

begin

  …

  …

end function_name;

在上面的例子中我們定義了一個函數aa,在begin模塊部分引用了此函數aa().

 

4.定義過程

procedure procedure_name(parameter IN type) is 

declare variant

begin

exception

end procedure_name;

 

 

 

 

見下例:

declare

/*t_emp  c_nt%rowtype;*/

i number:=1;

t number:=1;

procedure te_t(t_t number) is          /*定義一個函數*/

  begin

    insert into c_nt1(t_1) values(t_t);

end te_t;

begin

  for i in 1..100 loop

    te_t(i);

  end loop;

end;

/

 

5.定義Cursor

declare

/*t_emp  c_nt%rowtype;*/

t_emp1 number;

t_emp2 number;

cursor tes_t1

is select * from c_nt;

begin

  open tes_t1;

  delete from c_nt1;

  commit;

  loop

    fetch tes_t1 into t_emp1,t_emp2;

    exit when tes_t1%notfound;

    insert into c_nt1 values(t_emp1,t_emp2);a

  end loop;

  close tes_t1;

  commit;

end;

/

 

 

我們在open 一個cursor時,可能會存在一種情況,即我們不需要cursor中所有之記錄,我們該如何處理:

1.在定義一個cursor時,可以附帶參數如下所示

declae 

  cursor c1(p_emp_id) is 

select emp_no,emp_name from dept_no  where emp_id = p_emp_id;

demp_pt c1%rowtype;

begin 

open c1(123);

 loop

 fetch c1(123) into demp_pt

 …

 

2.在將cursor中之記錄項轉到變量中時進行控制,如下所示:

declare

  cursor is 

  select  empt_no,empt_name from dept_no;

  p_no    number;

  p_name  number;

begin 

  loop

  fetch c1 into (p_no,p_name);

  if condition1  then

   …

   …

  end if

   

end;

 

注意:

² 因為PL/SQL不支持I/O,所以程序所有結果都是放在數據檔中.

² Delete from accts where status=bad debt

If sql%rowcount>10 then

   Raise out_of_bounds;

End if;

 

另:

在聲明一個變量時,PL/SQL提供兩種變量類型:%TYPE,%ROWTYPE.

1.%TYPE

使用%TYPE時,可以有種用法:

² 一用法見下例:

declare 

Balance number(7,2);

Minimum_balance balance%type:=10.00;

在上例中,minimum_balance數據類型為number(7,2)具默認值為10.00.

² 二用法見下例(將數據類型與table中一column datatype相對應起來,如果table中column datatype變更,則在運行時,上數據類型會自動的變換上):

declare

my_dname            empc.empto%type;

 

2.%rowtype

使用%rowtype數據類型用於將table和cursor中一數據行相對起來.

見下例:

 

 

 

 

 

 

 

 

² Declare

Cursor my_cursor is select sal+nvl(comm,0) salcomm,wages,ename from emp;

My_rec my_cursor%rowtype;

Begin

Open my_cursor; 

loop

Fetch my_cursor into my_rec ;

Exit when my_cursor%notfound;

If my_rec.wages>200 then

Insert into temp values (null,my_rec.wages,my_rec.ename);

End if;

End loop;

Close my_cursor;

End;

 

 

 

 

 

 

二、 
變量說明

在PL/SQL中包括以下幾種常見的變量類型:

CHAR-存儲定長的ASCII字符串,允許存儲數字,文本文符等,最長可255個字符.

VARCHAR2-存儲變長的字符串,盡管伋按符串的最大長度來定義,但VARCHAR2和CHAR的區別在於如果達不到定義的長度,下的空間不會自動的填寫為空格,VARCHAR2最大可以放入2000個字符.

DATE-實際上是存儲時間信息的日期/時間戳,在使用日期時,應考慮怎樣使用日期函數.有關日期函數的格式見函數說明部分.

NUMBER-存儲數值數據,包括整數和浮點數、數據范圍可以從1Ï10   到38Ï10   ,而且,你有很大的數據空間.

BOOLENA-存儲布爾值.它表示是/否,真/假,1/0之類的東西.

 

LONG-這是一種文本字符串,其長度大於VARCHAR2字段的2000個字符.該類最多可儲存2 GB個字符,與原始二進制數據相比,它只能存儲字符信息.

RAW-用來存儲操作系統使用的原始二進制數據,可用於存儲像圖像或聲音記錄這樣的信息,但這種數據長度最長度只有255字節.

LONG RAW-與LONG類型等價,但存儲二進制數據,最長可達2GB個字節.

BINARY_INTEGER-這個字段按計算器使用的二進制格式存儲信息,從

       -2  到2  -1.

 

 

 

 

 

 

 

另:

PL/SQL提位兩種復合類型:TABLE和RECORD

1.TABLE

² 要定義一個數組,你使用表類型定義語句,例如要定義Last_name數組,可以使用下述語句:

type last_name_list is table of varchar2(22)

index by binary_integer;

last_name last_name_list;

 

² 當定義一個長類型時,就涉及到一個刪除表的問題,PL/SQL表不能用Delete語句來刪除,但可以將每一行空值如下所示:

sal_tab(3):=null;

另一種法是定義兩個相同類型的表類型,如果要將另一表清空,只需將空表給要清空的表即可.如下所示.

declare 

type numtabtype is table of number

index by binary_integer;

sal_tab numbertype;

empty_tab numbertype;

begin

for I in 1..100 loop

sal_tab(I):=I;

end loop;

.

End;

 

 

 

 

 

 

 

 

2.RECORD

Declare 

Type deptrectype is record

(deptno number(2),

 dname char(14),

 loc char(14),);

dept_rec deptrectype;

begin

select deptno,dname,loc into dept_rec from dept where deptno=30;

end;

與所有的編程語言一樣,定義一個變量時,同樣存在變量作用范圍問題:

如下所示:

declare 

  x  real;

function  function_name(variant type)return type is

  declare

    x char; 

begin

  …

  end function_name;

begin

x:=expression1

end;

 

 

 

如果想引用另一block之變量時,可以加上block label,如下所示:

<<outer>>

declare

birthdate  date;

begin

   …

   declare

 birthdate   date;

begin

.

If birthdate=outer.birthdate then

.

End if;

End;

End outer;

 

 

 

 

 

 

 

 

 

 

 

 

三、 
PL/SQL控制程序流

1. IF THENELSIFELSE…….END IF

IF … THEN 

 STATMENT1;

elseifthen

 statment2

elseifthen

 statment3

ELSE

 STATMENT4;

end if;

 

例:

<<outer>>

for ctr in 1..20 loop

  <<inner>>

  for ctr in 1..10 loop

   if outer.ctr>ctr then

    …

  end loop inner;

end loop outer;

 

2.loopexitend loop

  loop

   sequence_of_statement;

   …

   exit;

end loop;

例:

 loop

  fetch c1 into 

exit when c1%notfound;

end loop;

close c1;

 

 

另:加loop label;

例:<<outer>>

   loop

    …

    loop

     …

     exit outer when

    end loop;

     …

  end loop outer;

 

3.whileloopend loop結構如下所示:

例 

   while total<=25000 loop

     ….

     Select sa1 into salary from emp where

       Total:=total+salary;

   End loop;

 

4.forloop

   例1.

      select count(empno) into emp_count from emp;

      for L in 1..emp_count loop

          …

      end loop;

 

例2. 

   <<outer>>

   for step in 1..25 loop

       for step in 1..10 loop

          …

          if outer.step>15 then

       end loop;

   end loop outer;

 

5. cursor.loop

declare

sursor c1 is select ename from emp;

name varchar2(100);

begin

 

for p_c1_rec in c1 loop

name := p_c1_rec.ename;

 

end loop;

 

 

 

 

四、 
存儲過程

要創建存儲過程,可以使用下面的SQL和PL/SQL語句:

 

CREATE OR REPLACE PROCEDURE PROCEDURE_NAME(parameter list)

AS

BEGIN

(SQL AND PL/SQL COMMANDS)

END;

 

五、 存儲函數

create or replace function function_name (parameter list) return type is

.

Begin 

 …

end;

 

 

 

六、 Package

 

Package分為兩部分:Specific and Body

在包說明部分中,主要將此包中所含的過程和Function的調用參數說明清楚,如:

CREATE OR REPLACE PACKAGE ZDL_JOB_PKG

AS

PROCEDURE ZDL_INSERT_JOB(

p_bkc_id in number,

p_item_id in number,

p_job_number in out varchar2,

p_group_id in number,

p_lead_day in number,

p_load_type in number,

P_STATUS_TYPE IN NUMBER,

P_USER_ID IN NUMBER,

P_JOB_TYPE IN VARCHAR2);

PROCEDURE ZDL_UPDATE_JOB(

P_BKC_ID IN NUMBER,

P_GROUP_ID IN NUMBER,

P_STATUS_TYPE IN NUMBER,

P_USER_ID IN NUMBER);

FUNCTION WIP_MASS_LOAD(P_GROUP_ID IN NUMBER,P_USER_ID IN NUMBER) RETURN NUMBER;

PROCEDURE ZDL_PRE_UPDATE;

FUNCTION ZDL_UPDATE_ORACLE_WIP(P_USER_ID IN NUMBER) RETURN NUMBER;

FUNCTION ZDL_JOB_STATUS (P_JOB_NUMBER IN VARCHAR2) RETURN NUMBER;

END ZDL_JOB_PKG;

在包體部分,主要將包說明部分之過程及Function之代碼寫出來,

如:

CREATE OR REPLACE PACKAGE BODY ZDL_JOB_PKG

AS

PROCEDURE ZDL_INSERT_JOB (

p_bkc_id in number, p_item_id in number,p_job_number in out varchar2,

p_group_id in number,

p_lead_day in number,

P_LOAD_TYPE IN NUMBER,

P_STATUS_TYPE IN NUMBER,

P_USER_ID IN NUMBER,

P_JOB_TYPE IN VARCHAR2) 

is

…………

begin

…………

end ZDL_INSERT_JOB;

 

PROCEDURE ZDL_UPDATE_JOB(P_BKC_ID IN NUMBER,P_GROUP_ID IN NUMBER,P_STATUS_TYPE IN NUMBER,P_USER_ID IN NUMBER)

AS

…………

BEGIN

…………

END ZDL_UPDATE_JOB;

 

FUNCTION WIP_MASS_LOAD(P_GROUP_ID IN NUMBER,P_USER_ID IN NUMBER) RETURN NUMBER 

as

…………

begin

…………

END WIP_MASS_LOAD;

 

PROCEDURE ZDL_PRE_UPDATE IS

…………

begin

…………

end ZDL_PRE_UPDATE;

 

FUNCTION ZDL_UPDATE_ORACLE_WIP(P_USER_ID IN NUMBER) RETURN NUMBER

IS

…………

begin

…………

end ZDL_UPDATE_ORACLE_WIP;

 

FUNCTION ZDL_JOB_STATUS (P_JOB_NUMBER IN VARCHAR2) RETURN NUMBER

AS

…………

BEGIN

…………

END ZDL_JOB_STATUS;

 

END ZDL_JOB_PKG;

七、 
觸發器

² 所需系統權限

要為某表創建觸發器,必須能改變這個表,因此不僅要擁有表,並且要具有這個表的 alter權限,或者具有alter any table系統權限,除此之外,必須有create triger系統權限,若要在另一個用戶賬號(account)(也稱之為模式(schema))上創建觸發器,就必具有create any trigger系統權限.

 

² 所需表權限

觸發器可以引用的表並不是初始化觸發事件的表.

 

² 觸發器

觸發器有十二種類型.一個觸發器的類型由執行觸發器的層次位置和觸發事務的類型定義.

 

² 行級觸發器

在某個事務中,行級觸發器行執行,對於上述ledger表中記例子而言,觸發器.行級觸發器是在create trigger命令中通過用for each row 子句創建的.

 

² 合法的觸發器類型

當兩種不同類型之觸發動作相結合時,有十二種可能的配置:

Before insert 行級觸發器

before insert  語句級觸發器

after insert  行級觸發器

after insert  語句級觸發器

before update 行級觸發器

before update 語句級觸發器

after update  行級觸發器

after update     語句級觸發器

before delete 行級觸發器

before delete 語句級觸發器

after delete 行級觸發器

after delete 語句級觸發器

 

 

 

 

 

 

例:

CREATE OR REPLACE TRIGGER "APPS"."ZDL_BKC_JOB_BODY_AFI" 

AFTER INSERT ON "APPS"."ZDL_BKC_JOB_BODY" 

REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW 

BEGIN

  Insert into audit_tbl values(:new.id,:new……);

UPDATE ZDL_BKC_JOB_HEAD SET UPDATE_DATE = SYSDATE 

WHERE ZDL_BKC_JOB_HEAD_ID = :NEW.ZDL_BKC_JOB_BODY_ID;

END;

 

 

 

 

 

 

 

 

 

八、 
應用實例

下面以電算部開發出之程序<<MDS展開及開工日維護程序>>之各類程序為例:

1. Create table, index, sequence, table trigger

首先清除原先已有之重名table,Sequence等:

DROP TABLE ZDL_BKC_JOB_BODY;

DROP TABLE ZDL_BKC_JOB_HEAD;

DROP TABLE ZDL_BKC_JOB_UPDATE;

drop sequence zdl_bkc_job_s;

 

建立table, sequence以及Index

create table zdl_bkc_job_head

   (zdl_bkc_job_head_id number not null,

    assembly varchar2(9) not null,

    lot_no varchar2(240),

    job_no varchar2(240),

    OL_DATE date,

    quantity number,

    line_code varchar2(240),

    created_date date,

    update_date date,

    primary key(zdl_bkc_job_head_id)

);

 create table zdl_bkc_job_body

    (zdl_bkc_job_body_id number not null references zdl_bkc_job_head(zdl_bkc_job_head_id),

    level1 VARCHAR2(15),

    job1 varchar2(240),

    level2 VARCHAR2(15),

    job2 varchar2(240),

    level3 VARCHAR2(15),

    job3 varchar2(240),

    level4 VARCHAR2(15),

    job4 varchar2(240),

    level5 VARCHAR2(15),

    job5 varchar2(240));

create table ZDL_BKC_JOB_UPDATE

( BKC_ID NUMBER NOT NULL,

LOCATION_ID NUMBER NOT NULL,

ACTION_ID NUMBER NOT NULL,

JOB_NUMBER VARCHAR2(240),

UPDATED_FLAG VARCHAR2(1),

CREATION_DATE DATE,

UPDATED_DATE DATE

);

create sequence zdl_bkc_job_s;

CREATE INDEX ZDL_BKC_JOB_HEAD_N1 ON ZDL_BKC_JOB_HEAD(ZDL_BKC_JOB_HEAD_ID,ASSEMBLY);

CREATE INDEX ZDL_BKC_JOB_BODY_N1 ON ZDL_BKC_jOB_BODY(ZDL_BKC_JOB_BODY_ID,LEVEL1);

CREATE INDEX ZDL_BKC_JOB_BODY_N2 ON ZDL_BKC_jOB_BODY(ZDL_BKC_JOB_BODY_ID,LEVEL2);

CREATE INDEX ZDL_BKC_JOB_BODY_N3 ON ZDL_BKC_jOB_BODY(ZDL_BKC_JOB_BODY_ID,LEVEL3);

CREATE INDEX ZDL_BKC_JOB_UPDATE_N1 ON ZDL_BKC_JOB_UPDATE(ACTION_ID,LOCATION_ID);

COMMIT;

 

建立table Trigger:

-- Trigger head after update

CREATE OR REPLACE TRIGGER "APPS".ZDL_BKC_JOB_HEAD_AFU 

AFTER UPDATE OF "LINE_CODE", "LOT_NO", "OL_DATE", "QUANTITY" ON "APPS"."ZDL_BKC_JOB_HEAD" 

REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW 

BEGIN

INSERT INTO ZDL_BKC_JOB_UPDATE (

BKC_ID,

LOCATION_ID,

ACTION_ID,

JOB_NUMBER,

UPDATED_FLAG,

CREATION_DATE,

UPDATED_DATE)

VALUES(

:OLD.ZDL_BKC_JOB_HEAD_ID,

1,

3,

:OLD.JOB_NO,

'N',

SYSDATE,

SYSDATE);

END;

 

-- Trigger body before delete

CREATE OR REPLACE TRIGGER "APPS"."ZDL_BKC_JOB_BODY_BRD" 

BEFORE DELETE ON "APPS"."ZDL_BKC_JOB_BODY" 

REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW 

BEGIN

if :old.job1 is not null then

INSERT INTO ZDL_BKC_JOB_UPDATE(BKC_ID,LOCATION_ID,ACTION_ID,JOB_NUMBER,UPDATED_FLAG,CREATION_DATE,UPDATED_DATE)

VALUES(:OLD.ZDL_BKC_JOB_BODY_ID,2,7,:old.JOB1,'N',SYSDATE,SYSDATE);

END IF;

if :old.job2 is not null then

INSERT INTO ZDL_BKC_JOB_UPDATE(BKC_ID,LOCATION_ID,ACTION_ID,JOB_NUMBER,UPDATED_FLAG,CREATION_DATE,UPDATED_DATE)

VALUES(:OLD.ZDL_BKC_JOB_BODY_ID,2,7,:old.JOB2,'N',SYSDATE,SYSDATE);

END IF;

if :old.job3 is not null then

INSERT INTO ZDL_BKC_JOB_UPDATE(BKC_ID,LOCATION_ID,ACTION_ID,JOB_NUMBER,UPDATED_FLAG,CREATION_DATE,UPDATED_DATE)

VALUES(:OLD.ZDL_BKC_JOB_BODY_ID,2,7,:old.JOB3,'N',SYSDATE,SYSDATE);

END IF;

if :old.job4 is not null then

INSERT INTO ZDL_BKC_JOB_UPDATE(BKC_ID,LOCATION_ID,ACTION_ID,JOB_NUMBER,UPDATED_FLAG,CREATION_DATE,UPDATED_DATE)

VALUES(:OLD.ZDL_BKC_JOB_BODY_ID,2,7,:old.JOB4,'N',SYSDATE,SYSDATE);

END IF;

if :old.job5 is not null then

INSERT INTO ZDL_BKC_JOB_UPDATE(BKC_ID,LOCATION_ID,ACTION_ID,JOB_NUMBER,UPDATED_FLAG,CREATION_DATE,UPDATED_DATE)

VALUES(:OLD.ZDL_BKC_JOB_BODY_ID,2,7,:old.JOB5,'N',SYSDATE,SYSDATE);

END IF;

UPDATE ZDL_BKC_JOB_HEAD SET UPDATE_DATE = SYSDATE 

WHERE ZDL_BKC_JOB_HEAD_ID = :OLD.ZDL_BKC_JOB_BODY_ID;

END;

 

-- Trigger head after delete

CREATE OR REPLACE TRIGGER "APPS".ZDL_BKC_JOB_HEAD_BRD 

BEFORE DELETE ON "APPS"."ZDL_BKC_JOB_HEAD" 

REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW 

BEGIN

INSERT INTO ZDL_BKC_JOB_UPDATE

(BKC_ID,LOCATION_ID,ACTION_ID,JOB_NUMBER,UPDATED_FLAG,CREATION_DATE,UPDATED_DATE)

VALUES

(:OLD.ZDL_BKC_JOB_HEAD_ID,1,7,:OLD.JOB_NO,'N',SYSDATE,SYSDATE);

END;

 

-- Trigger body after insert

CREATE OR REPLACE TRIGGER "APPS"."ZDL_BKC_JOB_BODY_AFI" 

AFTER INSERT ON "APPS"."ZDL_BKC_JOB_BODY" 

REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW 

BEGIN

UPDATE ZDL_BKC_JOB_HEAD SET UPDATE_DATE = SYSDATE 

WHERE ZDL_BKC_JOB_HEAD_ID = :NEW.ZDL_BKC_JOB_BODY_ID;

END;

2. 建立兩個主要之package:

A. ZDL_BKC_APP_PKG

Package Specific

 

CREATE OR REPLACE PACKAGE ZDL_BKC_APP_PKG

AS

/*BOM之展開*/

PROCEDURE ZDL_BOM_EXPLOSION(

P_ITEM_ID IN NUMBER,

p_Organization_id IN NUMBER,

P_BOM_GROUP_ID IN NUMBER,

P_EXPL_QTY IN NUMBER,

P_ERROR_CODE OUT NUMBER);

 

/*展開之半制品放於ZDL_JOB_BKC_HEAD AND ZDL_JOB_BKC_BODY中,並調用ZDL_JOB_PKG中的

相閞過程實現JOB之產生及LOAD入Oracle MFG中*/

PROCEDURE ZDL_PROCESS_BOM(

P_ITEM_ID in number,

P_BKC_ID OUT NUMBER,

P_BOM_GROUP_ID IN NUMBER,

P_GROUP_ID IN NUMBER,

P_SCHEDULE_COMMENTS IN VARCHAR2,

P_SCHEDULE_QUANTITY IN NUMBER,

P_SCHEDULE_DATE IN DATE,

P_ORGANIZATION_ID IN NUMBER,

P_USER_ID IN NUMBER,

P_ERROR_CODE OUT NUMBER,

P_JOB_TYPE IN VARCHAR2);

END ZDL_BKC_APP_PKG;

 

 

Package Body

 

CREATE OR REPLACE PACKAGE BODY ZDL_BKC_APP_PKG

AS

PROCEDURE ZDL_BOM_EXPLOSION(

P_ITEM_ID IN NUMBER,

p_Organization_id IN NUMBER,

P_BOM_GROUP_ID IN NUMBER,

P_EXPL_QTY IN NUMBER,

P_ERROR_CODE OUT NUMBER) 

AS

  l_seq_id                NUMBER;

  l_bom_or_eng            NUMBER:=1;

  l_err_msg               VARCHAR2(80);

  l_err_code              NUMBER;

  exploder_error          EXCEPTION;

  loop_error              EXCEPTION;

  table_name   VARCHAR2(20);

  item_id_null   EXCEPTION;

  p_revision_date   varchar2(15);

  P_EXPLODE_OPTION_TYPE   varchar2(100);

BEGIN

  P_ERROR_CODE := 0;

  SELECT BOM_LISTS_S.NEXTVAL

  INTO  l_seq_id

  FROM  DUAL;

 

  TABLE_NAME := 'BUILD SQL';

  INSERT INTO BOM_LISTS (SEQUENCE_ID, ASSEMBLY_ITEM_ID,

                                ALTERNATE_DESIGNATOR)

        SELECT DISTINCT l_seq_id,P_ITEM_ID,

                bbom.alternate_bom_designator

         FROM   bom_bill_of_materials bbom

         WHERE  bbom.organization_id = 102

         AND    bbom.assembly_item_id = P_ITEM_ID

         AND    (bbom.alternate_bom_designator IS NULL)

         AND    (bbom.assembly_type = 1);

    commit;

    TABLE_NAME := 'EXECUTE SQL';

/* Call BOM exploder */

   TABLE_NAME := 'CALL EXPLODER';

   -- bug 519321

   P_REVISION_DATE := to_char(sysdate,'DD-MON-YY HH24:MI');

   bompexpl.explosion_report

        (

        org_id => p_Organization_id,  

        order_by => 2,   

        list_id => l_seq_id,    

        grp_id => P_BOM_GROUP_ID,        

        session_id => -1,

        levels_to_explode => 15, 

        bom_or_eng => 1,        

        impl_flag => 1,        

        explode_option => 2, 

        module => 2,

        cst_type_id => -1, 

        std_comp_flag => -1,

        expl_qty => P_EXPL_QTY,            

        report_option => -1,

        req_id => 0,

        lock_flag => -1,

        rollup_option => -1,

        alt_rtg_desg => '',

        alt_desg => '',

        rev_date => P_REVISION_DATE,

        err_msg => l_err_msg,

        error_code => l_err_code,

        verify_flag =>0,

        cst_rlp_id => 0,

        plan_factor_flag => 2,

        incl_lt_flag => 2

        );

  commit;

  TABLE_NAME := 'EXPLODE COMPLETE';

  if l_err_code = 9999 then

    raise loop_error;

  end if; 

  if l_err_code <0  then 

    raise exploder_error;

  end if;

  commit;    --save

  DELETE FROM BOM_LISTS WHERE SEQUENCE_ID = L_SEQ_ID;

  COMMIT;

EXCEPTION

    WHEN exploder_error THEN 

P_ERROR_CODE := 1;

        dbms_output.put_line(l_err_msg);   

    WHEN loop_error THEN

P_ERROR_CODE := 2;

        dbms_output.put_line('aaa'); 

    WHEN item_id_null THEN

P_ERROR_CODE := 3;

        dbms_output.put_line('Item is is null');

    WHEN NO_DATA_FOUND THEN

P_ERROR_CODE := 4;

        dbms_output.put_line(TABLE_NAME ||SQLERRM);

    WHEN OTHERS THEN

P_ERROR_CODE := 5;

        dbms_output.put_line(TABLE_NAME || SQLERRM);

END ZDL_BOM_EXPLOSION;

 

/* Process data of bom_explosion_temp */

PROCEDURE ZDL_PROCESS_BOM(

P_ITEM_ID in number,

P_BKC_ID OUT NUMBER,

P_BOM_GROUP_ID IN NUMBER,

P_GROUP_ID IN NUMBER,

P_SCHEDULE_COMMENTS IN VARCHAR2,

P_SCHEDULE_QUANTITY IN NUMBER,

P_SCHEDULE_DATE IN DATE,

P_ORGANIZATION_ID IN NUMBER,

P_USER_ID IN NUMBER,

P_ERROR_CODE OUT NUMBER,

P_JOB_TYPE IN VARCHAR2) 

AS

CURSOR C1 IS

SELECT 

BET.ASSEMBLY_ITEM_ID, 

MSI.SEGMENT1,

BET.COMPONENT_ITEM_ID,

BET.PLAN_LEVEL

FROM  BOM.BOM_EXPLOSION_TEMP BET, 

INV.MTL_SYSTEM_ITEMS MSI

WHERE 

BET.COMPONENT_ITEM_ID = MSI.INVENTORY_ITEM_ID AND 

BET.ORGANIZATION_ID = MSI.ORGANIZATION_ID AND 

MSI.ORGANIZATION_ID = P_ORGANIZATION_ID AND

BET.GROUP_ID = P_BOM_GROUP_ID AND

BET.TOP_ITEM_ID = P_ITEM_ID AND 

(MSI.ITEM_TYPE = 'SA' OR MSI.ITEM_TYPE = 'FG')

ORDER BY BET.PLAN_LEVEL;

P_C1 C1%ROWTYPE;

R_ITEM VARCHAR2(15);

P_JOB_NUMBER NUMBER;

BEGIN

P_ERROR_CODE := 0;

OPEN C1;

LOOP

FETCH C1 INTO P_C1;

EXIT WHEN C1%NOTFOUND;

IF P_C1.PLAN_LEVEL = 0 THEN

select zdl_bkc_job_s.nextval into P_BKC_ID from sys.dual;

insert into zdl_bkc_job_head

( zdl_bkc_job_head_id,

assembly,

CREATED_DATE,

update_date,

QUANTITY,

LOT_NO,

LINE_CODE,

OL_DATE) 

values

( P_BKC_ID,

P_item_ID,

SYSDATE,

SYSDATE,

P_SCHEDULE_QUANTITY,

SUBSTR(P_SCHEDULE_COMMENTS,1,INSTR(P_SCHEDULE_COMMENTS,'/')-1),

SUBSTR(P_SCHEDULE_COMMENTS,INSTR(P_SCHEDULE_COMMENTS,'/')+1,

LENGTH(P_SCHEDULE_COMMENTS)),

P_SCHEDULE_DATE);

COMMIT;

ZDL_JOB_PKG.ZDL_INSERT_JOB(P_BKC_ID,P_ITEM_ID,P_JOB_NUMBER,P_GROUP_ID,

0,1,0,P_USER_ID,P_JOB_TYPE);

UPDATE ZDL_BKC_JOB_HEAD SET JOB_NO = P_JOB_NUMBER WHERE ZDL_BKC_JOB_HEAD_ID = P_BKC_ID;

ELSIF P_C1.PLAN_LEVEL = 1 THEN 

ZDL_JOB_PKG.zdl_insert_job(P_BKC_ID,P_C1.COMPONENT_ITEM_ID,p_job_number,p_group_id,

-2,1,0,P_USER_ID,P_JOB_TYPE);

insert into zdl_bkc_job_body

(zdl_bkc_job_body_id,level1,job1)

values(P_BKC_ID,P_C1.SEGMENT1,p_job_number);

COMMIT;

ELSIF P_C1.PLAN_LEVEL = 2 THEN

SELECT SEGMENT1 INTO R_ITEM 

FROM MTL_SYSTEM_ITEMS 

WHERE ORGANIZATION_ID = P_ORGANIZATION_ID 

AND INVENTORY_ITEM_ID = P_C1.ASSEMBLY_ITEM_ID;

ZDL_JOB_PKG.ZDL_INSERT_JOB(P_BKC_ID,P_C1.COMPONENT_ITEM_ID,P_JOB_NUMBER,P_GROUP_ID,

-3,1,0,P_USER_ID,P_JOB_TYPE);

UPDATE ZDL_BKC_JOB_BODY SET

LEVEL2 = P_C1.SEGMENT1,

JOB2 = P_JOB_NUMBER

WHERE LEVEL1 = R_ITEM AND ZDL_BKC_JOB_BODY_ID = P_BKC_ID;

COMMIT;

ELSIF P_C1.PLAN_LEVEL = 3 THEN

SELECT SEGMENT1 INTO R_ITEM 

FROM MTL_SYSTEM_ITEMS 

WHERE ORGANIZATION_ID = P_ORGANIZATION_ID 

AND INVENTORY_ITEM_ID = P_C1.ASSEMBLY_ITEM_ID;

ZDL_JOB_PKG.ZDL_INSERT_JOB(P_BKC_ID,P_C1.COMPONENT_ITEM_ID,P_JOB_NUMBER,P_GROUP_ID,

-4,1,0,P_USER_ID,P_JOB_TYPE);

UPDATE ZDL_BKC_JOB_BODY SET

LEVEL3 = P_C1.SEGMENT1,

JOB3 = P_JOB_NUMBER

WHERE LEVEL2 = R_ITEM AND ZDL_BKC_JOB_BODY_ID = P_BKC_ID;

COMMIT;

ELSIF P_C1.PLAN_LEVEL = 4 THEN

SELECT SEGMENT1 INTO R_ITEM 

FROM MTL_SYSTEM_ITEMS 

WHERE ORGANIZATION_ID = P_ORGANIZATION_ID 

AND INVENTORY_ITEM_ID = P_C1.ASSEMBLY_ITEM_ID;

ZDL_JOB_PKG.ZDL_INSERT_JOB(P_BKC_ID,P_C1.COMPONENT_ITEM_ID,P_JOB_NUMBER,P_GROUP_ID,

-6,1,0,P_USER_ID,P_JOB_TYPE);

UPDATE ZDL_BKC_JOB_BODY SET

LEVEL4 = P_C1.SEGMENT1,

JOB3 = P_JOB_NUMBER

WHERE LEVEL3 = R_ITEM AND ZDL_BKC_JOB_BODY_ID = P_BKC_ID;

COMMIT;

ELSIF P_C1.PLAN_LEVEL = 5 THEN

SELECT SEGMENT1 INTO R_ITEM 

FROM MTL_SYSTEM_ITEMS 

WHERE ORGANIZATION_ID = P_ORGANIZATION_ID 

AND INVENTORY_ITEM_ID = P_C1.ASSEMBLY_ITEM_ID;

ZDL_JOB_PKG.ZDL_INSERT_JOB(P_BKC_ID,P_C1.COMPONENT_ITEM_ID,P_JOB_NUMBER,P_GROUP_ID,

-6,1,0,P_USER_ID,P_JOB_TYPE);

UPDATE ZDL_BKC_JOB_BODY SET

LEVEL5 = P_C1.SEGMENT1,

JOB3 = P_JOB_NUMBER

WHERE LEVEL4 = R_ITEM AND ZDL_BKC_JOB_BODY_ID = P_BKC_ID;

COMMIT;

END IF;

END LOOP;

CLOSE C1;

DELETE FROM BOM_EXPLOSION_TEMP WHERE GROUP_ID = P_BOM_GROUP_ID;

COMMIT;

EXCEPTION

WHEN OTHERS THEN

P_ERROR_CODE := 6;

END ZDL_PROCESS_BOM;

 

END ZDL_BKC_APP_PKG;

 

 

B. ZDL_JOB_PKG

 

Package Specific

 

CREATE OR REPLACE PACKAGE ZDL_JOB_PKG

AS

 

/*給每個展開之半制品分配一個JOB號,並將其存儲於WIP_JOB_SCHEDULE_INTERFACE中*/

PROCEDURE ZDL_INSERT_JOB(

p_bkc_id in number,

p_item_id in number,

p_job_number in out varchar2,

p_group_id in number,

p_lead_day in number,

p_load_type in number,

P_STATUS_TYPE IN NUMBER,

P_USER_ID IN NUMBER,

P_JOB_TYPE IN VARCHAR2);

 

/*維護O/L日期等時自動更新Oracle MFG之WIP*/

PROCEDURE ZDL_UPDATE_JOB(

P_BKC_ID IN NUMBER,

P_GROUP_ID IN NUMBER,

P_STATUS_TYPE IN NUMBER,

P_USER_ID IN NUMBER);

 

/*觸發WIP JOB MASS LOAD程序*/

FUNCTION WIP_MASS_LOAD(P_GROUP_ID IN NUMBER,P_USER_ID IN NUMBER) RETURN NUMBER;

 

/*在使用ZDL_BKC_JOB_UPDATE檔更新Oracle MFG時,將其中之相關數據織一下*/

PROCEDURE ZDL_PRE_UPDATE;

 

/*調用前面之相關程序,並根據ZDL_BKC_JOB_UPDATE文件更新Oracle MFG*/

FUNCTION ZDL_UPDATE_ORACLE_WIP(P_USER_ID IN NUMBER) RETURN NUMBER;

 

/*檢查Oracle JOB之狀態,並返回*/

FUNCTION ZDL_JOB_STATUS (P_JOB_NUMBER IN VARCHAR2) RETURN NUMBER;

END ZDL_JOB_PKG;

 

Package Body

 

CREATE OR REPLACE PACKAGE BODY ZDL_JOB_PKG

AS

PROCEDURE ZDL_INSERT_JOB (

p_bkc_id in number,

p_item_id in number,

p_job_number in out varchar2,

p_group_id in number,

p_lead_day in number,

P_LOAD_TYPE IN NUMBER,

P_STATUS_TYPE IN NUMBER,

P_USER_ID IN NUMBER,

P_JOB_TYPE IN VARCHAR2) 

is

p_completion_date date;

r_schedule_date date;

p_start_quantity number;

l_seq_num number;

l_next_seq_num number;

p_lot_number varchar2(240);

P_LINE_CODE VARCHAR2(240);

p_wip_entity_id number;

begin

/* P_BKC_ID = 0 MEAN THAT THE BKC ID HAS BEEN DELETE FROM TABLE */

IF NOT (P_BKC_ID = 0 AND P_STATUS_TYPE = 7) THEN

select OL_DATE,quantity,lot_no,line_code into p_completion_date,p_start_quantity,p_lot_number,P_LINE_CODE

from zdl_bkc_job_head where ZDL_BKC_JOB_HEAD_ID = p_bkc_id;

END IF;

/* P_STSTUS_TYPE = 7 MEAD THAT THIS JOB MUST BE CANCELLED */

IF P_STATUS_TYPE <> 7 THEN

select seq_num,next_seq_num into l_seq_num,l_next_seq_num 

from bom_calendar_dates

where trunc(calendar_date) = trunc(p_completion_date);

if l_seq_num is null then

l_seq_num:=l_next_seq_num-1;

end if;

l_seq_num:=l_seq_num+p_lead_day;

select calendar_date into r_schedule_date from bom_calendar_dates where seq_num=l_seq_num; 

END IF;

/* P_LOAD_TYPE = 1 : ADD A JOB INTO ORACLE WIP

   P_LOAD_TYPE = 3 : UPDATE A JOB OF ORACLE WIP*/

if p_load_type = 1 then

select wip_job_number_s.nextval into p_job_number from sys.dual;

elsif p_load_type = 3 then

select wip_entity_id into p_wip_entity_id from wip_entities where wip_entity_name = p_job_number;

end if;

insert into wip_job_schedule_interface

(

last_update_date,

creation_date,

created_by,

last_updated_by,

group_id,

process_phase,

process_status,

load_type,

job_name,

wip_entity_id,

LAST_UNIT_COMPLETION_DATE,

organization_id,

primary_item_id,

description,

start_quantity,

STATUS_TYPE,

ATTRIBUTE_CATEGORY,

ATTRIBUTE1,

ATTRIBUTE2,

ATTRIBUTE3)

values

( sysdate,

sysdate,

P_USER_ID,

P_USER_ID,

p_group_id,

2,

1,

P_LOAD_TYPE,

p_job_number,

decode(p_load_type,1,null,p_wip_entity_id),

DECODE(P_STATUS_TYPE,0,to_date(to_char(r_schedule_date,'DD-MON-YYYY HH24:MI:SS'),

'DD-MON-YYYY HH24:MI:SS'),NULL),

102,

decode(p_load_type,1,p_item_id,null),

decode(p_load_type,1,'Created By ZDL BKC Program',DECODE(P_STATUS_TYPE,0,

'Updated by ZDL BKC Program','Cancelled by ZDL BKC Program')),

DECODE(P_STATUS_TYPE,0,p_start_quantity,NULL),

DECODE(P_STATUS_TYPE,0,NULL,P_STATUS_TYPE),

'JOB',

DECODE(P_LOAD_TYPE,1,P_JOB_TYPE,NULL),

p_lot_number,

P_LINE_CODE

);

commit;

end ZDL_INSERT_JOB;

 

PROCEDURE ZDL_UPDATE_JOB(P_BKC_ID IN NUMBER,P_GROUP_ID IN NUMBER,

P_STATUS_TYPE IN NUMBER,P_USER_ID IN NUMBER)

AS

P_JOB_NO VARCHAR2(240);

P_LOT_NO VARCHAR2(240);

P_QUANTITY NUMBER;

P_LINE_CODE VARCHAR2(240);

P_OL_DATE DATE;

p_job1 zdl_bkc_job_body.job1%type;

p_job2 zdl_bkc_job_body.job2%type;

p_job3 zdl_bkc_job_body.job3%type;

p_job4 zdl_bkc_job_body.job4%type;

p_job5 zdl_bkc_job_body.job5%type;

cursor l_bkc is 

select job1,job2,job3,job4,job5 from zdl_bkc_job_body where zdl_bkc_job_body_id=p_bkc_id;

BEGIN

SELECT  JOB_NO,LOT_NO,QUANTITY,LINE_CODE,OL_DATE 

INTO P_JOB_NO,P_LOT_NO,P_QUANTITY,P_LINE_CODE,P_OL_DATE 

FROM  ZDL_BKC_JOB_HEAD

WHERE ZDL_BKC_JOB_HEAD_ID = P_BKC_ID;

zdl_job_pkg.ZDL_INSERT_JOB(P_BKC_ID,0,p_job_no,p_group_id,0,3,P_STATUS_TYPE,P_USER_ID,NULL);

open l_bkc;

loop

fetch l_bkc into p_job1,p_job2,p_job3,p_job4,p_job5;

exit when l_bkc%notfound;

if P_job1 is not null then

zdl_job_pkg.ZDL_INSERT_JOB(P_BKC_ID,0,P_JOB1,P_GROUP_ID,-2,3,P_STATUS_TYPE,P_USER_ID,NULL);

end if;

IF P_JOB2 IS NOT NULL THEN

zdl_job_pkg.ZDL_INSERT_JOB(P_BKC_ID,0,P_JOB2,P_GROUP_ID,-3,3,P_STATUS_TYPE,P_USER_ID,NULL);

END IF;

IF P_JOB3 IS NOT NULL THEN

zdl_job_pkg.ZDL_INSERT_JOB(P_BKC_ID,0,P_JOB3,P_GROUP_ID,-4,3,P_STATUS_TYPE,P_USER_ID,NULL);

END IF;

IF P_JOB4 IS NOT NULL THEN

zdl_job_pkg.ZDL_INSERT_JOB(P_BKC_ID,0,P_JOB4,P_GROUP_ID,-6,3,P_STATUS_TYPE,P_USER_ID,NULL);

END IF;

IF P_JOB5 IS NOT NULL THEN

zdl_job_pkg.ZDL_INSERT_JOB(P_BKC_ID,0,P_JOB5,P_GROUP_ID,-8,3,P_STATUS_TYPE,P_USER_ID,NULL);

END IF;

end loop;

END ZDL_UPDATE_JOB;

 

FUNCTION WIP_MASS_LOAD(P_GROUP_ID IN NUMBER,P_USER_ID IN NUMBER) RETURN NUMBER 

as

req_id number;

LOGINID NUMBER;

begin

SELECT FND_CONCURRENT_REQUESTS_S.NEXTVAL INTO REQ_ID FROM DUAL;

SELECT FND_LOGINS_S.NEXTVAL INTO LOGINID FROM DUAL;

insert into  FND_CONCURRENT_REQUESTS (

REQUEST_ID, 

LAST_UPDATE_DATE, 

LAST_UPDATED_BY, 

LAST_UPDATE_LOGIN, 

REQUEST_DATE, 

REQUESTED_BY, 

PHASE_CODE, 

STATUS_CODE, 

PRIORITY_REQUEST_ID, 

PRIORITY, 

REQUESTED_START_DATE, 

HOLD_FLAG, 

ENFORCE_SERIALITY_FLAG, 

SINGLE_THREAD_FLAG, 

HAS_SUB_REQUEST, 

IS_SUB_REQUEST, 

IMPLICIT_CODE, 

UPDATE_PROTECTED, 

QUEUE_METHOD_CODE, 

ARGUMENT_INPUT_METHOD_CODE, 

ORACLE_ID, 

PROGRAM_APPLICATION_ID, 

CONCURRENT_PROGRAM_ID, 

RESPONSIBILITY_APPLICATION_ID, 

RESPONSIBILITY_ID, 

NUMBER_OF_ARGUMENTS, 

NUMBER_OF_COPIES, 

SAVE_OUTPUT_FLAG, 

NLS_LANGUAGE, 

NLS_TERRITORY, 

PRINTER, 

PRINT_STYLE, 

PRINT_GROUP, 

REQUEST_CLASS_APPLICATION_ID, 

CONCURRENT_REQUEST_CLASS_ID, 

PARENT_REQUEST_ID, 

CONC_LOGIN_ID, 

LANGUAGE_ID, 

DESCRIPTION, 

REQ_INFORMATION, 

RESUBMIT_INTERVAL, 

RESUBMIT_INTERVAL_UNIT_CODE, 

RESUBMIT_INTERVAL_TYPE_CODE, 

RESUBMIT_TIME, 

RESUBMIT_END_DATE, 

RESUBMITTED, 

CONTROLLING_MANAGER, 

ACTUAL_START_DATE, 

ACTUAL_COMPLETION_DATE, 

COMPLETION_TEXT, 

OUTCOME_PRODUCT, 

OUTCOME_CODE, 

CPU_SECONDS, 

LOGICAL_IOS, 

PHYSICAL_IOS, 

LOGFILE_NAME, 

LOGFILE_NODE_NAME, 

OUTFILE_NAME, 

OUTFILE_NODE_NAME, 

ARGUMENT_TEXT, 

ARGUMENT1, 

ARGUMENT2, 

ARGUMENT3, 

ARGUMENT4,

ARGUMENT5, 

ARGUMENT6, 

ARGUMENT7, 

ARGUMENT8, 

ARGUMENT9, 

ARGUMENT10, 

ARGUMENT11, 

ARGUMENT12, 

ARGUMENT13, 

ARGUMENT14, 

ARGUMENT15, 

ARGUMENT16, 

ARGUMENT17, 

ARGUMENT18, 

ARGUMENT19, 

ARGUMENT20, 

ARGUMENT21, 

ARGUMENT22, 

ARGUMENT23, 

ARGUMENT24, 

ARGUMENT25, 

CRM_THRSHLD, 

CRM_TSTMP

)

VALUES

(

REQ_ID,

SYSDATE,

P_USER_ID,

LOGINID,

SYSDATE,

P_USER_ID,

'P',

'I',

REQ_ID,

50,

SYSDATE,

'N',

'Y',

'N',

'N',

'N',

'N',

'N',

'I',

'S',

900,

706,

34291,

706,

20560,

3,

0,

'Y',

'AMERICAN',

'AMERICA',

NULL,

'LANDSCAPE',

'N',

NULL,

NULL,

-1,

LOGINID,

0,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

'N',

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

RTRIM(TO_CHAR(P_GROUP_ID))||', 0, 1',

P_GROUP_ID,

0,

1,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

NULL,

0,

NULL

);

COMMIT;

return(req_id);

END WIP_MASS_LOAD;

 

PROCEDURE ZDL_PRE_UPDATE IS

cursor c1 is 

select rowid,bkc_id,location_id,action_id,job_number 

from zdl_bkc_job_update where updated_flag = 'N';

p_c1_rec c1%rowtype;

p_count number default 0;

begin

delete 

from zdl_bkc_job_update z1

where rowid != 

(select 

max(rowid) 

from 

zdl_bkc_job_update z2 

where 

z1.bkc_id = z2.bkc_id and

z1.location_id = z2.location_id and

z1.action_id = z2.action_id and

z1.job_number = z2.job_number AND

Z1.UPDATED_FLAG = z2.updated_flag)

and z1.updated_flag = 'N';

commit;

open c1;

loop

fetch c1 into p_c1_rec;

exit when c1%notfound;

if p_c1_rec.action_id = 3 then

select count(*) into p_count 

from zdl_bkc_job_update

where bkc_id = p_c1_rec.bkc_id and 

location_id = p_c1_rec.location_id and

action_id = 7 and

job_number = p_c1_rec.job_number AND UPDATED_FLAG = 'N';

if p_count > 0 then

delete from zdl_bkc_job_update 

where rowid = p_c1_rec.rowid;

commit;

end if;

end if;

end loop;

end ZDL_PRE_UPDATE;

 

FUNCTION ZDL_UPDATE_ORACLE_WIP(P_USER_ID IN NUMBER) RETURN NUMBER

IS

P_GROUP_ID NUMBER;

P_REQ_ID NUMBER;

p_bkc_id number;

p_action_id number;

p_location_id number;

p_job_number varchar2(240);

p_count boolean default false;

p_count_item number;

cursor c1 is 

select bkc_id,action_id,location_id,job_number 

from  zdl_bkc_job_update

where action_id = 3 and location_id = 1 AND UPDATED_FLAG = 'N';

cursor c2 is 

select bkc_id,action_id,location_id,job_number 

from  zdl_bkc_job_update

where action_id = 7 AND UPDATED_FLAG = 'N';

begin

ZDL_JOB_PKG.ZDL_PRE_UPDATE;

select wip_job_schedule_interface_s.nextval into p_group_id from sys.dual;

open c1;

loop

fetch c1 into p_bkc_id,p_action_id,p_location_id,p_job_number;

exit when c1%notfound;

zdl_job_pkg.zdl_update_job(p_bkc_id,p_group_id,0,P_USER_ID);

end loop;

if c1%rowcount > 0 then

UPDATE zdl_bkc_job_update SET UPDATED_FLAG = 'Y',UPDATED_DATE = SYSDATE

where action_id = 3 and location_id = 1 AND UPDATED_FLAG = 'N';

p_count := true;

end if;

close c1;

commit;

open c2;

loop

fetch c2 into p_bkc_id,p_action_id,p_location_id,p_job_number;

exit when c2%notfound;

zdl_job_pkg.zdl_insert_job(0,0,p_job_number,p_group_id,0,3,7,P_USER_ID,NULL);

end loop;

if c2%rowcount > 0 then

p_count := true;

UPDATE zdl_bkc_job_update SET UPDATED_FLAG = 'Y',UPDATED_DATE = SYSDATE

where action_id = 7 AND UPDATED_FLAG = 'N';

end if;

close c2;

commit;

 

if p_count then 

P_REQ_ID := ZDL_JOB_PKG.WIP_MASS_LOAD(P_GROUP_ID,P_USER_ID);

else

p_req_id := 0;

end if;

RETURN(P_REQ_ID);

end ZDL_UPDATE_ORACLE_WIP;

 

FUNCTION ZDL_JOB_STATUS (P_JOB_NUMBER IN VARCHAR2) RETURN NUMBER

AS

P_STATUS_TYPE NUMBER;

BEGIN

SELECT 

STATUS_TYPE INTO P_STATUS_TYPE

FROM 

WIP_DISCRETE_JOBS WDJ,

WIP_ENTITIES WE

WHERE WE.WIP_ENTITY_ID = WDJ.WIP_ENTITY_ID AND

WDJ.ORGANIZATION_ID = WE.ORGANIZATION_ID AND

WE.WIP_ENTITY_NAME = P_JOB_NUMBER;

RETURN (P_STATUS_TYPE);

END ZDL_JOB_STATUS;

 

END ZDL_JOB_PKG;

 

 

 

 

自我補充:

日期函數:

1、 求某天是星期幾  
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day') from dual;  
星期一  
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;  
monday  
設置日期語言  
ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';  
也可以這樣  
TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')  

2、 兩個日期間的天數  
select floor(sysdate - to_date('20020405','yyyymmdd')) from dual; 

 

3、 時間為null的用法  
select id, active_date from table1  
UNION  
select 1, TO_DATE(null) from dual;  
注意要用TO_DATE(null)  

 

4、 處理月份天數不定的辦法  
select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual  

 

5、  找出今年的天數  
select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual  

6、 閏年的處理方法  
to_char( last_day( to_date('02' || :year,'mmyyyy') ), 'dd' )  
如果是28就不是閏年  

 

7、 5秒鍾一個間隔  
Select TO_DATE(FLOOR(TO_CHAR(sysdate,'SSSSS')/300) * 300,'SSSSS') ,TO_CHAR(sysdate,'SSSSS')  
from dual  

2002-11-1 9:55:00 35786  
SSSSS表示5位秒數  

 

8、 一年的第幾天  
select TO_CHAR(SYSDATE,'DDD'),sysdate from dual  
310 2002-11-6 10:03:51  

 

9、 floor((date2-date1) /365) 作為年  
floor((date2-date1, 365) /30) 作為月  
mod(mod(date2-date1, 365), 30)作為日.  
23.next_day函數  
next_day(sysdate,6)是從當前開始下一個星期五。后面的數字是從星期日開始算起。  
1 2 3 4 5 6 7  
日 一 二 三 四 五 六

 

10、 extract()找出日期或間隔值的字段值 
date_value:=extract(date_field from [datetime_value|interval_value]) 
SQL> select extract(month from sysdate) "This Month" from dual; 

This Month 
---------- 
         11 

SQL> select extract(year from add_months(sysdate,36)) "3 Years Out" from dual; 

3 Years Out 
----------- 
        2006

 

11、 localtimestamp()返回會話中的日期和時間 
timestamp_value:=localtimestamp 
SQL> column localtimestamp format a28 
SQL> select localtimestamp from dual; 

LOCALTIMESTAMP 
---------------------------- 
13-11-03 12.09.15.433000 
下午

 

12、 decode()函數

 

先構造一個例子,假設我們想給智星職員加工資,其標准是:工資在8000元以下的將加20%;工資在8000元以上的加15%,通常的做法是,先選出記錄中的工資字段值? select salary into var-salary from employee,然后對變量var-salaryif-then-elsechoose case之類的流控制語句進行判斷。 如果用DECODE函數,那么我們就可以把這些流控制語句省略,通過SQL語句就可以直接完成。如下:select decode(sign(salary - 8000),1,salary*1.15,-1,salary*1.2,salary from employee 是不是很簡潔?

使用方法:

  1、比較大小

  select decode(sign(變量1-變量2),-1,變量1,變量2) from dual; --取較小值

  sign()函數根據某個值是0、正數還是負數,分別返回0、1、-1

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM