久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

使用 Oracle 數(shù)據(jù)庫 10g PL/SQL 新特性

 dazheng 2007-04-15

將鼠標(biāo)置于此圖標(biāo)上可以加載和查看本教程的所有屏幕截圖,。(警告:因為此操作會同時加載所有屏幕截圖,所以網(wǎng)速較慢時,,響應(yīng)時間可能會比較長,。)

注意:此外,您還可以在下列步驟中將鼠標(biāo)放在每個單獨的圖標(biāo)上,,從而僅加載和查看與該步驟相關(guān)的屏幕截圖,??梢酝ㄟ^單擊各個屏幕截圖來將其隱藏。

在 Oracle 數(shù)據(jù)庫 10g 中,,PL/SQL 語言提供了幾個增強(qiáng)功能,。在本概述部分中,您將了解以下主題:

1.

PL/SQL 條件編譯

2. 了解批量綁定功能增強(qiáng)
3. 使用 JDeveloper 調(diào)試 PL/SQL

返回主題列表

PL/SQL 條件編譯

Oracle 數(shù)據(jù)庫 10g 第 2 版引入了對 PL/SQL 條件編譯的支持,。新語法允許編譯器根據(jù)指定條件編譯部分程序,。應(yīng)用程序開發(fā)人員通過將指令嵌入其 PL/SQL 源程序中來使用條件編譯。在提交 PL/SQL 程序進(jìn)行編譯時,,會運行指令來選擇要編譯的部分程序,。這種特性在以下情況中非常有用:

應(yīng)用程序通常包含調(diào)試或跟蹤代碼,該代碼是在開發(fā)周期內(nèi)專門針對測試編寫的,。在生產(chǎn)環(huán)境中運行應(yīng)用程序時并不需要這些代碼,。在早期版本中,所能做的就是針對生產(chǎn)完全刪除這些代碼(這會阻礙后續(xù)的調(diào)試),,或者用運行時 IF 測試將其包圍(導(dǎo)致在程序大小和執(zhí)行速度方面耗費運行時)?,F(xiàn)在,可以在開發(fā)環(huán)境中啟用調(diào)試或跟蹤功能,,并在生產(chǎn)應(yīng)用程序中禁用該功能,。

 

應(yīng)用程序通常包含自檢查代碼,以遵從良好的編程實踐,。如果程序設(shè)計所依賴的不變量被破壞,,則這種代碼將引發(fā)異常。理論上,,在生產(chǎn)環(huán)境中應(yīng)該永遠(yuǎn)不會出現(xiàn)這種異常,。然而,這些自測試會導(dǎo)致運行時消耗,,尤其是當(dāng)它們出現(xiàn)在嵌套很深的循環(huán)中時,。但是,在系統(tǒng)測試完成并啟用應(yīng)用程序前,,將其全部刪除將妨礙調(diào)試小組對首次在生產(chǎn)環(huán)境中出現(xiàn)的錯誤做出診斷,。只有少數(shù)開發(fā)團(tuán)隊會保留應(yīng)用程序源代碼的并行副本:一個用于調(diào)試,一個用于生產(chǎn),。PL/SQL 條件編譯支持新的最佳實踐:通過有選擇地編譯自檢查,,保留了診斷功能,且不耗費生產(chǎn)環(huán)境,。

 

程序包通常包含私有“幫助”子程序,,當(dāng)然,在開發(fā)期間,需要對這些子程序進(jìn)行測試,。但是,,由于它們是私有的,因此不能用外部測試工具對其進(jìn)行測試,。通過在程序包規(guī)范中的條件指令內(nèi)聲明這些“私有”子程序,,可以在開發(fā)和測試期間從程序包外調(diào)用這些程序,然后在生產(chǎn)環(huán)境中將其隱藏,。

 

應(yīng)用程序代碼經(jīng)常調(diào)用服務(wù)子程序,。這種服務(wù)子程序可能返回 PL/SQL 記錄,以描述員工何時通過其唯一標(biāo)識符進(jìn)行了調(diào)用,。最佳實踐指出,,如果假設(shè)唯一關(guān)鍵字找到多個紀(jì)錄,則該服務(wù)例程將引發(fā)定義完善的異常,。(如果數(shù)據(jù)損壞是由整個系統(tǒng)的一個有缺陷的不同組件所導(dǎo)致,,則可能會出現(xiàn)此異常。)最佳實踐進(jìn)一步指出,,調(diào)用服務(wù)子程序的應(yīng)用程序代碼必須在異常出現(xiàn)時表現(xiàn)正常,,例如向用戶顯示一個友好的、相對而言非特定的“出現(xiàn)問題”消息,,并記錄所有相關(guān)信息以向跟蹤文件詳細(xì)說明出現(xiàn)異常的來龍去脈,。當(dāng)然,必須在開發(fā)周期內(nèi)對應(yīng)用程序代碼的此種強(qiáng)健特性進(jìn)行測試,。設(shè)法損壞數(shù)據(jù)使服務(wù)子程序引發(fā)異常通常有一定難度,并且非常耗時,。條件編譯通過有條件地將代碼包含在服務(wù)子程序中隨意引發(fā)給定異常,,使您能夠以低成本獲得同樣的效果。

 

