日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

plsql programming 18 包

發布時間:2025/4/16 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 plsql programming 18 包 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

所謂包, 就是把一組PL/SQL 的代碼元素組織在一個命名空間下.

另外, 包的用法就類似java中的類.( 有封裝, 有重載, 沒有繼承和多肽)

1 create or replace procedure process_employee( 2 employee_id_in IN employees.employee_id%type) 3 is 4 l_full_name varchar2(100); 5 begin 6 select last_name || ' , ' || first_name 7 into l_full_name 8 from employees 9 where employee_id = employee_id_in; 10 dbms_output.put_line('The full name is : ' || l_full_name); 11 end; 12 / 13 show errors; 14 15 -- 運行1 16 begin 17 process_employee(195); 18 end; 19 / 20 -- 運行2 21 exec process_employee(195);

可以看到, 如上代碼還是基本上使用了 cs106中的軟件設計方法, 即自頂向下, 分而治之的辦法.

現在如果用戶又打來電話說"還是用姓-空格-名的格式吧", 我們就不用滿腹牢騷, 通宵加班的尋找 ||','|| 了. 相反, 我們只需要花上5秒鐘來修改 employee_pke.fullname的實現部分, 然后通知用戶一切搞定了.

上例代碼實現:

1 package employee_pkg 2 as 3 subtype fullname_t IS varchar2(200); 4 5 function fullname( 6 last_in employees.last_name%type, 7 first_in employees.first_name%type) 8 return fullname_t; 9 10 function fullname( 11 employee_id_in in employees.employee_id%type) 12 return fullname_t; 13 end employee_pkg; 14 / 15 show errors; 1 package body employee_pkg 2 as 3 function fullname( 4 last_in employees.last_name%type, 5 first_in employees.first_name%type) 6 return fullname_t 7 is 8 begin 9 return last_in || ' , ' || first_in; 10 end; 11 12 function fullname( employee_id_in in employees.employee_id%type) 13 return fullname_t 14 is 15 retval fullname_t; 16 begin 17 select fullname(last_name, first_name) into retval 18 from employees 19 where employee_id = employee_id_in; 20 21 return retval; 22 exception 23 when no_data_found then 24 dbms_output.put_line('There is no data'); 25 when too_many_rows then 26 dbms_output.put_line('There are too many rows'); 27 end; 28 end employee_pkg;

上邊的內容最好分開編譯, 先編譯聲明部分, 再編譯包體部分

初始化:oracle 負責保證每個包在每個會話會被初始化一次.

持久化, 除了數據持久化之外, 還有一個會話持久化, 這意味著如果我們連接到oracle數據庫(建立了一個會話) 然后執行一個程序給一個包級別的變量(也就是一個在包的規范部分聲明的變量, 或者雖然是在包體中聲明, 但又游離于包體中的所有程序之外的變量)賦值, 這個變量設置會一直持續會話生命期, 即便執行賦值操作的程序已經結束, 只要會話還沒有結束, 這個變量的值就會一直保持.

緩存靜態的會話信息

初始化單元可以緩存靜態會話信息, 這些信息可以持續整個會話生命期. 不過這樣會占用內存, 比如有1000個會話, 那么就要占用1000份內存, 不過這樣可以提高CPU提取數據的速度.

包體中, 把缺省值的賦值操作移動到初始化單元中.

例如:

1 create or replace package valerr 2 is 3 function get return varchar2; 4 end valerr; 5 / 6 show errors; 1 create or replace package body valerr 2 is 3 -- 一個包級別的, 但是 私有的全局變量 4 v varchar2(1) := 'ABC'; 5 6 function get 7 return varchar2 8 is 9 begin 10 return v; 11 end; 12 13 begin -- 注意這個 begin 沒有 end; 與之對應 14 dbms_output.put_line('Before i show you v...'); 15 exception 16 when others then 17 dbms_output.put_line('Trapped the error!'); 18 end valerr;

上邊的包體中的初始化單元, begin 開始, 但是沒有 end; 與之對應, 一定要注意.
為什么要有這個初始化單元的另外一個原因是, 如果你不是在初始化單元定義的變量, 如果發生異常, 是不會被捕獲的.

