PLSQL 之類型、變量和結構

1、類型

在《.Net程序員學用Oracle系列(5):三大數據類型》一文中詳細地講述了 Oracle 的基本數據類型,文中還提到,除基本數據類型之外,Oracle 還在語法上支持一些非固有數值類型。

事實上,Oracle 在語法上支持的數據類型遠不止于此,Oracle 還支持一些復雜而強大的數據類型。如屬性類型%TYPE%ROWTYPE,記錄類型 RECORD,集合類型 VARRAY 和 TABLE 等。本節將會介紹實用的屬性類型和靈活的記錄類型。

1.1、屬性類型

屬性類型是一種可以直接引用數據庫中列的數據類型來描述變量類型的類型。Oracle 提供了兩種屬性類型,分別是%TYPE%ROWTYPE,下文將逐一說明。

%TYPE:該屬性允許在聲明中引用數據庫中的列或先前聲明的變量的數據類型,而不是硬編碼類型名稱。在聲明常量、變量和參數時,都可以使用%TYPE屬性作為數據類型說明符。如果引用的類型被更改,則聲明也將自動更新,這點有利于后期代碼維護。

示例:

DECLAREv_staff_name?t_staff.staff_name%TYPE;BEGINSELECT?t.staff_name?INTO?v_staff_name?FROM?demo.t_staff?t?WHERE?t.staff_id=5;DBMS_OUTPUT.PUT_LINE(v_staff_name);END;

%ROWTYPE:該屬性可以表示數據庫中表或游標的行的記錄類型。使用%ROWTYPE聲明的變量可以存儲從表中選擇或從游標或游標變量獲取的整行數據,且變量記錄中的字段和每行中的相應列具有相同的名稱和數據類型。

示例:

DECLAREv_staff?t_staff%ROWTYPE;BEGINSELECT?t.*?INTO?v_staff?FROM?demo.t_staff?t?WHERE?t.staff_id=5;DBMS_OUTPUT.PUT_LINE(v_staff.staff_name);END;

想要更多的了解屬性類型可參考:《Database PL/SQL User's Guide and Reference: %TYPE Attribute》和《Database PL/SQL User's Guide and Reference: %ROWTYPE Attribute》。

1.2、記錄類型

記錄類型是由單行多列標量構成的復合結構。可以看做是一種用戶自定義的數據類型,提供了將一個或多個標量封裝成一個對象進行操作的能力。在使用記錄數據類型的變量時,需要在聲明部分先定義記錄的成員變量,然后在執行部分引用該記錄變量本身或其中的成員。但不可以對記錄做整體性的比較運算,如判斷記錄類型的變量是否為 NULL。

示例:

DECLARETYPE?staff_type?IS?RECORD(staff_name?VARCHAR2(50),gender?VARCHAR2(2));v_staff?staff_type;BEGINSELECT?t.staff_name,DECODE(t.gender,1,'男',0,'女','兩性')?INTO?v_staff.staff_name,v_staff.gender??FROM?demo.t_staff?t?WHERE?t.staff_id=5;DBMS_OUTPUT.PUT_LINE(v_staff.staff_name||'|'||v_staff.gender);END;

記錄類型和%ROWTYPE屬性在用途上比較相似,區別在于前者是自定義結構,而后者為表結構,前者比較靈活,而后者比較方便。

2、變量

一般計算機編程語言中都有變量的概念,PL/SQL 也不例外,變量用于存儲計算結果和表示可變狀態,本節將著重介紹在 PL/SQL 中變量如何定義及賦值。另外,PL/SQL 中也有常量,只是極少有人使用,有興趣的讀者可以參考《Oracle Database PL/SQL Language Reference: Constant》。

2.1、變量類型

在 PL/SQL 中定義變量的可選類型非常多,包括 Oracle 中常見的三大類基本數據類型,以及 Oracle 在語法上支持的諸多非固有數據類型。如整形(INT/INTEGER)、布爾類型(BOOLEAN)等 Oracle 本身并不支持,卻在 PL/SQL 中可用的數據類型。

2.2、變量定義

在 PL/SQL 中定義變量與 C# 中定義變量本質上并無區別,不同的是 PL/SQL 中的變量得集中定義,變量定義區域得用DECLARE關鍵字開頭,且每行只能定義一個變量。如果是 SQL*Plus 環境則必須用VAR[IABLE]開頭。