在開發(fā)期間,,程序員通常創(chuàng)建兩個版本,、獲得相同結(jié)果的編譯單元。兩種版本必須經(jīng)過測試才能確定哪個最有效,。一般而言,,兩個版本在文本上基本相同,只是在分布于整個源文件上的小關(guān)鍵點處略有不同,。在此種情況下,,與編寫兩個單獨的程序相比,編寫一個包含兩種版本的程序要更容易(不易犯人為錯誤),。條件編譯對此方法提供了豐富的支持,,而這起初需要手工生成兩種版本的源代碼。

 

在編寫某些應(yīng)用程序時不僅要考慮在最新的 Oracle 數(shù)據(jù)庫版本上運行,,而且要考慮在早期版本上運行,。通常,,開發(fā)團(tuán)隊只想保留單一的源代碼。這迫使開發(fā)人員避免在最新版本中使用新的強(qiáng)大特性(由新的 PL/SQL 語法提供),,妨礙了用戶將代碼部署 在最新的版本上,。條件編譯可用于在最新版本上和早期版上安裝程序時選擇最優(yōu)的程序源代碼。

 

Oracle 數(shù)據(jù)庫 10g 版本 10.1.0.4 或更高版本中已引入了條件編譯,。

返回主題

了解批量綁定功能增強(qiáng)

Oracle 數(shù)據(jù)庫 10g 擴(kuò)展了 Oracle9i 在批量綁定領(lǐng)域中引入的增強(qiáng)功能,。將 SAVE EXCEPTIONS 語法引進(jìn) Oracle9i,用于在批量插入(刪除或更新)行時捕獲異常,。盡管此特性使數(shù)據(jù)操作語言 (DML) 能夠繼續(xù)將所有異常保存在 SQL%BULK_EXCEPTIONS 集合中,,但操作的性能會受到顯著影響。如果正在處理的集合因所涉及的應(yīng)用程序邏輯而變得比較稀疏,,則這可能是不必要的開銷,。在 Oracle 數(shù)據(jù)庫 10g 中,您可以使用新的 INDICES OF 和 VALUES OF 特性解決這些問題,。

返回主題

使用 JDeveloper 調(diào)試 PL/SQL

從 9.0.3 版開始,,JDeveloper 支持 PL/SQL 調(diào)試。這是通過 Java 調(diào)試線路協(xié)議 (JDWP) 實現(xiàn)的,。在 Oracle9i 第 2 版(以及更高版本)中,,該調(diào)試器使用行業(yè)標(biāo)準(zhǔn),而在早期版本(Oracle8i 和 Oracle9i 第 1 版)中,,則使用 DBMS_DEBUG 程序包,。通過此調(diào)試用戶界面,您可以單步,、步進(jìn)和步過執(zhí)行 PL/SQL 對象,,還能夠在 Watch 和 Inspector 窗口中設(shè)置 PL/SQL 表達(dá)式、設(shè)置條件斷點以及查看集合數(shù)據(jù),。

返回主題

開始本教程之前,,您應(yīng)該:

1.

完成了教程在 Windows 上安裝 Oracle 數(shù)據(jù)庫 10g

2.

下載 plsql.zip 文件并將其解壓縮到您的工作目錄(如 c:\wkdir)中,。

返回主題列表

使用 PL/SQL 條件編譯

本部分將向您介紹如何使用條件編譯,,并給出了幾個用法示例。

返回主題列表

預(yù)處理器指令

指令由指令控制標(biāo)記“$”和普通的 PL/SQL 文本組成,。條件編譯使用三個指令:選擇,、查詢和錯誤。特殊的觸發(fā)器字符“$”代表條件編譯指令,。選擇指令是條件編譯機(jī)制的重要組成部分,,而查詢和錯誤指令支持有用的附加功能。

返回主題

選擇指令

選擇指令對條件編譯表達(dá)式進(jìn)行評估,并根據(jù)評估的結(jié)果選擇要包含在該編譯中的代碼,。完全忽略未選中的代碼,。這不會干擾到現(xiàn)有程序,因為這些程序并未使用條件編譯,。條件選擇指令以 $if 開始并使用常規(guī)語法:

$if <B-expr > $then
  <PL/SQL-code-fragment>
$elsif <B-expr > $then
  <PL/SQL-code-fragment>

$else
  <PL/SQL-code-fragment>
$end

其中,,<B-Expr> 表示靜態(tài)布爾表達(dá)式。靜態(tài)布爾表達(dá)式是一個或多個程序包常量或一個或多個查詢指令的任意組合,。以下是選擇指令將程序包常量用作靜態(tài)布爾表達(dá)式的示例:

