再談 Formsville

來源:互聯網
上載者:User

http://www.oracle.com/technology/global/cn/pub/articles/muir-forms.html

 

瞭解許多基於 Oracle Forms 的應用程式常用的主要體繫結構概念,仍然是十分重要的。

2008 年 6 月發表

新程式員在轉到運行傳統 Oracle Forms 和 Oracle Designer 應用程式的 Oracle 網站時,將面臨許多挑戰。新程式員在很大程度上將依賴於進階程式員來教他們如何構建應用程式的結構,以及從來之不易的經驗中所瞭解到的此類結構的優點。當然,圍繞 Oracle Forms 確實存在著大量的最佳實務,而且 Oracle Designer 也為 Oracle Forms 體繫結構提供了獨特的設計方法。但是在許多網站,進階程式員已進一步深入其研發工作,留下他們的後續程式員猜測為何要將應用程式構建為目前的結構。隨著不斷增加的維護問題的修複壓力,原有解決方案的簡潔性可能會受到損害。

對於初次接觸 Oracle Forms 的人員,本文將嘗試解釋許多基於 Oracle Forms 和 Oracle Designer 的應用程式常用的主要體繫結構概念,包括其優點以及如何善用之。本文特別著重介紹以下內容:

  • 簡單的 Oracle Forms 觸發器體繫結構
  • 靈活的公司-應用程式-表單 Oracle Forms 庫體繫結構
  • 將方法擴充到從 Oracle Designer 產生的表單
  • Oracle Designer 構件,包括表 API、cg_ref_codes 和日誌表。
簡單的 Oracle Forms 觸發器體繫結構

不同的開發人員在處理不同問題時,會提出同樣的最佳實務解決方案,這在計算中常常是令人驚訝的事情。有時,這來自於難得的經驗、巧妙的編程,或只是來自積極傾聽 Oracle 或者 Oracle 使用者群活動上討論的最佳實務。Oracle Forms 應用領域內出現的此類常用解決方案正是我們所謂的 Oracle Forms 觸發器架構。從 Oracle Forms 4.5 版本直到最新版本,此編程架構都已證明十分有用,並且可在許多 Oracle 網站的不同混合表單中找到。

在本部分中,我們將描述觸發器體繫結構及其構建方式以及其主要的優缺點。對於熟悉 Oracle Headstart 的人員,這兩種方法之間存在明確的相似性。

註:Oracle Headstart 是與 Oracle JHeadstart(“Java”Headstart)目的相同的產品,前者僅針對 Oracle Designer 和 Oracle Forms,而後者則支援 Oracle JDeveloper 和 Oracle 應用開發架構 (Oracle ADF)。Oracle Headstart 曾經一度是許多進行“100% 產生”的 Oracle 網站的選擇,並且是當時從 Oracle Designer 產生 Oracle Forms 應用程式的最佳實務技術。

目標

觸發器架構的目標包括三個方面:

• 刪除“觸發器四處散落的片段”— 為了避免前一程式員在項級、塊級和表單級編碼出數以百萬計的觸發器的可怕情景,這些觸發器是非常難以調試和搜尋的。

• 增加觸發器類型和觸發時間的透明度,而不必特別記住每個觸發器類型的獨特性,這對於不熟悉 Oracle Forms 但分配了維護現有 Oracle Forms 系統任務的初級程式員來說尤為重要。

• 通過更簡便的調試來降低維護成本 — 歸因於 Oracle Forms 調試器在多個版本中都無法使用的廣為人知的事實。由於我在使用不同版本 Oracle Forms 的客戶網站之間移動,我發現這個優勢特別重要。

實施架構

此架構有兩個規則:

• 無項級觸發器,所有項級觸發器均已提升為塊級。

• 除了調用程式單元的觸發器外,觸發器中無代碼。

第一個規則意味著不應編寫項級觸發器,必須在塊級執行此工作。第二個規則意味著塊級或表單級觸發器將調用傳入觸發器/事件名稱的程式單元,定義如下所示。