語法:

variable_name?datatype?[[NOT?NULL]?{:=?|?DEFAULT}?expression];

如果使用了 NOT NULL 則必須給變量賦初始值。另外,在命名變量的時候還需要遵守以下命名規則:

  • 1、變量名必須以字母開頭。

  • 2、變量名長度不能超過 30 個字符。

  • 3、變量名中不能含有空格。

  • 4、同一語句塊內變量名不能重復。

  • 5、變量名不能與查詢中的列名相同。

2.3、變量賦值

給 PL/SQL 變量賦值的寫法與給 C# 字段賦值寫法基本一樣,既可以在定義變量時就賦給它一個初始值,也可以在使用之前給它賦值,如果不賦值也會有默認值。唯一的區別就是,C# 中類型不同默認值也不同,而 PL/SQL 中所有類型的默認值都一樣,都是 NULL。

在 PL/SQL 中還有一點比較怪的就是,可能所有編程語言的賦值操作符都是=,而 PL/SQL 中的賦值操作符卻偏偏是:=。而且 Oracle 相關的 API 中參數寫法也與其它大多數數據庫不同。

示例一(普通 PL/SQL 環境):

DECLAREv1?NUMBER;v2?NUMBER(5,2);v3?NUMBER?:=?50.20;v4?NUMBER(4)?:=?1998;v5?VARCHAR2(4)?DEFAULT?'A';v6?DATE?NOT?NULL?:=?fn_now;BEGINv1?:=?100;v2?:=?99.99;v5?:=?'A5';v6?:=?SYSDATE;??DBMS_OUTPUT.PUT_LINE(v1||'|'||v2||'|'||v3||'|'||v4||'|'||v5||'|'||v6);END;

示例二(SQL*Plus 環境):

VARIABLE?v1?NUMBERBEGIN:v1?:=?12;DBMS_OUTPUT.PUT_LINE(:v1);END;/

3、結構

和普通編程語言一樣,PL/SQL 中也有常見的三大控制結構以及順序控制語句——GOTO。本節將重點講述被廣泛接受的三大控制結構,至于不受待見的 GOTO 語句,有興趣的讀者可以參考《Oracle Database PL/SQL User's Guide and Reference: Using the GOTO Statement》。

3.1、順序結構

順序結構是面向過程編程中最基本、最簡單、最常用的程序控制結構。順序結構用于表示若干個依次執行的處理步驟,表現形式就是線性結構,一個方向走下去、不拐彎。使用時只要按照解決問題的順序寫出相應的語句就行,它的執行順序是自上而下、依次執行。

3.2、選擇結構

PL/SQL 中提供了兩種選擇結構,分別是IF結構和CASE結構。其中IF結構有三種變體,CASE結構有兩種變體。下文將逐一講述各個選擇語句:

IF 結構變體一:

語法:

IF?condition?THEN{...statements?to?execute?when?condition?is?TRUE...}END?IF;

示例:

BEGINIF?1>0?THENDBMS_OUTPUT.PUT_LINE('executed');??END?IF;END;

IF 結構變體二:

語法:

IF?condition?THEN{...statements?to?execute?when?condition?is?TRUE...}ELSE{...statements?to?execute?when?condition?is?FALSE...}END?IF;

示例:

BEGINIF?1>2?THENDBMS_OUTPUT.PUT_LINE('The?result?is?true');ELSEDBMS_OUTPUT.PUT_LINE('The?result?is?false');??END?IF;END;

IF 結構變體三:

語法:

IF?condition1?THEN{...statements?to?execute?when?condition1?is?TRUE...}ELSIF?condition2?THEN{...statements?to?execute?when?condition2?is?TRUE...}[ELSE{...statements?to?execute?when?both?condition1?and?condition2?are?FALSE...}]END?IF;

示例:

BEGINIF?1>2?THENDBMS_OUTPUT.PUT_LINE('1>2?branch');ELSIF?1<2?THENDBMS_OUTPUT.PUT_LINE('1<2?branch');??ELSEDBMS_OUTPUT.PUT_LINE('1=2?branch');??END?IF;END;

注意:IF 結構變體三中有個巨坑,就是 IF 和 ELSE 之間的分支寫法,不是 ELSE IF 也不是 ELSEIF 而是 ELSIF。盡管你寫成 ELSE IF 編輯器也有智能提示,但當你執行的時候就會報ORA-06550的錯,而且這個錯誤的描述正常人基本沒可能看懂。