$if Trace_Pkg.Trace > 2 $then  $end  

其中,,Trace_pkg 是程序包的名稱,Trace 是聲明為 PLS_INTEGER 的常量,。請注意,,如果 PL/SQL 編譯單元 U 內(nèi)的選擇指令中使用了在程序包 Trace_pkg 內(nèi)聲明的常量,那么,,U 將在 Trace_pkg 上具有一個依賴項,,就好像 Trace_pkg 已經(jīng)在常規(guī) PL/SQL 代碼中進(jìn)行了引用。

返回主題

查詢指令

查詢指令允許訪問編譯環(huán)境,,以便將選擇基于當(dāng)前環(huán)境,。查詢指令的形式為 $$<PL/SQL-identifier>。例如,,要進(jìn)行編譯的單元的 PL/SQL 編譯器參數(shù)的值(例如 PLSQL_OPTIMIZE_LEVEL),。此種查詢可以與條件選擇指令結(jié)合使用來選擇要編譯的程序部分。例如,,可以使用查詢指令查詢 PL/SQL 編譯器參數(shù)的值,。查詢指令以兩個觸發(fā)器字符 $$ 開頭,例如:

$if $$debug_level > 3 $then … $end

標(biāo)識符 debug_level 是使用 plsql_ccflags 初始化參數(shù)(Oracle 數(shù)據(jù)庫 10g 第 2 版中的新增內(nèi)容)定義的,,因此:

...plsql_ccflags    = ‘debug_level:4, ...‘

返回主題

錯誤指令

錯誤指令的形式如下所示

$error <VARCHAR2-expression> $end.

它可以使編譯器報告編譯錯誤,,包括 VARCHAR2 表達(dá)式中提供的消息。

返回主題

預(yù)定義編譯器參數(shù)

Oracle 數(shù)據(jù)庫 10g 第 2 版提供了以下可以在條件查詢指令中使用的 PL/SQL 編譯器參數(shù):

PLSQL_CCFLAGS

PLSQL_DEBUG

PLSQL_OPTIMIZE_LEVEL

PLSQL_CODE_TYPE

PLSQL_WARNINGS

NLS_LENGTH_SEMANTICS

編譯時,,PL/SQL 編譯器參數(shù)的值存儲在編譯單元中,并可以使用 all_plsql_object_settings 系列視圖進(jìn)行查看,。此外,,還提供了預(yù)定義的查詢指令 $$PLSQL_UNIT, $$PLSQL_LINE。有關(guān)條件編譯指令語法的詳細(xì)信息,,請參閱 PL/SQL 用戶指南和參考 手冊,。

返回主題

使用指令

示例 1:使用程序包常量進(jìn)行跟蹤和調(diào)試

示例 2:使用編譯器警告和 PLSQL_CCFLAGS

示例 3:使用 DBMS_PREPROCESSOR 過程打印或檢索源文本

示例 4:使用條件編譯分支代碼確定最佳性能版本

示例 5:將條件編譯與不同版本的 Oracle 數(shù)據(jù)庫結(jié)合使用

返回主題

示例 1:使用程序包常量進(jìn)行跟蹤和調(diào)試

在條件編譯指令中使用程序包常量為通過單一機(jī)制控制一個或多個 PL/SQL 編譯單元提供了一種方法。例如,,假設(shè)應(yīng)用程序由許多 PL/SQL 編譯單元組成,。在該應(yīng)用程序內(nèi),已嵌入了執(zhí)行調(diào)試或跟蹤的 ed 方法。這些方法可以通過使用程序包常量的條件編譯指令啟用,。因此,,可以通過隨時重新編譯該程序包來更改該常量的值。在重新編譯程序包時,,所有的相關(guān)對象都將自動重新編譯,,以接受該程序包常量的新值。這可以用于在整個應(yīng)用程序中啟用跟蹤和調(diào)試功能,。在進(jìn)行跟蹤和調(diào)試時,,利用保護(hù)跟蹤和調(diào)試代碼的新常量值重新編譯程序包規(guī)范。這將使所有相關(guān) PL/SQL 單元無效,,以便下一次使用時,,將不會選中跟蹤和調(diào)試代碼進(jìn)行編譯。程序包常量的使用是一種控制所有相關(guān) PL/SQL 單元的有效機(jī)制,,這些單元在選擇指令內(nèi)使用打包常量進(jìn)行條件處理,。以下示例演示了這一用法。

1.

打開一個終端窗口,,執(zhí)行以下命令:

cd\wkdir
            sqlplus hr/hr

 

2.

創(chuàng)建程序包 STATIC_CONSTANTS 以聲明可用于條件編譯的程序包常量,。從 SQL*Plus 會話中,執(zhí)行以下腳本:

@static_constants

static_constants.sql 腳本包含以下內(nèi)容:

CREATE OR REPLACE PACKAGE static_constants is
debug CONSTANT BOOLEAN := FALSE;
trace CONSTANT BOOLEAN := FALSE;
END ;
/

 

3.

創(chuàng)建兩個過程:CHECK_DEBUG(用于檢查程序包常量調(diào)試的值是否是 TRUE)和 CHECK_TRACE(用于檢查程序包跟蹤的值是否是 TRUE),。從 SQL*Plus 會話中,,執(zhí)行以下腳本:

@debug_trc

debug_trc.sql 腳本包含以下內(nèi)容:

CREATE OR REPLACE PROCEDURE check_Debug IS
BEGIN
$IF static_constants.debug $THEN DBMS_OUTPUT.put_line(‘Debugging ON‘);
$ELSE DBMS_OUTPUT.put_line(‘Debugging OFF‘); $END
END;
/
CREATE or REPLACE PROCEDURE Check_trace IS
BEGIN
$IF static_constants.trace $THEN DBMS_OUTPUT.put_line(‘Tracing ON‘);
$ELSE DBMS_OUTPUT.put_line(‘Tracing OFF‘); $END
END;
/

 

4.

Set serveroutput on 使用的是 Oracle 數(shù)據(jù)庫 10g 第 2 版中提供的新 SIZE UNLIMITED 語法。現(xiàn)在執(zhí)行這兩個過程,。您將看到它顯示跟蹤和調(diào)試均被關(guān)閉,。

注意:可以將每一行單獨地復(fù)制到 sqlplus 中,但不要一起復(fù)制這 3 個語句,。

set serveroutput on size unlimited
            exec check_debug
            exec check_trace

 

5.

現(xiàn)在,,將更改程序包常量的值。從 SQL*Plus 會話中,,執(zhí)行以下腳本

@reset_const

reset_const.sql 腳本包含以下內(nèi)容:

CREATE OR REPLACE PACKAGE static_constants is
debug CONSTANT BOOLEAN := TRUE;
trace CONSTANT BOOLEAN := TRUE;
END ;
/

 

6.

現(xiàn)在,,再次執(zhí)行這兩個過程。您將看到調(diào)試和跟蹤自動啟用了,。在重新編譯程序包時,,所有相關(guān)的對象都變?yōu)闊o效,并在下一次執(zhí)行時重新編譯,。因此,,程序包常量的新值可即刻適用于所有相關(guān)對象。

exec check_debug
            exec check_trace

這可以擴(kuò)展至任意數(shù)量的相關(guān)程序,。在需要通過單一機(jī)制控制大量程序時,,使用這個方法最為有效,。用例的其他示例包括針對同一應(yīng)用程序按州更改賦稅,或根據(jù)許可選項更改軟件特性等等,。

 

返回子主題

示例 2:使用編譯器警告和 PLSQL_CCFLAGS

通過設(shè)置 PLSQL_CCFLAGS 的值,,可以使用條件參數(shù) PLSQL_CCFLAGS 提供對指定程序的細(xì)粒度訪問。為此,,可以使用 ALTER SESSION 命令或 ALTER...COMPILE 命令,。ALTER COMPILE 命令只影響正在編譯的程序。利用 ALTER SESSION 語句之后的 CREATE or REPLACE 重新編譯這些程序,,ALTER SESSION 命令可用于影響多個程序,。

在以下示例中,要創(chuàng)建一個稱為 GET_RECORD 的過程,,以接受 employee_id 的值,,并顯示相應(yīng)的記錄。為了保持良好的編程實踐,,該過程將調(diào)用 CHECK_UNIQUE 過程來驗證每個員工記錄的唯一性,。只有極少數(shù)的情況下存在重復(fù)的記錄,程序會發(fā)出一個用戶友好的消息,,并使用名為 SEND_MESSAGE_TO_DBA 的過程向 DBA 發(fā)送預(yù)警,。然而,因為測試數(shù)據(jù)庫中的數(shù)據(jù)并不包含任何重復(fù)項,,所以可以在查詢指令中使用帶有靜態(tài)布爾表達(dá)式的 PLSL_CCFLAGS 模擬重復(fù)項,。

1.

更改會話以顯示所有的編譯器警告。從 SQL*Plus 會話執(zhí)行以下語句:

ALTER SESSION SET  plsql_warnings = ‘enable:all‘;

請注意,,已刪除了所有條件編譯指令,。

 

2.

創(chuàng)建 SEND_MESSAGE_TO_DBACHECK_UNIQUE 過程。CHECK_UNIQUE 過程包含兩個不同的代碼段,,一個用于開發(fā)中的測試,,另一個部署在最終生產(chǎn)環(huán)境中。開發(fā)代碼使用條件編譯指令,,而生產(chǎn)代碼使用傳統(tǒng)的 IF-THEN-ELSE 邏輯檢查重復(fù)的記錄,。從 SQL*Plus 會話中,執(zhí)行以下腳本:

@dba_email
            @chk_unq
            show errors

