oracle pl/sq技朮升級

《oracle pl/sql技術升級》就是其中的一本 全書9章 看完這本書收穫相當大,對繁體字和名稱也熟悉了很多。

其實到現在這本書還有地方我看的一頭霧水,估計有是實踐的機會慢慢我更多的瞭解的~ 把筆記整理出來 以後哪忘記了也有個地方查閱 

第一章 對資料庫(數據庫) 資料表 欄位等做了些介紹~ 都是理論

二: 資料庫的介紹

建表CERATE TABLE plsql101_test_1 (

       first)name CHAR(15),

    last_namr CHAR(20)

);

新增記錄 

 Insert INTO plsql101_rest_1 VALUES ('Jane', 'Smith');

選擇記錄

 Select * FROM plsql101_test_1;

刪除刪除

 Drop TABLE plsql101_rest_1;

資料表和欄位的命名原則:名稱最好不超過30個字   命名可以用 應為字幕  數字和底線,用英文字母開頭,不區分大小?。名稱裏面不能放空格 ,不能重名

 

oracle儲存文字資料的方式

建立一個具有CHAR(CHARACHTER文字資料類型)  欄位的資料表  n是欄位的長度Create TABLE table_name (column_name CHAR(n));

CHAR這種欄位一般會用在長度固定的資料上

VARCHAR2用在長度不固定的資料上

 

orACLE儲存數值資料的方式 

定義一個儲存數值資料的欄位可以用NUMBER

product_price NUMBER(3,3)

 

orACLE儲存日期資料的方式茱莉亞日期 

 

訂定資料表的結構

DESC table_name    DESC  指令的?出結果共包含有3?欄位  Name(顯示名稱) Null(空) Type(顯示?欄位的資料型和資料長度)

 

NULL欄位和NOT NULL欄位

NULL(表示空欄位)NOT NULL(不能為空)

 

新增有空值的記錄

Insert INTO plsql101_purchase VALUEA('Product Name 1',1,NULL);

Select * FROM plsql101_purchase;

 

如何新增含有頓號的資料

在Insert指令之前執行SET SCAN OFF的指令    將頓號用兩個單連續頓號表示 

SET SCAN OFF

Insert INTO plsql101_purchase VALUES

    ('Fifth Product''s Name',25,'05-MAY-03');

SET SCAN ON 

 

選擇特定欄位Select product_name FROM plsql101_purchase;

 

資料表做數據運算Select product_name,product_price*1.15 FROM plsql101_purchase;

 

表示式Select product_name, product_price *2 +10 FORM

 plsql101_purchase;

 

將兩個或多個文字連在一起Select product_name || salesperson FROM plsql101_purchase;

 

設置欄位別名Select product_name || 'was sold by' || salesperson "Sold By" FROM plsql101_purchase;

 

 

 

 

=================================

3 進階資料的處理

 

限制所選的資料錄

Select columns FROM table_name Where condition(s);

Condition條件式

 

過濾數值資料

依單一值來選擇資料

Select * FORM plsql101_product

Where quantity_on_hand = 1;

以上指令可以找出某一個值爲1的所有資料

 

依某個區間值來選擇資料

select * from plsql101_product

where product_prict >=  50

    and

    product_prict >=  100

;

 

select * from plsql101_product

where product_prict between 50 and 100;

 

顯示不包函的紀錄

select * from plsql101_product

where product_prict <  50

    or

    product_prict >  100

;

 

 

select * from plsql101_product

where product_prict not between 50 and 100;

 

select * from plsql101_product

where product_prict <> 99;

 

select * from plsql101_product

where product_prict != 99;

 

就是用OR來取代AND  用<>或者!=?取代=     

 

選取一組可接受的值

select * form product 

where color = 'red'

    or

    color = 'green'

    or

    color = 'white'

;

如果數量多的話 可以用in 

select * form plsql101_product

where product_price in (50, 99);

 

 

過濾文字資料

select * form plsql101_product 

where product_name = 'sankk widget';

找出某一組字串的資料一樣可以用in來做 

select * form plsql101_product

where product_name in ('samll widget', 'round chrome snaohoo');

 

使用萬用字元

select * form plsql101_product