CASE 結構變體一

示例:

DECLAREv_grade?VARCHAR2(1);BEGINv_grade:='B';??CASE?v_gradeWHEN?'A'?THEN?DBMS_OUTPUT.PUT_LINE('甲');WHEN?'B'?THEN?DBMS_OUTPUT.PUT_LINE('乙');WHEN?'C'?THEN?DBMS_OUTPUT.PUT_LINE('丙');????ELSE?DBMS_OUTPUT.PUT_LINE('丁');??END?CASE;END;

CASE 結構變體二

示例:

DECLAREv_score?NUMBER(3);
BEGINv_score:=78;??CASEWHEN?v_score>=80?THEN?DBMS_OUTPUT.PUT_LINE('優');WHEN?v_score>=70?THEN?DBMS_OUTPUT.PUT_LINE('良');WHEN?v_score>=60?THEN?DBMS_OUTPUT.PUT_LINE('中');ELSE?DBMS_OUTPUT.PUT_LINE('差');END?CASE;END;

與多分支的 IF 語句相比,CASE 語句更可讀、更高效,所以當程序分支較多時,應盡可能的使用 CASE 而不是 IF。CASE 語句的 ELSE 子句是可選的。但如果省略 ELSE 字句,PL/SQL 將為 CASE 語句添加以下隱式的 ELSE 子句:

ELSE?RAISE?CASE_NOT_FOUND;

換句話說,如果你省略了 ELSE 子句,且 CASE 語句與 WHEN 子句不匹配,PL/SQL 就會引發預定義的異常CASE_NOT_FOUND

3.3、循環結構

PL/SQL 中提供了三種循環結構,分別是LOOPWHILE LOOPFOR LOOP。另外 PL/SQL 還提供了EXIT語句用于退出當前循環。下文將逐一講述各個循環語句:

LOOP 循環

語法:

LOOP??{...statements...}EXIT?[?WHEN?boolean_condition?];END?LOOP;

示例一:

DECLAREv_counter?BINARY_INTEGER?:=?0;
BEGIN??LOOPv_counter?:=?v_counter?+?1;DBMS_OUTPUT.PUT_LINE(v_counter);?--?輸出結果:1、2、3、4、5、6、7、8、9IF?v_counter?>=?9?THENEXIT;????END?IF;--?上面的?IF?語句塊還可以由“EXIT?WHEN?v_counter?>=?9;”代替??END?LOOP;END;

示例二(嵌套循環):

DECLARE??i?BINARY_INTEGER?:=?0;??j?BINARY_INTEGER?:=?0;
BEGINLOOP????i?:=?i?+?1;????j?:=?0;LOOP??????j?:=?j?+?1;DBMS_OUTPUT.PUT_LINE('i*j=('||i||'*'||j||')='||i*j);EXIT?WHEN?j?>=?3;END?LOOP;EXIT?WHEN?i?>=?4;END?LOOP;
END;

示例三(標記循環):

DECLARE??i?BINARY_INTEGER?:=?0;??j?BINARY_INTEGER?:=?0;
BEGIN<<outer_loop>>LOOP????i?:=?i?+?1;????j?:=?0;<<inner_loop>>LOOP??????j?:=?j?+?1;DBMS_OUTPUT.PUT_LINE('i*j=('||i||'*'||j||')='||i*j);EXIT?inner_loop?WHEN?j?>=?3;EXIT?outer_loop?WHEN?i?>=?4;END?LOOP?inner_loop;END?LOOP?outer_loop;
END;

WHILE LOOP 循環

語法:

WHILE?condition
LOOP??{...statements...}END?LOOP;

示例:

DECLAREv_score?NUMBER(3)?:=?0;BEGINWHILE?v_score?<?60?LOOPv_score?:=?v_score?+?10;DBMS_OUTPUT.PUT_LINE(v_score);?--?輸出結果:10、20、30、40、50、60END?LOOP;DBMS_OUTPUT.PUT_LINE('over');END;

FOR LOOP 循環

語法:

FOR?loop_counter?IN?[REVERSE]?lowest_number..highest_number
LOOP??{...statements...}END?LOOP;

示例一(正向循環):

BEGINFOR?i?IN?3..7?LOOPDBMS_OUTPUT.PUT_LINE(i);?--?輸出結果:3、4、5、6、7END?LOOP;END;