dba_email.sql 腳本包含以下內(nèi)容:

CREATE OR REPLACE PROCEDURE send_message_to_DBA(emp_id number)
IS
mailhost VARCHAR2(64) := ‘mailhost.fictional-domain.com‘;
sender VARCHAR2(64) := ‘[email protected]‘;
recipient VARCHAR2(64) := ‘[email protected]‘;
mail_conn utl_smtp.connection;
BEGIN
mail_conn := utl_smtp.open_connection(mailhost, 25);
utl_smtp.helo(mail_conn, mailhost);
utl_smtp.mail(mail_conn, sender);
utl_smtp.rcpt(mail_conn, recipient);
-- open_data(), write_data(), and close_data() into a single call to data().
utl_smtp.open_data(mail_conn);
utl_smtp.write_data(mail_conn, ‘A primary key violation has occurred for record ‘||
emp_id || ‘in the EMPLOYEES table. This is an automatically generated e-mail message. Please do not respond to this, this is an alert.‘ || chr(13));
utl_smtp.write_data(mail_conn, ‘This is line 2.‘ || chr(13));
utl_smtp.close_data(mail_conn);
utl_smtp.quit(mail_conn);
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
/

chk_unq.sql 腳本包含以下內(nèi)容:

Create or replace Procedure check_unique(emp_id NUMBER) is
v_num number;
force_pk_violation exception;
Begin
Select count(*) into v_num from employees where employee_id = emp_id;
-- production code
If v_num > 1
then SEND_MESSAGE_TO_DBA(emp_id);
raise force_pk_violation;
END IF ;
-- Development code
$if $$FORCE
$then SEND_MESSAGE_TO_DBA(emp_id);
raise force_pk_violation;
$end
END;
/


3.

現(xiàn)在,,更改會話,,將 $$force 的值設(shè)為 FALSE。從 SQL*Plus 執(zhí)行以下命令,。

ALTER SESSION SET PLSQL_CCFLAGS=‘force:FALSE‘;

 

4.

現(xiàn)在,,再次執(zhí)行 chk_unq.sql,。

因為變量 $$force 現(xiàn)在的值是 FALSE,,所以沒有出現(xiàn)警告,;

 

5.

創(chuàng)建 GET_RECORD 過程。該過程接受 employee id 并返回員工記錄,。如果 CHECK_UNIQUE 過程檢查出存在重復(fù)記錄,,則會顯示一個友好消息。從 SQL*Plus 會話執(zhí)行以下腳本:

@get_record

get_record.sql 腳本包含以下內(nèi)容:

Create or replace procedure get_record(emp_id IN NUMBER)
as
emp_record employees%rowtype;
Begin
check_unique(emp_id);
Select * into emp_record from employees where employee_id =emp_id;
Dbms_output.put_line ( ‘Name: ‘|| emp_record.first_name||‘ ‘||emp_record.last_name||‘ ‘||‘Hiredate: ‘ ||emp_record.hire_date||‘
‘||‘Job: ‘||‘ ‘||emp_record.job_id);
Exception
When others then
DBMS_OUTPUT.PUT_LINE(‘We are unable to process your request at this time.
Please try again later. We apologize for any inconvenience‘);
End;
/


6.

現(xiàn)在,,執(zhí)行 GET_RECORD 過程,,傳入 100 作為參數(shù)。

exec GET_RECORD(100)      

因為沒有重復(fù)記錄,,所以該過程成功執(zhí)行,。

 

7.

現(xiàn)在,測試是否在出現(xiàn)重復(fù)記錄時顯示消息,。更改會話,,并將 $$force 的值設(shè)為 TRUE,并再次執(zhí)行 GET_RECORD,。從 SQL*Plus 會話執(zhí)行以下命令:

ALTER SESSION SET PLSQL_CCFLAGS=‘force:TRUE‘;
            exec GET_RECORD(100) 

由于未重新編譯該過程,,因此它不會受到影響。


8.

使用 ALTER...COMPILE 語句重新編譯 CHECK_UNIQUE 過程,,并為 PLSQL_CCFLAGS 參數(shù)提供新值,。使用 REUSE SETTINGS 選項。然后,,以值 100 再次執(zhí)行 GET_RECORD,。從 SQL*Plus 會話中,執(zhí)行以下命令,。

ALTER PROCEDURE CHECK_UNIQUE compile
            plsql_ccflags = ‘force:TRUE‘ REUSE SETTINGS;
            exec GET_RECORD(100) 

現(xiàn)在,,PLSQL_CCFLAGS 值生效,因而程序發(fā)出消息,。該方法可以用于影響會話內(nèi)的特定程序,,比如后生產(chǎn)調(diào)試。然而,,每個需要新設(shè)置的程序都必須使用 CREATE OR REPLACEALTER...COMPILE 語句進(jìn)行重新編譯,。

 

返回子主題

示例 3:使用 DBMS_PREPROCESSOR 過程打印或檢索源文本