此架構要求

• 每個塊有一個程式包 — 至少每個包含觸發器代碼的塊都有一個程式包。

• 一個表單有一個單獨的程式包 — 至少包含觸發器代碼的表單有一個程式包。

例如,對於具有兩個塊 ORGANISATIONS_BLK 和 EVENTS_BLK 的表單,表單的觸發器代碼和兩個塊將需要三個程式包,即 FORMS_PKG、ORGANISATIONS_BLK_PKG 和 EVENTS_BLK_PKG。

觸發器的定義如下所示:

在表單級或塊級定義的任何觸發器的格式應如下所示 — 注意上述的兩個架構規則,我們不定義項級觸發器:

FORM.WHEN-NEW-FORM-INSTANCE 觸發器:
    form_pkg.event_handler('WHEN-NEW-FORM-INSTANCE');
 
BOOKINGS_BLK.WHEN-VALIDATE-ITEM 觸發器:
    bookings_blk_pkg.event_handler('WHEN-VALIDATE-ITEM');

注意每個程式包如何帶有 event_handler 方法,我們將調用此方法傳入已觸發的觸發器名稱,這將引導我們進入下一討論點:

每個程式包都要求:

• 採用以下規範的單個方法處理常式:

PROCEDURE event_handler(i_trigger IN VARCHAR2) IS ....

現在 event_handler 中將有一個大型 IF-ELSIF-ELSE-THEN(或 CASE)語句,具體取決於 Oracle Forms 中的 PL/SQL 版本,該語句用於確定已觸發了哪個觸發器或要調用哪個其他過程來處理事件。

從潛在意義來講,如果觸發器是 event_handler 過程中的項級觸發器,則還需派生出 :system.cursor_item 以瞭解哪個項觸發了觸發器,從而確定要執行的代碼。

讓我們舉個例子來協助解釋上面的內容。

假設在 BOOKINGS_BLK 中,對於 STATUS 和 NUMBER_ATTENDEES 這兩項,我們希望基於 WHEN-VALIDATE-ITEM 觸發器在這些欄位上編寫代碼以執行資料驗證。

考慮到上文解釋的觸發器架構,我們不會為每項建立兩個單獨的 WHEN-VALIDATE-ITEM 觸發器,相反我們將在 BOOKINGS_BLK 級建立一個 WHEN-VALIDATE-ITEM 觸發器:

bookings_blk_pkg.event_handler('WHEN-VALIDATE-ITEM');

event_handler 常式如下所示:

PACKAGE BODY bookings_blk_pkg IS
  PROCEDURE event_handler(i_trigger IN VARCHAR2) IS
    k_trigger_item CONSTANT VARCHAR2(500) := :system.cursor_item;
  BEGIN
    IF i_trigger = 'POST-QUERY' THEN
       ...do something;
    ELSIF i_trigger = 'WHEN-VALIDATE-ITEM' THEN
      IF k_trigger_item = 'BOOKINGS_BLK.STATUS' THEN
         ...do something for status;
      ELSIF k_trigger_item = 'BOOKINGS_BLK.NUMBER_ATTENDEES' THEN
         ...do something for number_attendees;
      ELSE
        NULL; -- Do nothing; other items have no validation
      END IF;
    ELSE
      -- unhandled trigger; programmer error
      RAISE FORM_TRIGGER_FAILURE;    
    END IF;
  END event_handler;
END bookings_blk_pkg;

從以上代碼可知,處理 STATUS 或 NUMBER_ATTENDEES 欄位時,通常需要進行一個程序呼叫,除非有少量代碼。任何此類過程將保留在同一程式包 BOOKINGS_BLK_PKG 中,以便對代碼進行邏輯分組。

調試的優勢

除了將使用者相似的代碼分組到程式包的邏輯優勢之外,還可以利用此方法的以下優勢:

• event_handler 充當所有觸發事件的阻塞點。無論您使用 Oracle Forms 調試器還是功能良好的舊式內建的訊息 Forms,均可將一個斷點或對訊息的調用置於 event_handler 過程的開頭,以確定觸發器和觸發時間。這對初級程式員尤其有用,因為它使觸發器的觸發順序立刻明顯起來。

• 如果表單出現故障且您懷疑這是由於多個觸發器的互動所致,只需在 event_handler 過程中的觸發器勾子前面加上注釋符號,即可有效禁用代碼。將這種情況與不同表單的項級上有眾多 WHEN-VALIDATE-ITEM 觸發器的情況進行比較;使用注釋符號來禁用所有觸發器是件非常困難的任務,尤其是在漏掉一個觸發器的時候。

缺點

此方法存在下列缺點:

• 如果刪除對 event_handler 的調用,則還需刪除 event_handler 代碼。否則,代碼中將保留一個掛起的冗餘事件處理常式。

• 此代碼的效能會受到影響,因為它需要一個程序呼叫,然後需要在 event_handler 過程中遍曆一個(可能)非常龐大的 IF-ELSIF-ELSE-THEN 結構。此外,對於某些項,觸發器處理常式中實際上不存在對特定項執行的代碼,從而導致不必要的處理。

靈活的公司-應用程式-表單 Oracle Forms 庫體繫結構

上述方法允許您使用標準的事件處理常式機制來添加表單特定代碼,但對於需要在應用程式中的多個表單之間甚至組織的多個應用程式之間實現標準化的代碼來講,該怎麼辦呢?為了實現此目標,我們將使用 PL/SQL 庫。

目標

我們希望所有表單以類似方式工作。我們希望觸發器在預設情況下執行標準公司代碼。此外,如有必要,我們還希望允許 Oracle Forms 在某一特定應用程式中將應用程式級的代碼添加至公司代碼或改寫公司代碼。

實施架構

此架構需要以下結構:

• 每個表單都附加一個應用程式 PL/SQL 庫。

• 每個應用程式 PL/SQL 庫都附加一個公司 PL/SQL 庫。

• 在所有表單中都定義一組標準的表單級觸發器。每個觸發器都將調用應用程式級事件處理常式。

• 預設情況下,應用程式庫中的事件處理常式將調用公司庫中的事件處理常式。

例如,讓我們考慮需要以下 Oracle Forms 行為的組織:

• 進入任何錶單的正常行為是執行查詢。

• 對於登記應用程式,我們還希望執行一些其他代碼來定義進入登記表單的許可權。

• 我們希望禁用所有表單的編輯按鍵。

考慮表單 BK0010.fmb。該表單有一個附加的應用程式庫 APPPLSTD.PLL,而該應用程式庫也相應地有一個附加的公司級庫 COMPLSTD.PLL。

BK0010 表單中的 WHEN-NEW-FORM-INSTANCE 觸發器包含以下代碼:

-- perform normal application processing
app_event_handler_pkg.handle_event('WHEN-NEW-FORM-INSTANCE');

APPPLSTD.PLL 中的 app_event_handler_pkg 程式包將包含以下代碼:

PACKAGE BODY app_event_handler_pkg IS
  PROCEDURE handle_event(i_trigger IN VARCHAR2) IS
  BEGIN
    IF i_trigger = 'WHEN-NEW-FORM-INSTANCE' THEN
      -- call an application specific procedure
      security_handler_pkg.set_block_privs;
      -- now call the standard corporate processing
      com_event_handler_pkg.handle_event(i_trigger);
    ELSIF i_trigger = 'KEY-EDIT' THEN
      -- no application specific code just call the corporate code
      com_event_handler_pkg.handle_event(i_trigger);
    ELSIF i_trigger = 'PRE-FORM' THEN
      -- no application specific code just call the corporate code
      com_event_handler_pkg.handle_event(i_trigger);
    ..... trap other standard trigger events
    .........................................