示例二(反向循環):

BEGINFOR?i?IN?REVERSE?3..7?LOOPDBMS_OUTPUT.PUT_LINE(i);?--?輸出結果:7、6、5、4、3END?LOOP;END;

注意:FOR LOOP 循環中的計數器(變量)可以被讀取,但不能被修改。另外,在 LOOP 循環的示例中用到的 EXIT 和循環標記,同樣可用于 WHILE LOOP 循環和 FOR LOOP 循環中

本文轉自帥氣的頭頭博客51CTO博客,原文鏈接http://blog.51cto.com/12902932/1926164如需轉載請自行聯系原作者


sshpp

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/279570.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/279570.shtml
英文地址,請注明出處:http://en.pswp.cn/news/279570.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

kindle圖書免費下載_如何在Kindle上免費簽出圖書館書籍

kindle圖書免費下載Tired of paying so much for ebooks? Most libraries these days let you check out eBooks, for free, just like regular books. 厭倦了為電子書支付這么多錢&#xff1f; 如今&#xff0c;大多數圖書館都讓您免費閱讀電子書&#xff0c;就像普通書籍一樣…

第五章 了解你的用戶

第五章 了解你的用戶邏輯人的爭議&#xff1a;要學會把軟件開發簡單易用象牙塔式的開發&#xff1a;開發團隊常年閉封在“高塔”之中&#xff0c;一門心思的做著魔法一般的軟件。這些開發者根本就不知道用戶會怎么樣的使用他們所做的軟件。我們應該避免這種象牙塔式的開發&…

總結之:CentOS 6.4系統裁減詳解及裝載網卡步驟

前言 隨著接觸Linux的慢慢深入、對Linux也有了一個基本認識了吧&#xff0c;慢慢的接觸系統內核、系統配置文件、在了解Linux的系統啟動流程后&#xff0c;現在來總結一下一個簡單的Linux系統的裁減方法和步驟&#xff0c;一個只有內核文件和幾個簡單的命令的小Linux系統&am…

android 設備占用_如何查看正在占用Android設備的空間

android 設備占用When you picked up your shiny new Android device, you probably thought “yeah, this has plenty of storage. I’ll never fill it up!” But here you are, some number of months later with a full phone and no clue why. No worries: here’s how yo…

最近沉迷生意經

高度戰略搶占顧客心智 速度戰略 . 規模不夠就談發展速度&#xff0c;避開自己的劣勢&#xff1b; . 發展速度快說明產品好&#xff0c;受歡迎度高; 錢是工具&#xff0c;從錢上解脫 . 不能被錢所困 . 放下錢&#xff0c;才能瀟灑地使用錢 第一時間搶占顧客心智 . 核心點就是搶占…

mysql密碼正確卻提示錯誤, 不輸入密碼反而能登錄

今天部署阿里云服務器, 發現之前可以連接的mysql服務器突然連接不上了, 密碼我確認是正確的,但登錄時就是顯示密碼錯誤, 很崩潰, 差點氣得我就想重裝mysql了。 好在經過幾番苦尋找到了以下能解決我問題的資料&#xff0c; 成功解決了我的問題&#xff0c; 萬分感謝&#xff0c;…

域用戶權限|安裝軟件

如何讓普通的域用戶有安裝軟件的權限&#xff1f;現在給客戶部署了活動目錄&#xff0c;客戶要求 普通的域用戶也可以自己安裝軟件。不知道如何設置&#xff0c;希望大家幫幫忙&#xff01;我告訴客戶的做法如下&#xff1a;不知道可行性如何&#xff1f; 1、在域中新建一個域賬…

c/c++ new delete初探

new delete初探 1&#xff0c;new有2個作用 開辟內存空間。調用構造函數。2&#xff0c;delete也有2個作用 釋放內存空間調用析構函數。如果用new開辟一個類的對象的數組&#xff0c;這個類里必須有默認(沒有參數的構造函數&#xff0c;或者有默認值的參數的構造函數)的構造函數…

php舊版本windows_Windows的舊版本中如何進行多任務處理?

php舊版本windowsConsidering that DOS was a single-tasking OS and the ties it had with early versions of Windows, just how did earlier versions of Windows manage to accomplish multi-tasking? Today’s SuperUser Q&A post looks at the answers to this ques…