where product_name like 'Chrome%';

%就是萬用字元 放在後面的時候表示(只要開頭爲這個文字的字符串的資料就符合搜索條件)chrome前面還有其他字

select * form plsql101_product

where product_name like '%Chrome%';

被搜索的內容區分大小?

where product_name like '%w_d%';

搜索含有D的所有資料

 

過濾日期資料

select * from plsql101_product

where last_stock_date = '15-JAN-03';

同樣也可以用 between not between

 

NULL值的處理

select * form plsql101_product

where last_stork_date is null;

檢查日期欄位爲空的資料

select * form plsql101_product

where last_stork_date is not null;

檢查日期欄位不爲空的?料 

 

更改紀錄的順序

依據某一欄位做排序

select * form table_name order by column_to_sort_by;

table_na表名 column_to_sort_by欄位名

 

依據多個欄位做排序

select last_stock_date,

    product_name,

    product_price,

    quantitu_on_hand

from    plsql101_product

order by last_stock_date,

    product_name

;

 

 

顯示唯一值

Select distinct product_name

From plsql101_purchase

order by product_name;

 

加入distinct來過濾唯一值 也可以用unique

 

依據DUAL來顯示資料 

desc dual;

select * from dual;

select 18*1.05 from dual;

 

變更資料表裏面的資料 

Update table_name set column_name = new_value where condititon;

 

Select * from plsql_purchase;

 

Update plsql101_purchase

Set     product_name = ‘large widget’

Where product_name = ‘samll widget’;

把plsql101_purchase 裏面所有名爲”small widget”的產品改成”large widget”

 

刪除資料表裏面的紀錄

Delete from table_name where condition;

指定條件來做刪除

Select * from plsql101_purchase;

 

Delete from plsql101_purchase

Where purchase_date >’15-jul-03’ ;

刪除july 15,2003之後的資料

Delete from plsql101_purchase

Where purchase_name = ‘large widget’;

產品名稱爲large widget 的資料全部刪除

 

刪除某個表裏面的所有資料

Delete from table_name;

 

資料表的解除

Truncate table tble_name;

 

Truncate table plsql101_purchase;

Select * from plsql101_purchase;

針對plsql101_purchase來做刪除動作 

 

 

交易控制 

復原DML交易

Insert ioto plsql101_purchse values

(‘small widget’, 1, ’14-jul-03’, ‘ca’);

Savepoint a;

Rollback to a;

復原使用rollback   savepoint用來做保存節點   commit會直接將異動資料進資料庫     

 

=====================

Sql *plus的控制

使用文字編輯器

Edit 可以簡寫成ED    用來開啓文本編輯器 輸入代碼   結束用 /  在按回車就可以了

 

行編輯

使用change指令

Select product_nmae from plsql101_product;

這裏的攔位名nmae寫錯  

Change/nmge/name 

然後按/再執行命令

Change可以用c來代替

 

 

在行編輯模式裏面選擇所要編輯的行

Select product_nmae

From    plsql101_produtc 

Where    quantity_on_hand >= 100

        And

        Last_stocl_date is not null

order by product_name;

 

Sql> 1

1* select    product_nmae

Sql> c/ma/am

1* select    product_name

Sql> 2

2* from plsql101_produtc 

Sql > c/tc/ct

2* from plsq;101_pruduct

Sql> / 

 

 

 

 

清楚sql *plus的畫面

在SQL*PLUS低下按住SHIFT然後再按住Delete 即可清空

 

 

 

產生比較可觀性的輸出畫面

在sql *plus 裏做數值資料的格式化

小數點對齊

Column column_name format format_code 

column_name參數是小數點對齊的欄位名稱 

format_code是要做欄位格式化的參數

 

 

select * from plsql101_product;

column product_price format 9999.99

select * from plsql101_product; 

 

product_price 欄位裏面的數字資料    末尾都多了 。00

 

 

 

加入錢號

Column product_price format $99.99

Select * from plsql101_product;

 

 

在SQL裏面做文字資料的格式化

Column column_name format ann word_wrap

裏面的nn是便是超過了多少字元之後要做換行處理(A代表字母或者數字的意思)

 

Select * from plsql101_product;