ELSE
      -- unhandled trigger; programmer error     
      RAISE FORM_TRIGGER_FAILURE;   
    END IF;
  END handle_event;
END app_event_handler_pkg;

注意,security_handler_pkg 程式包是特定於應用程式的,並且將在應用程式庫 APPPLSTD.PLL 中定義。

COMPLSTD.PLL 中的 app_event_handler_pkg 程式包將包括以下代碼:

PACKAGE BODY com_event_handler_pkg IS
  PROCEDURE handle_event(i_trigger IN VARCHAR2) IS
  BEGIN
    IF i_trigger = 'WHEN-NEW-FORM-INSTANCE' THEN
      -- execute the corporate processing
      initialise_pkg.perform_query;     
    ELSIF i_trigger = 'KEY-EDIT' THEN
      -- disable the normal key-edit behaviour
      NULL;
    ELSIF i_trigger = 'PRE-FORM' THEN
      -- no corporate code for this trigger event;
      NULL;
    ..... trap other standard trigger events
    .........................................
    ELSE
      -- unhandled trigger; programmer error
      RAISE FORM_TRIGGER_FAILURE;    
    END IF;
  END handle_event;
END com_event_handler_pkg;

請注意,initialise_pkg 程式包是特定於公司的,而且將在公司庫 COMPLSTD.PLL 中定義。

優勢

此方法提供了以下優勢:

• 標準化。此方法的主要優勢是對組織或應用程式中的 Oracle Forms 處理進行標準化的能力。如果已設定模板表單來使用此觸發器/庫結構,則從模板建立的任何錶單都會預先內建此標準處理,而無需開發人員採取任何措施。

• 維護。 此方法還更便於將代碼添加到整個應用程式或組織。添加到應用程式或公司庫中的事件處理常式的任何代碼將立即應用於所有表單。這比開啟每個表單並添加其他代碼要容易得多。

缺點

此方法存在下列缺點:

• 對應用程式或公司庫進行的任何更改都可能會對大量表單產生重大影響。部署前要謹慎控制和嚴格測試對這些庫所做的更改,這一點至關重要。

• 開發人員可以通過在表單的塊級或項級建立觸發器來改寫標準處理。這是此方法的一個預設特性,如上例所示,我們希望為表單中的特定項啟用 KEY-EDIT 功能。然而在某些情況下,這可能導致意外改寫公司或應用程式處理。開發人員理解此類結構並謹慎定義觸發器的執行層次非常重要。

• 程式單元的命名十分重要。在編譯時間,Oracle Forms 將首先在表單中尋找程式單元,然後按程式單元在 Application Navigator 中的顯示順序在附加的庫中進行尋找,最後會在資料庫中進行尋找。確保庫階層中的不同層級上的程式單元具有不同的名稱,以防止衝突。

將方法擴充到從 Oracle Designer 產生的表單

Oracle Designer 曾是許多 Oracle 網站選擇的 CASE 工具,但如今已讓位於相對現代的軟體開發工具(如 JDeveloper)。從 Oracle Designer 產生表單時,許多開發人員的目的是實現“100% 產生”,或者至少是最大限度地減少對錶單所做的產生後更改。(實現 100% 產生曾一度成為 Oracle Designer 和 Oracle Forms 開發夢寐以求的目標。)實現此目的的一個輔助方法是將上述庫結構擴充為一個三層結構,其中每個表單都具有自己的附加 PL/SQL 庫。此庫包括表單特定代碼。

實施

考慮上例中所述的 BLK0010 表單。使用三層結構,該表單將具有自己的附加庫 BK0010.PLL。該庫包含

• 一個模組事件處理常式,類似於上文為應用程式描述的事件處理常式。

• 特定於表單模組的所有代碼。

• 對應用程式級事件處理常式的調用。

BK0010 表單中的 WHEN-NEW-FORM-INSTANCE 觸發器包含以下代碼:

-- perform module specific processing
mod_event_handler_pkg.handle_event('WHEN-NEW-FORM-INSTANCE');

BK0010.PLL 中的 mod_event_handler_pkg 程式包包括以下代碼:

PACKAGE BODY mod_event_handler_pkg IS
  PROCEDURE handle_event(i_trigger IN VARCHAR2) IS
  BEGIN
    IF i_trigger = 'WHEN-NEW-FORM-INSTANCE' THEN
      -- call a module specific procedure
      form_pkg.event_handler('WHEN-NEW-FORM-INSTANCE');
      -- now call the standard application processing
      app_event_handler_pkg.handle_event(i_trigger);    
    ELSIF i_trigger = 'KEY-EDIT' THEN
      -- no module specific code just call the application code
      app_event_handler_pkg.handle_event(i_trigger);
    ..... trap other standard trigger events
    .........................................
    ELSE
      -- unhandled trigger; programmer error
      RAISE FORM_TRIGGER_FAILURE;    
    END IF;
  END handle_event;
END mod_event_handler_pkg;

本文第一部分中所述的程式包(例如,form_pkg)將保留在表單特定庫 BK0010.PLL 中,而非表單本身中。

優勢

使用此結構的主要優勢是可以將代碼更改有效地外部化。由於表單僅包含“勾子”而非代碼本身,因此幾乎不需要更改表單模組。相反,可以在附加到表單的模組特定庫中添加和更改代碼。

缺點

此方法的管理工作有些繁瑣,因為它可能導致大量的 PL/SQL 庫,最終達到一個表單一個庫。

Oracle Designer 構件

Oracle Designer 還提供了許多公用程式來協助開發過程。其中包括以下內容:

管理引用代碼

將引用資料的有效值作為域輸入 Oracle Designer 中。然後,可以使用這些域產生引用代碼錶。根據在 Oracle Designer 中選擇的喜好設定,將表命名為 CG_REF_CODES 或 APP_REF_CODES(其中 APP 是應用程式的縮寫)。該表可用於有效值或有效範圍。

此表的結構如下所示:

列名

用途

樣本 1

樣本 2

RV_DOMAIN

代碼的類型

COUNTRY

WORKING_DAYS

RV_LOW_VALUE

有效範圍的下限值,或有效值

AUS

0

RV_HIGH_VALUE

上限值(如果有的話)

 

7

RV_ABBREVIATION

產生的程式碼中使用的縮寫

A

 

RV_MEANING

有效值說明

Australia

 

在樣本 1 中,您將看到 COUNTRY 域的若干行。這些行將用於驗證和填充彈出式列表。

樣本 2 用於產生表單驗證,確保 WORKING_DAYS 域中的任一列的值介於 0 和 7 之間。

API 和觸發器

使用 Oracle Designer 開發的應用程式可以針對每個表包括一組程式包和觸發器。在以下描述中,名為 ORGANISATIONS 的表用於所有樣本中。

表 API

表程式包名為 cg$table_name(例如,CG$ORGANISATIONS),對於每個表,它包括以下結構:

類型

cg$row_type

一個記錄,包括資料類型和 ORGANISATIONS 中的每一列相匹配的一組欄位,此外還包括其他記錄欄位和行識別欄位。

cg$ind_type

一個記錄,包含表中每一列的布爾欄位。這些指示符用於記錄是否在 DML 語句中提供了列的值。

cg$pk_type

一個記錄,其結構與表的主鍵相匹配。

cg$table_type

ORGANISATIONS 記錄表。

cg$tableind_type

cg$ind_type 表。

可以使用提供的過程執行所有標準 DML 操作和一些其他驗證。

過程

ins

將記錄插入表中。
接受類型為 cg$row_type 的參數 cg$rec,該參數包含要插入 ORGANISATIONS 表中的行的值。
還接受 cg$ind_type 類型的參數 cg$ind(指示提供的列),還接受一個布爾參數 do_ins(指示應執行插入)。

