1. 程式人生 > >plsql實例精講部分筆記

plsql實例精講部分筆記

into next 命名 bsp ear sop 四舍五入 末尾 定義類

轉換sql:  

create or replace view v_sale(year,month1,month2,month3,month4,month5,month6,month7,month8,month9,month10,month11,month12)

  as

  select

  substrb(month,1,4),

  sum(decode(substrb(month,5,2),‘01‘,sell,0)),

  sum(decode(substrb(month,5,2),‘02‘,sell,0)),

  sum(decode(substrb(month,5,2),‘03‘,sell,0)),

  sum(decode(substrb(month,5,2),‘04‘,sell,0)),

DECLARE

STATEMENTS

BEGIN

STATEMENTS

EXCEPTION

STATEMENTS

END;

可執行部分必須存在

DECLARE

v_first_name VARCHAR2(35);

v_last_name VARCHAR2(35);

c_count CONSTANT NUMBER := 0;

BEGIN

SELECT first_name, last_name

INTO v_first_name, v_last_name

FROM student

WHERE student_id=123;

DBMS_OUTPUT.PUT_LINE(‘student_name: ‘ || v_first_name || ‘ ‘ || v_last_name);

EXCEPTION

WHEN NO_DATA_FOUND THEN

DBMS_OUTPUT.PUT_LINE(‘There is no student with‘ || ‘ student id 123‘);

END;

PLSQL減少訪問數據庫的網絡傳輸

命名語句塊存儲在數據庫中,以後可以應用

DECLARE

v_name VARCHAR2(50);

v_total NUMBER;

BEGIN

SELECT i.first_name || ‘ ‘ || i.last_name, COUNT(*)

INTO v_name, v_toal

FROM instructor i, section s

WHERE i.instructor_id = s.instructor_id

AND i.instructor_id = 123

GROUP BY i.first_name || ‘ ‘ || i.last_name;

EXCEPTION

WHEN NO_DATA_FOUND THEN

DBMS_OUTPUT.put_line(‘There is no such instructor‘);

END;

編譯過程: 語法檢查, 綁定(變量分配存儲地址), 生成偽代碼

. plsql結尾(可選) /執行plsql

set serveroutput on;顯示輸出結果

& 或者 && 替代變量前綴

使用替代變量獲取輸入值

替代變量沒有分配內存,不能用作輸出

& 每次出現替代變量都要重新輸入參數

set verify off; 不顯示具體替換工程

出現多次 && 只需輸入一次參數值 加上 ‘’

set define character 修改&為其他字符

set define on 重新修改為&

set serveroutput on size 5000; 修改默認緩存大小為5000字節

7一些函數類型

聲明變量如果沒有賦值 則為null,dbms_output輸出時內容為空

|| 不要用空格

coalesce(sum(data) , null,0) 返回第一個不是null的值

nvl(sum(data),0) oracle ifnull(sum(data),0) mysql

decode(sign(salary-8000),1,salary*1.15,-1,salary*1.2,salary) sign(data) 返回-1 1 0

to_char(34.56,’fm999.00’) 34.56

to_char(0.123,’fm999.00’) .12

9沒有數字顯示空格,0沒有數字顯示0 。fm去掉如果是9顯示的空格。

to_char(0.123,’fm990.00’)

TO_NUMBER(REGEXP_REPLACE(status,‘[^0-9]‘,‘‘)) > 30

status中非數字轉換為空字符 在用to_number函數

select to_number(’RMB234234.4350′,’L999999.0000′) from dual;

select username,decode(lock_date,null,‘unlocked‘,‘locked‘) status from t;

anchroed數據類型

declare

v_name sys_user.usr_name%type;

字節 字符

varchar2(n) 與字節數有關,a 1b 我2b varchar2(n char) 與字符數有關 a 1一個字符 哦 1個字符 每個字符占2個字節

nvarchar(n) 與字符數有關 可以容納n個字符 每個字符2個字節

varchar2(n) number(m,n) 四舍五入

date timestamp binary_integer 用於索引plsql表 boolean一般用char(1)

oracle 沒有Boolean plsql有Boolean 輸出不能直接用Boolean類型值

函數:trunc(sysdate, ‘hh24’) 2013-01-06 17:00:00 trunc(124.235,2) 124.23

to_char(sysdate, ‘hh24’) 17 sysdate+numtodsinterval(30,’minute’)