Column product_name format a10 word_wrap

Select * from plsql101_product;

 

Sql * plus每遇10個字元就會自動換行

 

 

 

在SQL*PLUS 裏做欄位擡頭的格式化

Column column_name heading ‘heading_test’ justify left

Column column_name heading ‘heading_test’ justify center

Column column_name heading ‘heading_test’ justify righr

 

 

將輸出結果存入在磁盤

 

Spool spool_file_name

 

===================================

 

在資料表之間傳送資料

使用insert傳送資料

Insert into table_name (

    Select statement

)

;

從現在的表中建立一個新表

Create table new_table_name AS select statement;

 

變更資料表名稱

Rename old_table_name to new_table_name;

 

新增欄位

Alter table table_name

Add new_column_name datatype [not null]

;

例子

Desc plsql101_log         

Alter table plsql101_log

Add data_load_date varchar2(8);

Desc plsql101_log     - -上下對比

 

 

更改欄位的類別

Alter table table_name

Modify column_name new_datatype

;

例子

Alter table plsql101_log

Modify data_load_date date;

 

改變NULL的選項

Alter table table_name

Modify column_name not null;

例子

 Alter table plsql101_log 

 Modify data_load_data not null;

 

資料集

建立資料集

Create or replace view view_name as

Select statement

;

or replace 透過這種方式我們就可以透過指令來建立一個與現有名稱相同的資料集

刪除資料集

Drop view view_name;

例子

Drop view plsql101_sales_per_person_v;

 

 

前N筆記錄得分析

Select column_name_1 [1,column_name_2….]

From table_name

Where rownum <=number_of_record_you_want

order by column_with_value_you_care_about

;

例子

Create or replace view plsql101_overstocked_items as 

Select product_name, quantity_on_hand

From plsql101_product

Where rowum <= 3

order by quantity_on_hand

;

Select * from plsql101_overstocked_items;

 

序數 

建立序數  

Create sequence sequence_name;

[increment by increment_quantity]

[start with starting_value]

[maxvalue highest_value]

[minvalue lowest_value]

[cycle]

;

Increment by 參數允許你建一個序數且每次的增加可以不時1

Start with 建立讓你建立一個初始值不爲1的序數    

maxvalue minvalue參數允許你定義序數產生的最大和最小值

 

同意字

Select * from your_user_name.your_table_name;

建立同意字

Create [public] synonym synonym_name

For object_name

;

修改既有的同意字

Srop [public] synonym synonym_name;                                                                                                                                                                                                                                                                                                                                                                        

 

PL/SQL介紹

內建程序

所謂內建程序(store procedure)是一組由pl/sql所選擇的指令集合。

Increase_price  (percent_increase number)

呼叫以上這支程序時需要將某個值傳送給它,從傳入給這個程序的值回在程序裏面以percent_increase 的變數來使用

Increase_salary_find_tax  (increase_percent in number := 7

Sal)

以上這支程序具有三個形式參數,而接在參數名稱之後的IN這個字則是表示這是一個輸入給該程序的值;而OUT這個字則表示此程序處理完後會利用這個參數將值傳回給呼叫他的元件;而參數名稱後接IN OUT的話,則表示這個可以透過參數某寫值送入這個程序

Increase_percent後面的7  會以 7%來計算。

 

 

內建函式

calc_percent(value_1 number, value_2 number)

Return number 

可以接受兩個參數,在函式裏可以透過以value_1和 value_2的變數來參考折兩格值。

例子

Insert into employ values(3000, calc_percent(300, 3000));

 

驅動程序

它會在某些由驅動程序所制定的事件發生時自動執行。

驅動程序根內建程序的差別

無法在程式裏面呼叫驅動程序,因爲驅動是由OEACLE資料庫根據某些預設事件來自動執行、驅動無法由參數列表的,驅動程序規格里面具有某些內建程序規格所沒有的資訊

 

 

 

PL/SQL程式區塊的結構

PL/SQL包含4個區塊 :鏢頭區塊,選擇性宣告區塊,執行區段以及選擇性例外區段。

匿名區塊:由於它不具有標頭或名稱區塊,所以叫匿名區塊

Set serveroutput on

