天天看點

PL/SQL變量與類型

變量的作用域:   變量可以使用的程式單元部分

可見性: 當一個變量在它的作用域中可以用一個不限定的名字來引用時

1.CONSTANT  聲明一個常量

2.NOT NULL 限制變量不能為空

3.:=value 用于為變量附初始值

例如

v_name DATE NOT NULL := SYSDATE

v_name INT  NOT NULL DEFAULT 7369

變量在沒有被初始化的時候 變量會被初始化成null值  即使+1   依然還是null值 

%TYPE

例子  用于定義相同類型的變量   用于綁定單個列的值

     v_empno emp.empno%TYPE

%ROETYPE

      用于綁定一整行的 所有列

     v_emp emp%ROWTYPE

%TYPE 和 %ROWTYPE  隻提供類型資訊  并不能保證NOT NULL 限制

本地變量:在PLSQL塊或子程式中定義的變量僅在本地可用,如果在塊之外通路變量是非法的,這種變量稱為本地變量 當超出其作用域時,變量使用的記憶體将會被釋放,直到變量被重新定義并初始化

外部塊中定義的變量對于子塊來說是全局的,如果全局變量在子塊中又被重新聲明,那麼全局變量和本地聲明的變量在子塊的作用域是存在的,要通路外部塊的全局變量,需要使用限定修飾符。

當外部塊和内部快都同時聲明同一變量  優先通路本地的

12-8-5                

<<outer>>                     

declare

v_empname varchar2(20);

begin

v_empname:='張三';

<<inner>>

v_empname:='李四';

dbms_output.put_line('内層塊的員工名稱:' || v_empname );

dbms_output.put_line('外層塊的員工名稱:' || outer.v_empname);

end;

dbms_output.put_line('outer員工名稱:' || v_empname);

12-9-1 

資料類型

PLSQL 是一種靜态類型化的程式設計語言,靜态類型化又稱為強類型化,也就是說類型會在編譯時被檢查,而不是在運作時,增強程式的穩定性

标量類型:用來儲存單個值的資料類型,包含字元型,數字型,布爾型和日期型

複合類型:記錄 嵌套表 索引表和變長數組

引用類型:REF CURSOR 和REF 2種

LOB類型:用來處理二進制和大于4GB的字元串

每個oracle資料庫表都有一個名為ROWID的僞列。

SQL> select rowidtochar(rowid),ename,empno from emp;

ROWIDTOCHAR(ROWID) ENAME           EMPNO

------------------ ---------- ----------

AAAQ+jAAEAAAAAeAAA SMITH            7369

AAAQ+jAAEAAAAAeAAB ALLEN            7499

AAAQ+jAAEAAAAAeAAC WARD             7521

AAAQ+jAAEAAAAAeAAD JONES            7566

AAAQ+jAAEAAAAAeAAE MARTIN           7654

AAAQ+jAAEAAAAAeAAF BLAKE            7698

ROWID:實體ROWID和邏輯ROWID

  實體:辨別普通資料表中的一行資訊   邏輯:能夠辨別索引組織表中的一行資訊

UROWID 可以存儲 實體  邏輯  以及非 oracle 的ROWID  

ROWID 可以顯著的加速資料檢索的性能。隻要行存在 實體ROWID 值就不會改變。

v_empname ROWID;

v_othersname VARCHAR(18);

select ROWID into v_empname from emp where empno=&empno;

dbms_output.put_line(v_empname);

v_othersname:=ROWIDTOCHAR(v_empname);

dbms_output.put_line(v_othersname);

數字類型 NUMBER:精度:所允許的的總長度 刻度:小數點右邊多少位 如果為負值 及小數點左邊多少位

指定刻度超過 四舍五入

v_num NUMBER(4,-1):=31451      41450

v_num NUMBER(4.3):= 3.1415926  3.142

用來存儲符号整型值 PLS_INTEGER   BINARY_INTEGER

PLS_INTEGER 相對于NUMBER 來說需要更少的記憶體 來存儲資料而且在計算方面比NUMBER更有效率

NUMBER資料類型是以十進制格式進行存儲的 為了進行數學運算 需要轉換成二進制 是以速度會慢。

PLS_INTEGER 和 BINARY_INTEGER  都是以2的補碼格式進行計算的  PLS_INTEGER 在溢出時會觸發異常報錯   而 BINARY_INTEGER 會轉換成NUMBER  不會報錯。

SQL> select sessiontimezone from dual;

SESSIONTIMEZONE

---------------------------------------

+08:00

獲得目前時區

12-9-2

INTERVAL 類型 

INTERVAL YEAR TO MONTH  用來存儲和操縱年和月之間的時間間隔

INTERVAL DAY TO SECOND  用來存儲和操縱天數,小時,分鐘和秒之間的時間間隔。

v_start timestamp;

v_end timestamp;

v_interval interval year to month;

v_year number;

v_month number;

v_start := TO_TIMESTAMP('2010-05-12','YYYY-MM-dd');

v_end := CURRENT_TIMESTAMP;

v_interval := (v_end - v_start) YEAR TO MONTH;

