kxbin
          成功留給有準備的人
          posts - 10,  comments - 35,  trackbacks - 0

          使用變量可以保存計算機需要處理的數據,為了給該變量分配適當的內存空間,還需要指定數據類型,有的數據類型還需要指定長度,如字符串。
          有些類型可以用于建表(如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;

          5、替代變量
          語法: &替換內容
          作用:提供用戶輸入的界面,在用戶輸入數據以后,先替換PL/SQL腳本,再編譯執行。

          案例一:輸入年齡,然后打印出來
          SQL> declare
          2   v_age number(3);
          3 begin
          4    v_age:=&年齡;
          5    dbms_output.put_line('您的年齡是 = '||v_age);
          6 end;
          7 /
          輸入 年齡 的值: 20
          原值    4:   v_age:=&年齡;
          新值    4:   v_age:=20;

          說明:在用戶輸入“20”以后,將“&年齡”替換為了“20”。于是腳本的源代碼發生了改變:
          declare
          v_age number(3);
          begin
          v_age:=20;
          dbms_output.put_line('您的年齡是 = '||v_age);
          end;

          所以“&”變量并不是一個真正的變量,它不能保存任何內容,只是提供一個字符串替換的功能。


          案例二:用戶輸入姓名并打印。
          declare
          v_age varchar2(3);
          begin
          v_age:=&姓名;
          dbms_output.put_line('您的姓名是 = '||v_age);
          end;
          問題:如果用戶輸入“a”,程序是否能夠運行,如果能,打印的結果是什么?
          分析:當用戶輸入“a”,上面代碼就是:
          declare
          v_age varchar2(3);
          begin
          v_age:=a;
          dbms_output.put_line('您的姓名是 = '||v_age);
          end;
          由于“a”前后沒有單引號,所以會被當作“標識符”即當作變量名。
          但是a這個變量又沒有定義。所以一定會提示如下的錯誤:
          必須說明標識符 'A'

          解決的方法就是:在“&”前后加上單引號,即:
          declare
          v_age varchar2(3);
          begin
          v_age:='&姓名';
          dbms_output.put_line('您的姓名是 = '||v_age);
          end;
          /

          替代變量小結:
          ·替代變量的作用主要是為匿名塊提供一個數據錄入的界面。
          ·替代變量只是完成字符串替換的功能,不能保存值。
          ·如果替代變量是字符串,則必須加上單引號。

          說明:如果是命名塊,則通過名稱和參數進行調用,此時不會再用替代變量。

          6、table類型
          table類型叫做“表類型”,又叫“索引表類型”。
          注意:都是指PL/SQL腳本中的table類型,而不是數據庫的對象。

          在學習table類型之前,先看一個任務。

          需求:用戶輸入10,打印男;輸入20,打印女。
          方法一:用分支語句(if……等)判斷。
          方法二:請思考,能不能不用判斷語句。這個任務同樣適用于java學習者。

          方法一:
          declare
          v_sex_code number(2);
          v_sex_name char(2);
          begin
          v_sex_code:=&性別編號;
          if(v_sex_code=10)then
               v_sex_name:='男';
          else
              v_sex_name:='女';
          end if;
          dbms_output.put_line('您的性別是 = '||v_sex_name);
          end;

          用戶輸入:10
          打印: 男


          方法二:使用table類型。
          語法:type 類型名 is table of 值類型 index by 索引類型。

          說明:
          ·作用:定義了一個表格結構,這個表格只有2個列用于保存“索引(鍵)值對”,這樣就可以方便地通過索引找到值。
               如:10=男、20=女,其中10,20就叫做索引,通過10,20就能夠找到性別名稱:男和女
          ·值類型:指實際保存的數據的類型。如男和女。
          ·索引類型:通常指定為下面兩種整數類型之一:binary_integer 或者 pls_integer。區別是:
                    ·Binary_Integer類型變量值計算是由Oracle來執行,不會出現溢出,但是執行速度較慢,因為它是由Oracle模擬執行。
                   ·Pls_Integer的執行是由硬件即直接由CPU來運算,因而會出現溢出,但其執行速度較前者快許多。Oracle舊版本不支持。


          需求:用戶輸入10,打印男;輸入20,打印女。
          分析:
          ·根據上面的需求,值是“男”或者“女”,所以只需要char(2)就可以了。
          ·在數據量不是太大時,可以選擇索引的類型為:pls_integer。

          代碼:
          declare
          --1.定義表結構
          type myTabType is table of char(2) index by pls_integer;
          --2.創建表類型變量
          sexTab myTabType;

          v_sex_code number(2);
          v_sex_name char(2);
          begin
          --3.插入數據:
          sexTab (10):='男';
          sexTab (20):='女';
          --用戶輸入
          v_sex_code:=&性別編號;

          --4. 查詢數據(如:sexTab (10) 表示“查詢索引為10的值,得到 男”)
          v_sex_name:=sexTab (v_sex_code);

          dbms_output.put_line('您的性別是 = '||v_sex_name);
          end;

          說明:sexTab在插入數據以后,在內存結構如下:
          index    值
          10          男
          20          女

          使用table類型也可以查詢多行多列的數據。

          需求:查詢所有部門

          declare
          --定義表結構(省略了index by,見說明)

          type myType is table of dept%rowtype;
          --創建表類型變量
          myTab myType;
          begin

          select * bulk collect into myTab from dept;
          for x in 1..myTab.count
          loop
             dbms_output.put_line(myTab(x).deptno);
             dbms_output.put_line(myTab(x).dname);
          end loop;

          end;

          說明:

          ·本列中myTab的索引是由程序為索引賦值,所以index by語句可以省略。

          · 將查詢的所有部門放到myTab,索引自動設置為1,2,3…

          打印:

          10
          ACCOUNTING
          20
          RESEARCH
          30
          SALES
          40
          OPERATIONS

          探討:有關PL/SQL表類型中的理解。
          ·很容易認為PL/SQL表類型象c或Java中的數組類型,因為其中有個關鍵字叫做“index”(索引),而數組的下標也叫做“index”。
          ·但是這樣無法解釋PL/SQL表類型的索引可以不連續,甚至可以為負數的問題。
          ·我認為,PL/SQL表類型更象是java中的map對象,索引就對應map中的鍵,多個值之間的鍵可以不連續,可以為負數,甚至可以是字符串。兩者有異曲同工之妙。

          示例:用字符串做索引。
          declare
          --定義表結構
          type myTabType is table of char(2) index by varchar2(5);
          sexTab myTabType;

          v_sex_code varchar2(5);
          v_sex_name char(2); 
          begin
          --往表中添加內容
          sexTab('nan'):='男';
          sexTab('nv'):='女';
          --用戶輸入
          v_sex_code:='&性別編號';
          v_sex_name:=sexTab(v_sex_code);

          dbms_output.put_line('您的性別是 = '||v_sex_name);
          end;

          輸入:nan
          輸出: 男

          問題:用table類型能夠保存多個列嗎?
          回答:
          可以。只要將“值類型”換為復合類型就可以了。如下面的table定義就能夠保存emp表的所有記錄:
          type empTabType is table of emp%rowtype index by pls_integer。
          注意:empTabType的索引可以是empno,也可以不是。

          聯想一下下:
          ·在PL/SQL表中,利用PL/SQL表類型,在某些場合也能夠避免減少表連接,從而大大提高連接的效率。
          ·在java中map對象用途非常廣泛,可以緩存很多對象(如配置文件對象,常見的查詢結果對象等)。兩者的用法真的是異曲同工之妙。

          7、其它類型
          ·嵌套表、數組:用得少,不學了。
          ·游標類型,引用游標類型:在后面學習游標以后再學習。

          主要內容小結:
          ·塊結構:變量區、代碼區、異常區
          ·塊分類:匿名塊、命名塊(具體的在后面學習)
          ·標量類型:char,varchar2,number,date,boolean,type 
          ·復合類型:rowtype,record,table

          個人小結:
          ·保存一個值的變量,可以用具體的數據或者type類型

          ·保存多個值的變量,可以用rowtype,record。

          ·保存多行2列的變量,可以用table類型。

          ·保存多行多列的變量,仍然用table類型,只是數據類型選用rowtype即可。

          posted on 2012-09-05 16:25 kxbin 閱讀(454) 評論(0)  編輯  收藏 所屬分類: ORACLE轉發
          你恨一個人是因為你愛他;你喜歡一個人,是因為他身上有你沒有的;你討厭一個人是因為他身上有你有的東西;你經常在別人面前批評某人,其實潛意識中是想接近他。

          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿(5)

          隨筆檔案

          文章分類

          文章檔案

          相冊

          收藏夾

          J2EE

          java技術網站

          Linux

          平時常去的網站

          數據庫

          電影網站

          網站設計

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 正镶白旗| 江西省| 海口市| 景泰县| 石棉县| 新昌县| 霸州市| 隆昌县| 平顺县| 万载县| 湘阴县| 始兴县| 舟曲县| 金塔县| 会东县| 宁阳县| 玉溪市| 湘乡市| 东辽县| 军事| 个旧市| 沂水县| 靖州| 临武县| 故城县| 原阳县| 罗源县| 板桥市| 新乡市| 腾冲县| 侯马市| 年辖:市辖区| 绩溪县| 合山市| 延安市| 探索| 临夏市| 屯门区| 馆陶县| 阿拉善盟| 遂昌县|