declare

       num_a number := 6;

       num_b number;

       begin

       num_b := 0;

       num_a := num_a / num_b;

       num_b :=7;

       dbms_output.put_line('value of num_b' || num_b);

exception

         when zero_divide

         then

          dbms_output.put_line('trying to divide by zero');

          dbms_output.put_line('value of num_b'    ||  num_a);

          dbms_output.put_line('value of num_b'    ||  num_b);

         end;

 

 

標頭區塊

<<just_a_label>>

Declare

 

執行區段

從關鍵字begin開始 但是結束的職位則由兩種 要是區塊裏具有例外區段的話,則執行區段的結束位置會在關鍵字exception ; 

如果沒有例外區段的話用 end

 

Begin 

    一個或多個pl/sql敘述

[例外區段]

End[函式程序的名稱];

 

例外區段

Exception 列外名稱

    Then

        某個例外發生時需要採取的動作

    When 例外名稱

    Then

        某個例外發生時所要採取的動作

 

 

 

撰寫一支簡單的pl/sql程序

create procedure my_first_proc is         

       greetings varchar2(20);

begin

       greetings := 'hello world';

       dbms_output.put_line(greetings);

end my_first_proc;

 

 

 

程序和函數的呼叫

@body text indent 2 = procedure_name();

例子 

Procedure_name(formal_param1 => acual_param1,

Formal_param1 => Actual_param2

….

);

 

PL/SQL的變數和常數

Number 資料型類別的變數就存放數值資料用的 

而char或varchar2 類別是用來存文字資料的

 

 

 

 

PL/SQL的變數宣告

 

Variable_name data_type [[not null] := default_value_expression];

Variable_name data_type[[not null] default default_value_expression];

Variable_name 事 PLSQL裏面任何一個 合法識別字

 

 

 

 

 

PL/SQL的常數宣告

Variable_name data_type constant := constant_value_expression;

 

 

指定變數的值

Variable_name := expression;

 

Pl/sql的控制結構

 

IF敘述    

 

If  condition_1 then

    Action_1;

[elsif condition_2 then

Action_2;]

…..

[slse

Actions_last;]

End if;

Actions_1到actions_last均爲一個或多個PL/SQL的敘述

 

 

例子

create function compute_discountesi (order_amt number)

return number 

is

       small_order_amt number := 400;

       small_order_amt number := 1000;

       small_disct number := 1;

       small_disct number := 5;

begin

       if (order_amt < large_order_amt

           and

           order_amt >= small_order_amt)

       then

           return (order_amt * large_disct / 100);

       elsif (order_amt >= large_order_amt)

       then

           return (order_amt * large_disct / 100);

       else

           return(0);

       end if;

end compute_discountesi;

 

 

LOOP

所有敘述均會不斷重複執行,如果循環裏面利用WHEN證明離開條件表示式的條件時,每當所有敘述執行完一遍之後 程式回自動檢測條件是否爲真。如果事真的話,則所有在EXIT之後的敘述均會跳過不執行,而直接跳到END LOOP後面來執行其他的敘述。

<<loop_name>>

Loop

    Statement;

    Exit loop_name [when exit_condition_expression];

    Statements;

End loop; 

例子 

Declare

    Just_a_num number := 1;

Begin

    <<just_a_loop>> 

    Loop

             Dbms_output.put_line(just_a_num);

  exit just_a_loop

  when (just_a_num >= 10);

        just_a_num := just_a_num + 1;

        end loop;

  end; 

每執行一次就會將變數具屍體just_a_num的值增加1  加到10 離開開條件

 

 

While 循環

 

當敘述需要要反覆的執行的次數不確定時,就可以用 while 來處理    

While while_condition_expression

Loop

    Statements;

End loop;

 

 

例子:

declare

       just_a_num number  := 1;

begin

       while (just_a_num <= 10) loop

             dbms_output.put_line(just_a_num);

             just_a_num := just_a_num + 1;

       end loop;

end;

 

 

 

for循環

FIR循環會用到一個計數器變數,這種變數也稱爲循環引索[loop index],透過此一變數就可以計算循環的次數了

 

for counter in [reverse] lower) bound…upper_bound

loop

    statements;

