《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;