v_year := EXTRACT(YEAR FROM v_interval);

v_month := EXTRACT(MONTH FROM v_interval);

dbms_output.put_line('目前的interval值為:' || v_interval);

dbms_output.put_line('INTERVAL年份為:' || v_year || CHR(13)||CHR(10)|| 'INTERVAL月份為:'|| v_month );

v_interval := INTERVAL '01-03' YEAR TO MONTH;

dbms_output.put_line('目前INTERVAL值為:' || v_interval);

v_interval := INTERVAL '01' YEAR;

dbms_output.put_line('目前的INTERVAL值為:' || v_interval);

dbms_output.put_line('INTERVAL年份為' || v_year || CHR(13)|| CHR(10)||'INTERVAL月份為:'|| v_month );

v_interval := INTERVAL '03' MONTH;

dbms_output.put_line('目前的INTERVAL的值為:' || v_interval);

結果:

目前的interval值為:+04-07

INTERVAL年份為:4

INTERVAL月份為:7

目前INTERVAL值為:+01-03

目前的INTERVAL值為:+01-00

INTERVAL年份為1

INTERVAL月份為:0

目前的INTERVAL的值為:+00-03

引用類型

1.REF CURSOR 類型的變量通常稱為遊标變量

create or replace function selectallemployments

return sys_refcursor

as

st_cursor sys_refcursor;

open st_cursor for select * from emp;

return st_cursor;

x sys_refcursor;

v_emp emp%ROWTYPE;

x := selectallemployments;

loop

fetch x

into v_emp;

exit when x%NOTFOUND;

dbms_output.put_line('員工編号:' || v_emp.empno || '員工名稱:' || v_emp.ename);

end loop;

使用者自定義類型

引用遊标使用示例

subtype empcounttype is integer;

empcount empcounttype;

select count(*) into empcount from emp;

dbms_output.put_line('員勞工數為:' ||  empcount);

使用%TYPE

TYPE empnamelist is table of varchar2(20);

subtype namelist is empnamelist;

type emprec is record(

empno number(4),

ename varchar2(20)

);

subtype emprecord is emprec;

subtype empno is emp.empno%TYPE;

subtype emprow is emp%ROWTYPE;

null;

子類型具有的優勢:

1.可以檢查數值是否越界,這樣可以提高應用程式的可靠性。例如如果想要讓某個數字類型在0~9這個範圍之間,可以基于NUMBER類型定義一個子類型,這樣在指派時,如果資料溢出,編譯器會彈出錯誤提示

subtype numtype is number(1,0);

x_value numtype;

y_value numtype;

x_value := 3;

y_value := 10;              因為10 報錯  精度太高

2.未限制的子類型可以和它的基本類型互動使用

subtype numtype is number;

x_value number;

x_value:= 10;

y_value := x_value;

3.如果基類相同 那麼子類型可以互動使用

subtype numtype is varchar2(200);

x_value varchar2(20);

x_value:='This is a word';

y_value:=x_value;

12-10  資料類型轉換  

顯示轉換

v_startdate DATE;

v_enddate DATE;

v_resultdate NUMBER;

v_startdate:=TO_DATE('2007-10-11','yyyy-MM-dd');

v_enddate:=TRUNC(SYSDATE);

v_resultdate:=v_enddate-v_startdate;

dbms_output.put_line('起始日期:' 

|| TO_CHAR(v_startdate,'yyyy-MM-dd') 

|| CHR(13)

||CHR(10)

||'結束日期:'

||TO_CHAR(v_enddate,'yyyy-MM-dd')

||CHR(13)

||'相差天數:'

||TO_CHAR(v_resultdate));

隐示轉換

v_startdate char(10);

v_enddate char(10);

v_result NUMBER(5);

select min(hiredate) into v_startdate from emp;

select trunc(sysdate) into v_enddate from dual;

dbms_output.put_line('起始日期:'

|| v_startdate

|| CHR(10)

|| '結束日期:'

|| v_enddate );

v_startdate:='200';

v_enddate:='400';

v_result:=v_enddate-v_startdate;

表達式

v_sal NUMBER;

v_result NUMBER;

select sal into v_sal from emp where empno=&empno;

v_result:=v_sal * (1+0.15);

運算符類型

指派運算符,連接配接運算符,邏輯運算符,比較運算符。

PLSQL中一個左值僅能有一個右值  val1:=val2:=val3:=val4=0  這樣是錯誤的

連接配接運算符

x varchar2(8):='你好';

y varchar2(8):='中國';

z varchar2(10);

dbms_output.put_line(x || z || NULL || y);

執行結果   因為z沒有指派 是以是一個null   連接配接一個null   2個就都不顯示

SQL> declare

  2     x varchar2(8):='你好';

  3     y varchar2(8):='中國';

  4     z varchar2(10);

  5  begin

  6     dbms_output.put_line(x || z || NULL || y);

  7  end;

  8  /

你好中國

PL/SQL 過程已成功完成。

      本文轉自潘闊 51CTO部落格,原文連結:,http://blog.51cto.com/pankuo/1630245如需轉載請自行聯系原作者