DBMS_PREPROCESSOR 子程序會在處理條件編譯指令后,打印或檢索 PL/SQL 單元的處理后源文本,。這個處理后文本是用于編譯有效 PL/SQL 單元的實際源,。執(zhí)行以下步驟:

1.

執(zhí)行以下命令,查看用于編譯有效 PL/SQL 程序的實際源代碼:

EXEC DBMS_PREPROCESSOR.PRINT_POST_PROCESSED_SOURCE(‘PROCEDURE‘, ‘HR‘, ‘CHECK_UNIQUE‘);

請注意,,已刪除了所有條件編譯指令,。

 

返回子主題

示例 4:使用條件編譯分支代碼確定最佳性能版本

Oracle 數(shù)據(jù)庫 10g 引入了 BINARY_DOUBLE 數(shù)據(jù)類型,該數(shù)據(jù)類型可用于算法密集的操作,。本例中,,將對 BINARY_DOUBLE 數(shù)據(jù)類型與 NUMBER 數(shù)據(jù)類型進(jìn)行比較,。需要在兩個不同版本中創(chuàng)建同樣的代碼,一個使用 NUMBER,,另一個使用 BINARY_DOUBLE,。然后,可將兩個版本包含在同一過程中,,以使用 PLSQL_CCFLAGS 進(jìn)行測試,。執(zhí)行以下步驟:

1.

啟用 ALTER SESSION 以設(shè)置標(biāo)記,從而在兩個版本之間進(jìn)行選擇,。首先,,選擇使用 NUMBER 數(shù)據(jù)類型。從 SQL*Plus 會話中,,執(zhí)行以下命令:

ALTER SESSION SET PLSQL_CCFLAGS = ‘ numversion:TRUE‘;

 

2.

您希望知道哪個代碼執(zhí)行速度更快,。創(chuàng)建一個 CALC_CIRCLE 過程計算給定半徑的圓的周長和面積。從 SQL*Plus 會話中,,執(zhí)行以下腳本:

@num_bdbl

num_bdbl.sql 腳本包含以下內(nèi)容:

CREATE or REPLACE PROCEDURE Calc_circle( RADIUS $IF $$NUMVERSION $THEN NUMBER 
$ELSE BINARY_DOUBLE $END)
as
SUBTYPE my_real IS
$IF $$numversion $THEN
NUMBER;
$ELSE
BINARY_DOUBLE;
$END
num_circ my_real;
num_area my_real;
BDBL_circ my_real;
BDBL_AREA my_real;
BEGIN
num_CIRC:= (3.14016408289008292431940027343666863227 * 2 * RADIUS);
NUM_AREA := (3.14016408289008292431940027343666863227*radius*radius);
DBMS_OUTPUT.PUT_LINE(‘The circumference is: ‘||num_circ);
DBMS_OUTPUT.PUT_LINE(‘The area is: ‘||num_area);
END ;
/

 

3.

執(zhí)行 CALC_CIRCLE 過程,,使用數(shù)字 1234567890 作為半徑。

set timing on
            exec calc_circle(1234567890)

 

4.

使用 ALTER COMPILE 命令將 $$numversion 的值更改為 FALSE 來編譯 CALC_CIRCLE,,并使用相同的參數(shù)再次執(zhí)行 CALC_CIRCLE,。

ALTER PROCEDURE  calc_circle COMPILE plsql_ccflags = ‘numversion :false‘ REUSE SETTINGS;
            exec calc_circle(1234567890)
            set timing off

您可以看出二者性能間的差異。本例闡明了可以使用條件編譯在相同程序內(nèi)有選擇地測試兩個版本的代碼,。

 

返回子主題

示例 5:將條件編譯與不同版本的 Oracle 數(shù)據(jù)庫結(jié)合使用

以下示例演示了 DBMS_DB_VERSION 常量與條件編譯的結(jié)合使用,。其中對 Oracle 數(shù)據(jù)庫版本和發(fā)布均進(jìn)行了檢查。這個 CHECK_VERSIONS 過程使用 COMMIT WRITE IMMEDIATE NOWAIT 命令(已在 Oracle 數(shù)據(jù)庫 10g 第 2 版中引入),。如果在 Oracle 數(shù)據(jù)庫早期版本中執(zhí)行該過程,,則無法識別該命令。因此,,該過程 DBMS_DB_VERSION 程序包檢查數(shù)據(jù)庫的版本,。如果返回的版本低于 10.2,那么將使用常規(guī)的 COMMIT 提交事務(wù),。當(dāng)在版本為 10.2 或更高版本的數(shù)據(jù)庫中執(zhí)行該過程時,,將使用 COMMIT WRITE IMMEDIATE NOWAIT 命令完成該事務(wù)。

1.

現(xiàn)在可以測試 Oracle 數(shù)據(jù)庫版本了,。從終端窗口中執(zhí)行以下腳本:

@check_version

check_version.sql 腳本包含以下內(nèi)容:

