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

PLSQL 之类型、变量和结构相关推荐

  1. 结构体变量和结构体类型的定义

    结构体类型定义 定义方式1:Typedef struct LNode {int data; // 数据域struct LNode *next; // 指针域 } *LinkList; 定义方式2:st ...

  2. php弱类型机制,浅析php变量存储结构及弱类型实现机制

    根据需要下载相应php源代码: php 下载地址 当前下载php版本为 php-5.5.37 变量的值存储到以下所示zval结构体中. zval结构体定义在Zend/zend_types.h文件 ty ...

  3. 【C 语言】结构体 ( 结构体类型定义 | 结构体类型别名 | 声明结构体变量的三种方法 | 栈内存中声明结构体变量 | 定义隐式结构体时声明变量 | 定义普通结构体时声明变量 )

    文章目录 一.结构体类型定义 二.结构体类型别名 三.结构体类型变量声明 1.使用结构体类型 ( 别名 ) 声明变量 2. 定义隐式结构体时声明变量 3.定义普通结构体时声明变量 二.完整代码示例 一 ...

  4. php变量结构体的深入理解,第一节 变量的结构和类型

    前言中提到变量的三个基本特性,其中的有一个特性为变量的类型,变量都有特定的类型,如:字符串.数组.对象等等.编程语言的类型系统可以分为强类型和弱类型两种: 强类型语言是一旦某个变量被申明为某个类型的变 ...

  5. java 定义类变量初始化吗_Java的变量有哪些类型?变量如何定义?如何初始化?请说明理由并举例_学小易找答案...

    [单选题]根据金杯萃取理论,咖啡萃取比较适合的参数是: (2.9分) [判断题]高分化的鳞状细胞癌恶性程度高,低分化的鳞状细胞癌恶性程度低. ( ) [简答题]第 3-4 节之间的关系是什么?在全诗结 ...

  6. C语言定义了一个结构体怎么分配内存?C\C++中结构体变量与结构体指针内存分配问题?

    C语言定义了一个结构体怎么分配内存?C\C++中结构体变量与结构体指针内存分配问题? 问题1:结构体指针最开始怎么分配内存?用sizeof()是不能确定大小的. 问题2:给结构体变量分配之后,是否还要 ...

  7. 【STM32】typedef 类型及配合结构体使用

    文章目录 1 typedef 2 结构体 2.1 定义结构 2.2 结构体变量的初始化 2.3 访问结构成员 2.4 结构作为函数参数 2.5 指向结构的指针 1 typedef C 语言提供了 ty ...

  8. 黑马程序员C语言基础(第八天)复合类型(自定义类型)(结构体)、共用体(联合体)、枚举enum、 typedef

    黑马程序员C语言基础(第一天) 黑马程序员C语言基础(第二天) 黑马程序员C语言基础(第三天) 黑马程序员C语言基础(第四天)数据类型 黑马程序员C语言基础(第五天)运算符与表达式.程序流程结构.数组 ...

  9. 自己实现了一个C语言例程,加深对宏、大小端、typeof宏、offsetof宏、指针变量、结构体、联合体的理解

    如题所述,最近时间在复习C语言.自己实现了一个C语言例程,以加深对宏.大小端.typeof宏.offsetof宏.指针变量.结构体.联合体的理解.关于细分知识后续有空再填充- swap宏的使用: 对应 ...

  10. c语言学习笔记【结构体02】结构体指针变量与结构体变量的函数参数,C语言学习笔记结构体02结构体指针变量与结构体变量的函数参数.docx...

    C 语言学习笔记[结构体02]结构体指针变量与结构体变量 的函数参数 C 语言学习笔记之结构体指针变量一提指针,那可 是 C 语言的核心了,有多少学子曾拜倒在指针的脚下.单纯的说指针,其实并不难,但是 ...

最新文章

  1. 使用GDAL将12bit量化图像转为16bit或者8bit
  2. 使用ASV2011研究Molehill API
  3. 攻防世界-web-ics-04-从0到1的解题历程writeup
  4. js操作cookie的函数
  5. codeforces1472 G. Moving to the Capital
  6. centos清除dns cache.
  7. AI应用开发基础傻瓜书系列3-损失函数
  8. 我可能不适合做前端,你呢?
  9. JFinal上传文件时用getFile()方法报错
  10. 可以完成99%的静态页面的HTML标签
  11. 压力测试就是一种破坏性的性能测试
  12. VDO-SLAM 配置 2022 Ubuntu20.04
  13. C++设计模式10--命令模式(一)--降低请求发送者与接收者耦合
  14. Linux开发环境——tftp服务器的搭建
  15. Aircrack-ng套件——无线破解原理及工具详解
  16. java 判断exception类型_Java中获取Exception的详细信息
  17. docker安装shipyard
  18. JavaScript数据类型、引用类型、操作符、语句
  19. Android超强大的粒子动画库,流星雨,爆炸,满屏飞花,等粒子特效快速实现
  20. NAS不够快?那就上SSD享受如火箭般的体验吧!

热门文章

  1. 实验七:Xen环境下cirrOS的安装配置
  2. FZU - 2268 Cutting Game
  3. Android Studio 之 NDK篇
  4. SHA-1算法c语言实现
  5. java中范型的限定
  6. HDU4055 - number string(DP)
  7. android 小工具:pc 上用 curl 命令打开手机浏览器,浏览指定网址
  8. 运行cmd状态下MySQL导入导出.sql文件
  9. JAVA编程心得-JAVA实现CRC-CCITT(XMODEM)算法
  10. Django实战(1):需求分析和设计