substr instr trunk to_date to_timestamp

date相減是天數(帶小數) timestamp相減是時間格式

timestamp精確到毫秒

trunc不支持timestamp

聲明exception變量 e_show_exception_scope exception; raise exception拋出異常

when e_show_exception_show then ….

《inner_block》《outer_block》

v_bool Boolean; null true false

if v_bool is null then… end;

v_bool := nvl(v_bool , false);

if(v_bool) then dbms_output.put_line(‘false’);

sequence.currval nextval

dml

select into

commit rollback savepoint xx rollback to savepoint xxx

trim ltrim rtrim

8條件語句

if then else end if

if then elseif then else end if

case 搜索case 表達式case 3種形式

case xxx類型 與when xx返回類型一樣

case xxx when xx then xx; when xxx then xx ; else xx; end case;

搜索case when返回Boolean類型值

case when xxx then xx ; else xx; end case;

表達式case

賦值:=case end

select case。。。end into

表達式case 直接end,不是end case 表達式case中沒有 符號 ;

嵌套case

v_date date:=to_date(&sv_date,‘yyyy-mon-dd‘);
to_char(v_date,‘d‘) 數字形式星期 1234567 日一二三四五六七

nullif(exp1,exp2) exp1=exp2返回null,否則返回exp1
exp1不能賦值字面值null

coalesce(exp1,exp2,exp3,…) 返回第一個不是null的值

9循環

loop … end loop

if xx then exit end if

exit when condition

while condition loop

statements

end loop

null不能與任何變量進行比較 false

循環計數器經常使用 binary_integer

for v_counter in 1..5 loop statements end loop

for中v_counter被隱含定義和 遞增,for外面不能引用v_counter

for v_counter in reverse 1..5 loop exit when .. end loop

reverse逆序

if then continue end if;

continue when

10異常

exception when then

no_data_found to_many_rows zero_divide login_denied program_error

value_error invalid_number dup_value_on_index

others

when others then …..

聲明部分的異常無法處理,除非外面還有語句塊包圍處理,

重新拋出 when exception then raise

raise_application_error(-20001,’zip code is not valid’);

11遊標

創建遊標 打開遊標 檢索遊標 關閉遊標

記錄類型

遊標屬性: %notfound %found %isopen %rowcount

sql%rowcount 隱藏遊標可以用 沒有數據拋異常 不用sql%rowcount=0判斷

12.高級遊標

或者open 時帶參數

會加鎖

13.觸發器

for each row 之能增刪改操作

刪除一個表,表上的觸發器也會刪除

使用:

一些復雜業務規則;統計值;自動生成衍生列的值;防止無效事務

事務回滾或者提交,觸發器執行的操作也會提交或者回滾。 自治事務例外

自治事務都會提交 autononous transaction commit

:new :old

如果某行沒有update,:new是null,所以用nvl(new.zip,’’)

操作view,底層數據庫表也會修改

刪除時如果存在約束,需要先刪除外鍵表中記錄

instead of 觸發器比較復雜,要考慮不同表之間的關系,以及特定關系可能引起的負面影響

視圖中插入數據時,外鍵zip在zipcode表中不存在對應記錄,則先在zipcode表中插入對應記錄

14.復合觸發器

變異表問題:

select into 操作的表section正在被修改,是變異的,改用如下方式:

復合觸發器:

drop trigger sss

drop package xxx

GRANT EXECUTE ON verify_function_11G TO PUBLIC;

before each row 才能用 :new

作業1:

create or replace trigger instructor_compound

for insert or update on instructor

compound trigger

v_day varchar2(10);

v_hour varchar2(5);

before statement is

begin

v_day := rtrim(to_char(sysdate,‘day‘));

v_hour := to_char(sysdate,‘hh24‘);

if v_day like (‘s%‘) then

raise_application_error(-20001,‘this table can not be

modified on off day‘);

elseif v_hour <9 or v_hour >17 then

raise_application_error(-20001,‘this table can not be

modified on off day‘);

end if;

end before statement;

before each row is

begin

:new.instructor_id := seq_instructor_id.nextval;

if inserting then

:new.created_by := user;

:new.created_date := sysdate;

elseif updating then

:new.created_by := :old.created_by;

:new.created_date := :old.created_date;

end if;

:new.modified_by := user;

:new.modified_date := sysdate;