批量提取視頻文件信息(文件大小及時長)并統計

隨著設備性能提高&#xff0c;視頻文件越來越大了。服務器在對外提供視頻服務時&#xff0c;需要承擔越來越大的存儲負擔。一般提供1080P的AVC編碼視頻已滿足多數觀看需求。&#xff08;1小時視頻大約1.3G&#xff09;此文要解決的就是關于已有大量高清視頻&#xff08;1小時超…

列出所有K個元素的子集-----2013年1月26日

問題描述:列出一個集合的元素個數為k的所有子集。思路:在字典順序列出所有子集的基礎上判斷元素個數就可以了&#xff0c;比較簡單。代碼如下:1 #include <stdio.h>2 #define MAX 10003 4 int main()5 {6 int n5;7 int set[MAX]{1};8 int index0;9 int …

docker swarm的應用----docker集群的構建

一、docker安裝 這里我們安裝docker-ce 的18.03版本 yum -y remove docker 刪除原有版本 #安裝依賴包 [rootDocker ~]# yum -y install yum-utils device-mapper-persistent-data lvm2 #添加docker的CE版本的yum源配置文件 [rootDocker ~]# curl https://download.docker…

微信小程序 fire_如何在Fire TV和Fire TV Stick上側面加載應用程序

微信小程序 fireAmazon’s Fire TV and Fire TV stick technically runs Android…but you wouldn’t know it from looking. Amazon has a wall of content for its set-top box, and doesn’t want Google (with its own competing platform) to crash the party. But even t…

PS 技巧

1. 鋼筆的使用&#xff1a; 扣完一圈以后&#xff0c;按Ctrl回車鍵&#xff0c;會出現螞蟻線&#xff0c;然后按CtrlJ 是復制扣出來的圖層&#xff0c;右下角的框里會出現一個新圖層&#xff0c;注意每個圖層前邊有一個小框&#xff0c;點一下是出現眼睛就可以顯示該圖層在中央…

Ibatis - Open quote is expected for attribute {1} associated with an element type '

昨天晚上提交的代碼&#xff0c;今天運行起來&#xff0c;始終報錯&#xff1a; Open quote is expected for attribute "{1}" associated with an element type id,查了半天&#xff0c;覺得很奇怪。 回滾到昨天的代碼&#xff0c;運行正常。經過compare代碼&#…

Linux系統運維之路

九月份開始&#xff0c;半年內搞定運維&#xff0c;博客會慢慢的更新&#xff0c;vim編輯器&#xff0c;Nginx配置文件優化 運維基礎 運維基礎-Linux發展史、安裝、基本操作 運維基礎-用戶和組管理 運維基礎-文件權限管理 運維基礎-進程管理 運維基礎-IO 管道 運維基礎-查找壓…

設備無法獲得谷歌運行怎么辦_因此,您剛剛獲得了Google主頁。 怎么辦?

設備無法獲得谷歌運行怎么辦So you scored a Google Home for Christmas. That’s awesome because this is a killer little smart speaker that can do a lot of different things—in fact, it can be a little overwhelming. The good news is that we’ve got you covered…

IDEA Maven創建多個Module相互依賴

1、前言 在大型企業項目中&#xff0c;系統架構復雜多變&#xff0c;一個項目根本無法支撐起所有業務。為了提高項目擴展性、靈活性、重用性&#xff0c;封裝性&#xff0c;將項目分為多個Module是非常必要的。 這里就不說IDEA如何安裝了&#xff0c;安裝好IDEA后需要修改maven…

速達5000出現計算成本數據溢出的問題

算成本提示某貨品成本溢出處理方法&#xff0c;該問題是由于貨品成本異常&#xff0c;成本上億或者負億造成的&#xff1b; 1.首先通過語句&#xff1a;select * into tmp_goods from l_goods where ABS(aprice)>100000&#xff0c;把成本價格超過10萬的貨品資料取出&#x…

Win32頁上的所有控件屬性與方法

Win32頁上的所有控件。該頁控件是在32位Win系統中的一些基本控件&#xff0c;如果你選擇開發CLX程序&#xff0c;則在控件面板上不會顯示該頁TTabControl屬性DisplayRect&#xff1a;只定該控件客戶區的一個矩形HotTrack&#xff1a;設置當鼠標經過頁標簽時&#xff0c;它的字是…