upd

更新表中的一條記錄。
接受 cg$row_type 類型的參數 cg$rec,該參數包含要更新到 ORGANISATIONS 表中的行的值。
還接受 cg$ind_type 類型的參數 cg$ind(指示提供的列),還接受一個布爾參數 do_upd(指示應執行更新)。
更新主鍵時,還會使用 cg$row_type 類型的參數 cg$pk。

del

刪除表中的記錄。
接受 cg$pk_type 類型的參數 cg$pk,該參數包含要刪除的記錄的主鍵,還接受參數 do_del(指示應執行刪除)。

lck

鎖定表中的記錄。
接受 cg$row_type 類型的參數 cg$old_rec,該參數包含在進行任何更改前要鎖定的記錄的值。
還接受 cg$ind_type 類型的參數 cg$old_ind(指示在進行任何更改前記錄中非空的列),還接受一個用於確定鎖定行為的參數 nowait_flag。

slct

使用主鍵選擇記錄。
接受 cg$row_type 類型的參數 cg$sel_rec,該參數包含主鍵,使用此主鍵提取記錄,然後將其返回到記錄中。

validate_domain

驗證引用代碼。
接受 cg$row_type 類型的參數 cg$rec(包含要驗證的記錄),還接受一個記錄 cg$ind(指示要求驗證的欄位)。此過程提供根據前述的標準 cg_ref_codes 表執行驗證的功能。

insert_jn

建立日誌行。
接受 cg$row_type 類型的參數 cg$rec,該參數包含來自 DML 語句的值和更改原因。
還接受一個巨集指令引數,記錄已發生的 DML 操作的類型。將記錄插入標準記錄資料表 ORGANISATIONS_JN 中。

此外還包括其他過程,但它們都遵循類似模式。

程式包中的主要過程均將全域變數 called_from_package 設定為 TRUE,指示從表 API 中起動 DML 語句。

優勢

使用表 API 對錶執行所有操作的結果是將所有商務規則都放在一個單獨的位置中 — 從根本上說,就是資料庫。如果選擇在應用程式的中介層或前端編碼商務規則,則在為應用程式新增內容,或允許使用其他工具直接存取表時,可能會輕易錯過這些商務規則。

如果授予使用者執行程式包的許可權,而不是對錶執行操作的直接許可權,則可確保對錶所做的所有更改都通過表 API 進行。這不僅可以確保執行所有驗證,而且可以提供一個集中點進行調試。

缺點

此方法相當冗長並會導致大量程式碼,這會使缺乏經驗的開發人員感到困惑。

從效能角度來講,這些過程將對單個記錄執行 DML。由於這些過程最初是在不能使用 FORALL 子句進行批量處理時開發的,因此它們不能利用該子句提供的效能優勢。

維護工作可能會更加困難和耗時。如果更改了表的結構,例如添加了列,則需要對錶 API 中的過程進行相應的更改。

觸發器

除了表 API 以外,在某些情況下,還會使用 Oracle Designer 為每個表建立一組觸發器。在 DML 語句訪問表,但未通過表 API 起動 DML 時,應使用觸發器。在這種情況下,全域變數 called_from_package 將為空白。

觸發器在每個操作中的語句層級和行層級建立,這需要發生一些處理。調用的代碼將鏡像程式包。

觸發器根據觸發事件和觸發層級來命名。使用 ORGANISATIONS 表作為樣本,更新觸發器的命名方式如下:
cg$BUS_ORGANISATIONS:之前,更新語句級觸發器
cg$BUR_ORGANISATIONS:之前,更新行級觸發器
cg$AUR_ORGANISATIONS:之後,更新行級觸發器
cg$AUS_ORGANISATIONS:之後,更新語句級觸發器

優勢

使用這些觸發器可以確保應用商務規則(如驗證),而不必管 DML 語句的來源如何。這可以防止直接更改表的 SQL 繞過驗證代碼。