end before each row;

end instructor_compound;

作業2:

create or replace trigger zipcode_compound

for insert or update on zipcode

v_type varchar2(10);

v_count number;

v_table varchar2(20);

before each row is

begin

:new.modified_by := user;

:new.modified_date := sysdate;

end before each row;

after statement is

if inserting then

v_type := ‘insert‘;

else updating then

v_type := ‘update‘;

end if;

v_count := sql%rowcount;

v_table := ‘zipcode‘;

update zipcode

set transaction_user=user,

transaction_date=sysdate,

transaction_rowcount=v_count

where table_name = v_table

and trancaction_name=v_type;

if sql%notfound then

insert into transaction

values(v_table,v_type,user,sysdate,v_count);

end if;

end after statement;

end zipcodecompound;

15章:集合

1.pl/sql表

聯合數組和嵌套表類似數據庫單列表,通過下標訪問,具有相同結構。

差別:嵌套表可以存儲在數據庫列中,聯合數組不可以。

聯合數組:

嵌套表:

要初始化,否則報異常 構造方法()

長度要擴展 extend

delete(10) delete(1,3) prior(3) next(3) trim(2)

count last first extend trim

declare

type index_by_type is table of number

index by binary_integer;

index_by_table index_by_type;

type nested_type is table of number;

nested_table nested_type :=

nested_type(1,2,3,4,5,6,7,8,9,10);

begin

for i in 1..10 loop

index_by_table(i) := i;

end loop;

if index_by_table.exists(3) then

dbms_output.put_line(‘index_by_table(3)=‘||

index_by_table(3));

end if;

--delete 10th element from a collection

nested_table.delete(10);

--delete elements 1 through 3 from a colleciton

nested_table.delete(1,3);

index_by_table.delete(10);

dbms_output.put_line(‘nested_table.count=‘||nested_table.count);

dbms_output.put_line(‘nested_table.first=‘||nested_table.first);

dbms_output.put_line(‘nested_table.last=‘||nested_table.last);

dbms_output.put_line(‘nested_table.prior(2)=‘||nested_table.prior(2));

dbms_output.put_line(‘nested_table.next(2)=‘||nested_table.next(2));

dbms_output.put_line(‘index_by_table.count=‘||index_by_table.count);

dbms_output.put_line(‘index_by_table.first=‘||index_by_table.first);

dbms_output.put_line(‘index_by_table.last=‘||index_by_table.last);

dbms_output.put_line(‘index_by_table.prior(2)=‘||index_by_table.prior(2));

dbms_output.put_line(‘index_by_table.next(2)=‘||index_by_table.next(2));

nested_table.trim(2);

dbms_output.put_line(‘nested_table.count=‘||nested_table.count);

nested_table.trim();

dbms_output.put_line(‘nested_table.count=‘||nested_table.count);

end;

當從中間刪除元素時,delete保留刪除元素的索引,則 count和last值就會不同。

last會比count值大

trim長度會改變,重新賦值需要 exntend

變長數組:

變長數組擴展不能超過最大尺寸,否則報錯。

extend(2,4) 末尾追加第四個元素的2個副本

limit限制長度

varray 變長數組不能delete

chr(10)換行

多層數組:

16記錄類型

type xxx is record (name type,…)

%rowtype

not null需要初始化,否則報錯

如果都是用戶自定義類型record ,如果類型名不同不可以相互賦值, 表記錄或者遊標自定義類型之間可以相互賦值。

如果輸入內容較多,修改大小

17章 本地動態sql

例子:

18章 批量sql

2.indices of 可以處理稀疏的集合,嵌套表或者聯合數組。

3 values of 集合中元素做索引

創建一個有字段的空表

cursor要一行行檢索

select buck collect into 會批量檢索 直接講結果存保存在了集合中

1.select bulk collect into填充嵌套表時,會自動初始化和擴展。

2.bulk collect into select不返回任何數據時,不拋出no_data_found異常,所以要自己檢查返回的集合是否有數據。

3.bulk collect 不會限制集合的尺寸,並自動擴展,所以當select返回大量數據時,最好限制結合寄過集。 通過使用帶有遊標select的bulk collect,以及添加limit.

帶有limit的bulk collect子句,一次性從student檢索50行數據。每個集合最多50條記錄。

合並forall select bulk collect into

plsql實例精講部分筆記