我們可以進一步把包設計的標準化, 以保證總有一個初始化過程, 以提示我們的組員避免以上問題, 例如:

也就是把想要初始化的內容放到一個 procedure 中, 也可以再定義一個驗證 初始化 procedure 的 verify_initialization, 然后在初始化單元里包含這兩個procedure, 這樣更標準化.

包數據可以被那些對這個包郵execute權限的程序使用(包括讀取和修改這個值) 共有的包數據非常類似于 oracle forms 中的 global 變量, 也和后者同樣危險.

如果在一個包過程中打開了一個游標, 這個游標會在整個會話生命期中一直保持著打開和可用狀態.

包游標

在包中聲明顯示游標

如果我們在聲明游標時只是聲明了游標頭, 我們就必須要在游標定義加上 RETURN 子句, 這個子句用來描述從游標中提取的數據元素.

1 create or replace package book_info 2 is 3 cursor byauthor_cur( -- 帶sql的游標, 整體 4 author_in in books.author%type) 5 is 6 select * 7 from books 8 where author = author_in; 9 10 cursor bytitle_cur( -- 帶 return 的游標頭 11 title_filter_in in books.title%type) 12 return books%rowtype; 13 14 type author_summary_rt is record( 15 author books.author%type, 16 total_page_count pls_integer, 17 total_book_count pls_integer); 18 19 cursor summary_cur( 20 author_id in books.author%type) 21 return author_summary_rt; 22 end book_info; 23 / 24 show errors; 1 create or replace package body book_info 2 is 3 cursor bytitle_cur( 4 title_filter_in in books.title%type) 5 return books%rowtype 6 is 7 select * 8 from books 9 where title like upper(title_filter_in); 10 11 cursor summary_cur( 12 author_id in books.author%type) 13 return author_summary_rt 14 is 15 select author, sum(page_count), count(*) 16 from books 17 where author = author_id; 18 end book_info; 19 / 20 show errors; 21

注意: 上邊包體并沒有把包聲明中的所有內容都實現, 但是帶有 return 的游標必須要實現.

直接定義變量, 是包中一個游標的類型, 然后直接打開, 提取, 關閉 游標就可以了.

以上游標要作為一個整體, 打開, 提取, 關閉 一體就沒有問題了.

建議, 專門構建一個打開游標, 關閉游標的過程.

?

這樣, 和包游標有關的所有復雜操作都被放在過程中完成.

剛剛說了, 包是在整個會話期間都可以使用, 占用了大量內存, 但是這樣也有好處, 同時也有辦法不這樣. 這就是包的串行化.

包的串行化

在包聲明和包體內都使用 SERIALLY_REUSABLE 這個編譯指令, 這種包的包狀態(變量值, 包游標的打開狀態等)的聲明周期可以從整個會話減少到對包的一個程序調用.

例如:

1 create or replace package book_info_n 2 is 3 pragma serially_reusable; -- 注意這里 4 5 procedure fill_list; 6 7 procedure show_list; 8 end book_info_n; 9 / 10 show errors; 1 create or replace package body book_info_n 2 is 3 pragma serially_reusable; -- 注意這里 4 5 -- ... 6 end book_info_n; 7 / 8 show errors;

關于串行包要注意的內容:

  • 串行包使用的是全局內存是從SGA中分配的, 而不是從用戶的UGA中分配的, 這樣一來包的工作區就可以重用的, 每次包重用時, 包級別變量都會重新初始化成缺省值或者NULL, 包的初始化單元也會重新執行.
  • 使用串行包所需要的工作區的最大數量取決于冰法使用這個包的用戶的數量, SGA內存使用的增加被UGA或者程序內存的減少所抵消. 最后, 如果數據庫由于其他的需求需要回收SGA內存, 數據庫就會把不再使用的工作期過期處理.

個人感覺一般還是不要使用 串行包.

何時使用包

封裝數據操作.

避免直接硬編碼: 比如在包中定義一個常量, 在包外可以直接引用.

把邏輯上相關的功能組織在一起

緩存會話的靜態數據從而改善應用程序性能( 在一個session 中會始終保存 )

?

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的plsql programming 18 包的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。