CREATE OR REPLACE PROCEDURE check_version AS
BEGIN
-- some code which performs transaction processing ...
$if DBMS_DB_VERSION.VER_LE_10_2 $then
-- traditional commit
COMMIT;
DBMS_OUTPUT.PUT_LINE (‘The transaction has been successfully committed.‘);
$else
-- faster COMMIT supported in 10.2
COMMIT WRITE IMMEDIATE NOWAIT;
DBMS_OUTPUT.PUT_LINE (‘The transaction has been successfully committed.‘);
$end
END;
/

 

2.

現(xiàn)在,,在 SQL*Plus 窗口中執(zhí)行以下命令來運行 check_version 過程。

exec check_version
            quit

check_version 的輸出說明:無論版本如何,,該過程都能成功完成,,而且對最終用戶而言是透明的。因此,,沒有理由在不同的數(shù)據(jù)庫版本中使用不同的程序單元,。

 

返回子主題

以下示例演示了如何使用 INDICES OFVALUES OF 關(guān)鍵字在 PL/SQL 中進(jìn)行批量綁定,。

當(dāng)以編程方式對記錄集合(緊密集合)進(jìn)行驗證,并從該集合中刪除無效記錄(不符合指定標(biāo)準(zhǔn)的記錄)時,,可以使用 INDICES OF 關(guān)鍵字。這會產(chǎn)生一個有效元素的稀疏集合,,隨后必須將該集合批量插入表中,。通過使用 INDICES OF 關(guān)鍵字,避免了丟失記錄異常的發(fā)生,。

當(dāng)必須將記錄集合(稀疏或緊密集合)根據(jù)某個可以或不可以復(fù)制某些記錄的條件復(fù)制到一個或多個集合變量,,然后將這些記錄插入到表中時,可以使用 VALUES OF 關(guān)鍵字,。使用“VALUES OF”語法,,結(jié)合其元素均為原始集合內(nèi)選定記錄的指針的指針數(shù)組,可以高效地完成此任務(wù),。這降低了創(chuàng)建多個數(shù)據(jù)副本的需要,。異常處理按每個指針記錄執(zhí)行,這意味著如果兩個或多個指針記錄指向同一“原始”數(shù)據(jù),,則報告的任何異常將指示迭代號(指針元素號),。

本示例使用 EMPLOYEES 表構(gòu)建一個稀疏的員工集合。

1.

必須先根據(jù)現(xiàn)有的 EMPLOYEES 表(在 hr 模式中)創(chuàng)建一個 NEW_EMPLOYEES 表,,并為 EMPLOYEE_ID 列創(chuàng)建一個唯一索引,。這將在插入重復(fù)記錄時生成異常。從終端窗口中執(zhí)行以下命令:

sqlplus hr/hr
            @setup

setup.sql 腳本包含以下內(nèi)容:

drop table new_employees;
            create table new_employees as select * from employees where 1=2;
            create unique index new_employees_employee_id
            on new_employees (employee_id);

 

2.

然后,,創(chuàng)建 P_BULK_BIND 程序包,。該程序包包含使用三種不同的方法創(chuàng)建稀疏集合并將記錄批量插入到 NEW_EMPLOYEES 表中的各種過程。

@cr_p

單擊 cr_p.sql 查看該腳本中包含的內(nèi)容,。

 

3.

為了解批量綁定如何在 Oracle 數(shù)據(jù)庫 10g 中工作,,我們先看一下它是如何在 Oracle9i 中工作的。FORALL 語句使用 SAVE EXCEPTIONS 語法抑制因為缺失記錄(稍后在 EXCEPTION 塊中打?。┒l(fā)的異常,。執(zhí)行下列命令:

set serverout on size 100000
            exec p_bulk_bind.Bulk_Insert_Pre_10g (i_make_sparse => true)

-- this code is located in the Bulk_Insert_Pre_10g procedure
            ...
            forall j in g_emp_recs.First()..g_emp_recs.Last()
            save exceptions
            insert into new_employees values g_emp_recs(j);
exception when bulk_errors then
            for j in 1..sql%bulk_exceptions.Count()
            loop
            Dbms_Output.Put_Line ( ‘Error from element #‘ ||
            To_Char(sql%bulk_exceptions(j).error_index) || ‘: ‘ ||
            Sqlerrm(SQL%bulk_exceptions(j).error_code) );
            end loop;
            ...

從輸出中,您看到每個缺失的記錄都生成了一個異常 (ORA-22160),。正如前面指出的,,即使通過 SAVE EXCEPTIONS 語法處理了剩余記錄,但如果已刪除的記錄數(shù)很大,,那么這也將導(dǎo)致性能降低,。

 

4.

下一步是使用 Oracle 數(shù)據(jù)庫 10g INDICES OF 語法忽略缺失的記錄,從而獲得更好的性能,。執(zhí)行下列命令:

exec p_bulk_bind.Bulk_Insert_With_Indices_Of (i_cause_exception => false)

在此情況下,,布爾輸入值用于忽略負(fù)責(zé)創(chuàng)建異常條件(您將在下個步驟中看到)的代碼塊,。

-- this code is located in the Bulk_Insert_With_Indices_Of
            -- procedure
            ...
            forall j in indices of g_emp_recs
            save exceptions
            insert into new_employees values g_emp_recs(j);
            ...

這次沒有因缺失記錄而引發(fā)異常。

 

5.

也可以通過將輸入?yún)?shù)集設(shè)置為 true 來運行前面的過程,。這將導(dǎo)致在插入時生成一個異常,;必須捕獲該異常(通過 SAVE EXCEPTIONS)并稍后對其進(jìn)行處理。導(dǎo)致異常的條件通過一個過程調(diào)用(將姓氏為“Ernst”和“Urman”的員工的 EMAIL 列取空)進(jìn)行模擬,。由于 EMAIL 列有一個 NOT NULL 限制,,因此這將導(dǎo)致在插入兩個相應(yīng)的記錄時生成異常。該異常稍后從 SQL%BULK_EXCEPTIONS 集合中處理,。執(zhí)行下列命令:

exec p_bulk_bind.Bulk_Insert_With_Indices_Of (i_cause_exception => true)

-- this code is located in the exception area
            -- in the Bulk_Insert_With_Indices_Of procedure
            ...
            forall j in indices of g_emp_recs
            -- between g_emp_recs.First() and g_emp_recs.Last()
            -- optional
            save exceptions
            insert into new_employees values g_emp_recs(j);
exception when bulk_errors then
            declare
            v_iteration pls_integer;
            n pls_integer;
            k pls_integer;
            begin
            for j in 1..sql%bulk_exceptions.Count()
            loop
            v_iteration := SQL%bulk_exceptions(j).error_index;
            Dbms_Output.Put_Line (
            ‘Error on the ‘ || To_Char(v_iteration)
            || ‘th iteration‘ );
            ...
                     

注意:錯誤針對迭代號進(jìn)行報告,。這是 Oracle 數(shù)據(jù)庫 10g 中一個新的異常處理功能。

 

6.

另一個方法是使用 VALUES OF 子句創(chuàng)建第二個指向原始數(shù)組元素的指針集合,。執(zhí)行下列命令:

exec p_bulk_bind.Bulk_Insert_With_Values_Of -
            (i_null_email => true, i_violate_pk => false)

Point_To_Sparse 過程用于根據(jù)與前面相同的邏輯創(chuàng)建一個指針集合,。也就是說,它指向包含姓氏中每個字母的第一個匹配項的元素,。該過程從 Bulk_Insert_With_Values_Of 過程中調(diào)用,。

-- this code is located in the Bulk_Insert_With_Values_Of
            -- procedure
            ...
            forall j in values of g_values_of_tab
            save exceptions
            insert into new_employees values g_emp_recs(j);
            ...

此結(jié)果與第 5 步中的結(jié)果相同:第五個和第十九個迭代引發(fā)異常。

 

7.

要查看報告迭代號(或指針元素號)的效果(與報告錯誤記錄索引相對),,可以在 i_violate_pk => true 的情況下運行前面的過程,。為了模擬錯誤條件,使用 Cause_Exception_For_Values_Of 過程將邊界集合 (G_EMP_RECS) 中的重復(fù)索引條目插入到指針集合 (G_VALUES_OF_TAB) 中,。因此,,這違反了唯一鍵約束(在第 1 步中創(chuàng)建),并在批量插入到 NEW_EMPLOYEES 表時引發(fā)異常,。執(zhí)行下列命令:

exec p_bulk_bind.Bulk_Insert_With_Values_Of -
            (i_null_email => false, i_violate_pk => true)

-- this code is located in the Bulk_Insert_With_Values_Of
            -- procedure
            ...
            exception when bulk_errors then
            declare
            v_iteration pls_integer;
            begin
            for j in 1..sql%bulk_exceptions.Count()
            loop
            v_iteration := SQL%bulk_exceptions(j).error_index;
            Dbms_Output.Put_Line (
            ‘Error on the ‘ || To_Char(v_iteration) ||
            ‘th iteration‘ );
-- Find the index of the offending element
            -- from the iteration number
            Dbms_Output.Put_Line (
            ‘last_name for error element: ‘ ||
            g_emp_recs(g_values_of_tab(v_iteration)).last_name );
       Dbms_Output.Put_Line (
            ‘Error was: ‘ ||
            Sqlerrm(SQL%bulk_exceptions(j).error_code) );
            end loop;
            end;
            ... 

返回主題列表

在本教程中,,您學(xué)習(xí)了如何:

如何執(zhí)行 PL/SQL 條件編譯
了解如何放寬 DBMS_OUTPUT PL/SQL 程序包的總體限制。
了解批量綁定特性

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多