end loop;

 

 

例子

begin 

      for just_a_num in 1..10

      loop

          dbms_output.put_line(just_a_num);

      end loop;

end;

 

 

指標

跟sql的 select敘述結合在一起使用。透過指標的話,可以將SQL敘述的 一筆一筆資料拿出來做處理

 

 

指標的宣告與指標的屬性

 

cursor cursor_name [(parameter1 [, parameter2 ...])]

[return return_specification]

is

        select_statement

              [for update

                   [of table_or_coll

                       [,table_or_col2 ...]

                   ]

              ]

     ;

指標裏面所有參數都爲IN的參數 指標傳回的規格return_specification 則是註明指標裏面的Select敘述所截取的類別資料  table_or_col可以指要變更的欄位名稱 for update的指令可以在指標開啓時將Select 敘述所選的資料鎖住。

 

 

Cursor_name%isopen      檢查指標是否開啓  傳回TURE 表明指標cursor_name已經開啓

Cursor_name%powcount   由指標的select敘述所傳回的資料筆數

Cursor_name%found      檢查指標裏面是否由下一筆資料    TURE 表示還有 

Cursor_name%notfound    與found屬性剛好相反 TURE 表示沒資料了

 

 

PL/SQL的記錄 

以資料表爲主的記錄型別 

指標爲主的記錄型別

使用者自定的記錄型別

 

 

在指標裏使用open, fetch 和close 

 

 

   Open cursor_name;

   Fetch cursor_name into record_var_or_list_of_var;

   Close cursor_name;

 

在指標內使用FOR循環 

For cursor_record in cursor_name loop

    Statements;

End loop;

透過指標專用的for循環可以反覆將指標裏面的資料取出來塞到cursor_record            

 

Where current of

當指標開啓準備提供資料更新或刪除時  使用 

Where current of cursor_name

 

 

例子

create table plsql101_product(product_name varchar2(15), product_price varchar2(20));

 select product_name, product_price

 form plsql101_product;

 

 declare

        cursor product_cur is

        select * form plsql101_product;

        for update of product_price;

 begin

        for product_rec in product_cur

        loop

            update plsql101_product

            set product_price = (product_rec.product_price * 0.97)

            where current of product_cur;

        end loop;

end;

 

 

 

巢狀循環和指標的使用範例

create or replace procedure do_commissins is

       commission_rate number := 2 ;

       total_sale      number := 0 ;

       current_person  char(3) := '';

       next_person     char(3)  ;

       quantity_sold   number := 0 ;

       item_price      number := 0 ;

       cursor sales_cur is

              select tab1.salesperson,

                     tab1.quantity,

                     tab2.product_price

              from   pllsql101_purchase tab1,

                     pllsql101_product tab2

              where  tab1.product_name = tab2.product_name

                     order by salesperson;

begin

       open sales_cur; 

       loop

           fetch sales_cur into

            next_person, quantity_sold, item_price;

       while (next_person = current_person

             and

             sales_cur%found)

       loop

           total_sale :=

                      total_sale + (quantity_sold * item_price);

           fetch sale_cur into

                      next_person, quantity_sold, tiem_price;

        end loop;

                 if (sales_cur%found)

                 then

                     if (current_person != next_person)

                     then

                         if (current_person != '')

                         then

                             dbms_output.put_line

                                    (current_person ||

                                    ' ' ||

                                    total_sale ||

                                    ' ' ||

                                    total_sale * commission_rate / 100);

                          end if;

                          total_sale := quantity_sold * item_price;

                          current_person := next_person;

                      end if;

                  else if (current_person != ' ')

                  then

                      dbms_output.put_line(current_person ||

                                  ' ' ||

                                  total_sale ||

                                  ' ' ||

                                  total_sale * commisson_rate / 100);

                       end if;

                   end if;

                   exit when sales_cur%notfound;

                   end loop;

                   close sales_cur;

          end do_commossions;

 

 

 其他重要的 pl/sql概念

 

程式的撰寫慣例

 

所有PL/SQL命令都以大寫來表示

名稱均爲小寫來表示

所有的邏輯片段均以獨立的一行來選擇。

函式和程序的規格一定要寫清除。

