前言: 使用變數可以儲存電腦需要處理的資料,為了給該變數分配適當的記憶體空間,還需要指定資料類型,有的資料類型還需要指定長度,如字串。 有些類型可以用於建表(如char),有些則不能(如boolean,rowtype)。 同樣是字串,建表時的限制為4000,在指令碼中則為3萬多。 簡單文法:變數名 資料類型; 完整文法:變數名 [constant] 變數類型 [not null] [default 值 | :=值] 其中“[ ]”表示可以不寫,“|”表示任選其一。 下面給出變數定義及解釋,資料類型先用建表時所用的資料類型: v1 char: 說明:沒有給出長度,所以v1隻能儲存一個字元。超過了則會出錯:數字或值錯誤 : 字串緩衝區太小。 v2 varchar2(10); 說明:v2最多隻能儲存10個字元。如果不寫長度,會出錯:字串長度限制在範圍(1...32767) v3 number; 說明:v3儲存的數字範圍非常大,幾乎可以認為是沒有限制的。 v4 number(5); 說明:v4最多能夠儲存5位整數。如果有小數,Oracle會自動四捨五入。如果整數部分超過5位,則會報錯:數字或值錯誤 : 數值精度太高。 v5 number(5,2); 說明:v5最多能夠儲存3位整數,2位小數。如果小數位不止2位,則Oracle會自動四捨五入。整數位超過3位會報錯,同上。 v6 date; 說明:可以直接儲存sysdate的值;如果是指定日期,則要用to_date來轉化。否則報錯:文字與格式字串不匹配。 定義了變數,變數的預設值為空白,此時進行計算,結果一定為NULL。所以變數必須初始化。 初始化有三種方式: v7 constant number := 100; 說明:定義v7為常量,定義時就必須給定值。然後在程式中就不能再對v7進行賦值了,否則會報錯:運算式 'V7' 不能用作賦值目標。 v8 number default 10; 說明:定義v8時就給定預設值10。注意,number類型變數的預設值不是0,而是NULL。 v9 number not null := 1000.50; 說明:定義v9變數不可為空,此時必須給出一個不為NULL的值。在運行時發現v9為NULL,則報錯:說明為 NOT NULL 的變數必須有初始化賦值。 預測各列印結果,如果代碼有錯誤請先改正: declare v1 char; v2 varchar2(10); v3 number; v4 number(5); v5 number(5,2); v6 date; v7 number default 10; begin v1:='ab'; v2:='abcd'; v4:=9998.99; v5:=1000.5555555; v6:=to_date('2002-10-2','yyyy-mm-dd'); dbms_output.put_line(v1); dbms_output.put_line(v2); dbms_output.put_line(v3+100); dbms_output.put_line(v4); dbms_output.put_line(v5); dbms_output.put_line(v6); dbms_output.put_line(v7+100); end; 只能在指令碼中使用的變數類型: 上面的資料類型,同時在建表時也能使用。而下面的資料類型只能在PL/SQL指令碼中使用。 即:boolean,type,rowtype,record,替代變數、table類型。 其中: ·一個變數只能儲存一個值,叫做“標量變數”。如:char、type。 ·一個變數只能儲存多個值,叫做“複合變數”。如:rowtype、record,table。 1、布爾類型 boolean boolean類型主要表達真或假。可以為boolean類型變數賦值true或false。 主要用於PL/SQL指令碼的流程式控制制。 樣本: declare v1 boolean; begin v1:=1>2; dbms_output.put_line(v1); end; 問題:列印的結果是什麼,是true、false、1、0? 回答: 都不對。運行時得到錯誤資訊:調用 'PUT_LINE' 時參數個數或類型錯誤。 這是因為在指令碼中不能直接列印boolean類型的值,所以只能在指令碼中使用if語句來判斷。 修改樣本: declare v1 boolean; begin v1:=1>2; if(v1)then dbms_output.put_line('真'); else dbms_output.put_line('假'); end if; end; 列印: 假 2、type類型。 文法:表.欄位%TYPE 返回:某個表的欄位的實際類型。 作用: PL/SQL指令碼中,有時定義的變數就是存取表中資料的。此時資料類型及長度就需要與欄位的定義一致。可以去查看該欄位的具體類型,但這樣做很麻煩;並且當欄位定義改變時,指令碼也需要修改。 所以使用type類型來引用該欄位的類型,更方便,維護性更好。 樣本:根據工號查詢員工姓名。 分析:要從emp表中擷取姓名,必須要用查詢語句。而要從查詢語句中擷取返回的值,要加上“into 變數”。 declare v_empno emp.empno%type; v_ename emp.ename%type; begin v_empno:=7900; select ename into v_ename from emp where empno=7900; dbms_output.put_line(v_ename); end; 3、rowtype類型 文法: 表%rowtype 作用: 儲存了某一行記錄的所有欄位的值。 樣本:根據工號為7900的員工的以下資訊:ename,job,sal,comm,hiredate。 第一種:如果用type類型,定義5個變數儲存查詢結果。代碼略。 第二種:如果用rowtype類型,只需要定義一個rowtype類型的變數。 代碼: declare v_empno emp.empno%type; v_row emp%rowtype; begin v_empno:=7900; select * into v_row from emp where empno=7900; dbms_output.put_line('ename='||v_row.ename); dbms_output.put_line('job='||v_row.job); dbms_output.put_line('sal='||v_row.sal); dbms_output.put_line('comm='||v_row.comm); dbms_output.put_line('hiredate='||v_row.hiredate); end; 列印: ename=JAMES job=CLERK sal=950 comm= hiredate=03-12月-81 說明 ·必須select *,或者根據表結構的順序寫出所有欄位名。 ·使用rowtype類型最主要的限制在於表中不能有大對象欄位如:CLOB、BLOB。 4、record類型 record的意思是“記錄”。 有時,用type類型會定義太多的變數,用rowtype又會取到自己不關心的資料。 如何只取自己關心的欄位的值呢?此時就用record類型來自訂有多少個列。 文法: type 類型名 is record( 屬性名稱1 屬性類型, 屬性名稱2 屬性類型 ); 注意 1、屬性之間定義用的是逗號(,),不是分號(;)。 2、最後一個屬性名稱不需要再用“,”。 使用步驟有兩個: 1、先用type自訂一個新的類型,這個類型的變數能夠的變數與定義有關。 2、再用這個新的類型來定義一個變數,這個變數才能儲存實際的資料。 樣本:需求同上。 declare --自訂一個類型 type myType is record( xm emp.ename%type, --姓名 gzuo emp.job%type, --工作 gzi emp.sal%type --工資 ); --使用自訂類型來定義變數 myValue myType; begin select ename,job,sal into myValue from emp where empno=7844; dbms_output.put_line('ename='||myValue.xm); dbms_output.put_line('job='||myValue.gzuo); dbms_output.put_line('sal='||myValue.gzi); end; 說明: · 在查詢時必須與自訂類型的屬性順序一一對應。 ·myValue中的屬性名稱也是自訂的,不是欄位名。 問題:上面的代碼比直接用type類型還多些,看不出優勢在什麼地方。為什麼還要用record? 回答: 在項目中,自訂類型通常會放到在包(package,後面會專門學習)中,這樣就可以在其它地方直接引用了。 樣本: 先在包中自訂類型: create or replace package my_bao as type myType is record( xm emp.ename%type, --姓名 gzuo emp.job%type, --工作 gzi emp.sal%type --工資 ); end; 然後就可以在塊中直接使用該類型,只不過在類型前要加上包名:“my_bao”。 declare --使用包中自訂類型來定義變數 myValue my_bao.myType; begin select ename,job,sal into myValue from emp where empno=7844; dbms_output.put_line('ename='||myValue.xm); dbms_output.put_line('job='||myValue.gzuo); dbms_output.put_line('sal='||myValue.gzi); end; 原文地址:http://hi.baidu.com/xydba/blog/item/7c136ec69565c145b319a8f5.html |