缺點

即使是從表 API 程式包起動處理,這些觸發器還是會觸發。一旦代碼確定變數 called_from_package 已設定為 TRUE,就會繞過其餘代碼。然而,這仍將導致觸發器執行,從而帶來相關的效能開銷。

維護工作可能會更加困難和耗時。如果更改了表的結構(例如,添加了一列),則需要對觸發器代碼進行相應的更改。

模組 API

此方法的一個擴充是使用 PL/SQL 程式包作為資料來源和每個表單塊的目標。如果使用此方法,您還將發現每個表單塊都有一個程式包,如下所述:

程式包 cgc$BK0020_ORGANISATIONS 用於對 BK0020 表單中的 ORGANISATIONS 塊執行操作。

此程式包包含一組過程,它們接受 cgc$rec_tab 類型的 PL/SQL 表。這是一個記錄表,這些記錄與表單塊中包含的欄位相匹配。這些過程用於支援表單塊的標準插入 (ins)、更新 (upd)、刪除 (del)、鎖定 (Lck) 和查詢 (qry) 行為。每個過程將在 PL/SQL 表的記錄周圍環回,然後從表 API 中調用相應的過程。

例如,為了更新記錄,表單塊會將已更改的記錄傳遞給 cgc$BK0020_ORGANISATIONS.upd。對於傳遞給 cgc$BK0020_ORGANISATIONS.upd 的 PL/SQL 的表中的每個記錄,將調用 cg$ORGANISATIONS.upd 過程來更新記錄。

此處的例外情況是 qry 過程,它不調用相應的表 API。該過程使用動態 SQL 查詢基礎資料表並返回結果。

優勢

通常,此方法僅用於複雜的表單,其中由塊執行的處理要比在單個表上執行 DML 語句複雜得多。此方法允許將其他代碼添加到模組 API,從而極大地增強(或繞過)正常的 Oracle Forms 處理。

缺點

此方法將導致雙層 API 結構,這將明顯增加應用程式中的程式碼。

使用此技術時,維護工作比較困難,因為對錶單塊所做的更改(如添加欄位)需要對兩個層級的程式包的每個程式包中的多個過程變更。

日誌表

Oracle Designer 提供了一種建立日誌表的標準方法,該方法將審核父表上的所有 DML,最終記錄所有資料更改。通過 Oracle Designer 中的喜好設定設定,在產生表 DDL 時,將建立一個相應的日誌表。日誌表的結構將和原始表中的列匹配,並將增加一些用於審核更改操作的列。

通常使用上述的表 API 的 insert_jn 過程填充日誌表。

增加的列包括

JN_OPERATION

DML 操作,例如 UPDATE

JN_ORACLE_USER

執行更改的會話的 Oracle 使用者名稱

JN_DATETIME

更改日期和時間

JN_NOTES

更改原因,由表單中的使用者提供

JN_APPLN

起動更改的過程的名稱,例如 cg$ORGANISATIONS.upd

JN_SESSION

執行更改的會話的會話 ID

優勢

此方法提供了有關 DML 語句中的值的全面日誌,而且不需要開發人員投入太多的精力,便可輕鬆回答刪除記錄或更改記錄的人員的問題。

缺點

此方法依賴於 Oracle Designer 表 API 和觸發器的使用。如果移除這兩項,則不發生日誌記錄。對於要執行插入日誌表的表,許多網站現在都使用人工觸發器來替代此方法。

結論

當代碼層明顯較多,但缺乏經驗或不能理解以前的Team Dev放置代碼的原因時,繼承原有系統是一項非常艱難的任務。Oracle Forms 和 Oracle Designer 一直是並且仍是構建大型公司系統的重要工具。因此,儘管許多系統中仍提供最佳實務,但不具備相應背景的初級程式員卻很少予以重視。對這些最佳實務的一種理解是將其視為為系統未來的活動保留,而無需探究看似簡單的一次性修複程式的代碼。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.