在逗號之後一定會接上格空格

 

 

變數型別的動態宣告 PL/SQL的記錄

根據欄位型別來宣告PL/SQL的變數語法:

Variable_name table_name.column_name%TYPE;

根據資料庫的欄位來宣告記錄語法:

Record_name table_name%ROWTYPE;

利用指標根據資料庫欄位來宣告記錄語法:

Record_name cursor_name%ROWTYPE;

 

 

 

建立一個屬於自己的記錄

TYPE record_type_name IS

(field_1_name field_1_type,

 Field_2_name field_2_type,

);

 

結構寫好之後,記錄的實際宣告 語法是

Record_variable_type_name;

 

 

 

- - performatnce事指每一位業務員所接到的 平均訂單金額  status事指錯誤狀態

 

 

set serveroutput on

declare

       cype performance_type is record     - - 宣告一個名爲performance_type的記錄類別

            (person_code     plsql101_person.person_code%TYPE,    

             person_name     plsql101_person.list_name%TYPE, - -用到TYPE所有欄位就可以對照plsql101_person

             current_sales   number(8,2),

             perform_percent number(8,1),

             status          varchar2(30)

                         );

       one_perform performance_type;   - - 又宣告了one_perform的記錄變數

 

       CURSOR person_cur IS         - -然後接了一個指標 可以通過指標將plsql101_person;所有資料截取出來

              Select *

              FORM plsql101_person;

 

- - 可以算出每一位業務員的平均訂單金額及總業績              

 

procedure current_performance  - -包含了兩格參數 1一筆人事資料記錄和plsql101_person;的欄位一樣,由person_cur將資料截取出來

          (a_person plsql101_person%ROWTYPE,

           a_perform OUT performance_type)  - -輸出的結果均會由程序寫入到這個函數裏面 自動將程序的執行結果填入a_perform

IS

           cursor history_cur (person varchar2) is   - -一次只做一個截取動作  用了一個欄位 avg_order

                  select      avg(tab2.product_price *  tab1.quantity)

avg_order

          from    plsql101_purchase_archive tab1,

                  plsql101_product          tab2

          where   tab1.product_name = tab2.product_name

          group by tab1.salasperson

          having   tab1.salesperson = person;

 

     hist_rec history_cur%rowtype;

     current_avg_sale number(8,2) := 0;

 

begin

     a_perform.person_code := a_person.person_code;  

     a_perform.person_name := a_person.last_name;

     a_perform.status := null;

 

     begin 

          select sum(tbl2.product_price * tbll.quantity),

                 avg(tbl2.product_price * tbll.quantity)

          into   a_perform.current_sales,

                 current_avg_sales

          from   plsql101_purchase tbl1,

                 plsql101_product  tb12

          where  tbl1.product_name = tbl2.product_name

          group by tab1.salesperson

          having tab1.salesperson = a_person.person_code;

     exception

          when no_data_found 

          then

              a_perform.status := 'current purchases exception';

              a_perform.current_sales := 0;

      end;

 

 

      open history_cur (a_person.person_code);

      fetch history_cur into hist_rec;

      if (history_cur%notfound)

      then

          a_perform.perform_percent := 0;

          if (a_perform.status is null)

          then

              a_performl.status := 'erroneous or no history';

          end if;

       else

          a_perform.perform_percent := 

                    100 * (current_avg_sales-hist_rec.avg_order) / hist_rec.avg_order;

          a_perform.status := 'all fine';

 

      end if; 

      close history_cur;

exception

      when no_data_found

      then

          a_perform.status := 'exception found';

end current_performance;

 

begin

     for person_rec in person_cur

loop

     current_performance(person_rec, one_perform);

 

     dbms_output.put_line(one_perform.person_code ||

                         ' ' ||

                         one_perform.person_name ||

                         ' ' ||

                         one_perform.current_sales ||

                         ' ' ||

                         one_perform.perform_percent ||

                         ' ' ||

                         one_perform.status);

      end loop

end;

/

select * from plsql101_person;

select * from plsql101_perchase;

select * from plsql101_purchase_archive;

select * from plsql101_product;                                          

 

 

 

 

發佈了12 篇原創文章 · 獲贊 1 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章