5.2 数据类型、变量和常量

视频讲解:光盘\TM\lx\5\数据类型与定义变量.mp4

数据类型本质上是一种用于描述数据存储的内存结构,用它来决定变量中所存储数据的类型。而变量本质上是一种用名称进行识别的标示符号,它可以存储不同类型的数据。根据不同的数据类型,定义不同名称的变量,这样就可以存储不同类型的数据。变量在程序运行的过程中,其值可以发生变化,与变量对应的就是常量,常量就是指在程序运行的过程中,其值不会发生变化的量。

5.2.1 基本数据类型

与其他编程语言一样,PL/SQL语言也有多种数据类型,这些数据类型能够满足在编写PL/SQL程序过程中定义变量和常量之用,本节主要介绍在编写PL/SQL程序时经常用到的基本数据类型。

1.数值类型

数值类型主要包括NUMBER、PLS_INTEGER和BINARY_INTEGER三种基本类型。其中,NUMBER类型的变量可以存储整数或浮点数,而BINARY_INTEGER或PLS_INTEGER类型的变量只能存储整数。

NUMBER类型还可以通过NUMBER(P, S)的形式来格式化数字,其中,参数P表示精度,参数S表示刻度范围。精度是指数值中所有有效数字的个数,而刻度范围是指小数点右边小数位的个数,在这里精度和刻度范围都是可选的。下面通过一个示例来具体讲解一下。

【例5.4】 声明一个精度为9,且刻度范围为2的表示金额的变量Num_Money,代码如下。

        Num_Money NUMBER(9,2);

PL/SQL语言出于代码可读性或与来自其他编程语言的数据类型相兼容的考虑,提出了“子类型”的概念,所谓子类型就是与NUMBER类型等价的类型别名,甚至可以说是NUMBER类型的多种重命名形式,这些等价的子类型主要包括DEC、DECIMAL、DOUBLE、INTEGER、INT、NUMERIC、SMALLINT、BINARY_INTEGER、PLS_INTEGER等。

2.字符类型

字符类型主要包括VARCHAR2、CHAR、LONG、NCHAR和NVARCHAR2等。这些类型的变量用来存储字符串或字符数据。下面对这几种字符类型进行讲解。

(1)VARCHAR2类型

PL/SQL语言中的VARCHAR2类型和数据库类型中的VARCHAR2比较类似,用于存储可变长度的字符串,其声明语法格式为:

        VARCHAR2(maxlength)

参数maxlength表示可以存储字符串的最大长度,这个参数值在定义变量时必须给出(因为VARCHAR2类型没有默认的最大长度),参数maxlength的最大值可以是32767。

注意

数据库类型的VARCHAR2的最大长度是4000字节,所以一个长度大于4000字节的PL/SQL类型VARCHAR2变量不可以赋值给数据库中的一个VARCHAR2变量,而只能赋值给LONG类型的数据库变量。

(2)CHAR类型

CHAR类型表示指定长度的字符串,其语法格式如下:

        CHAR(maxlength)

参数maxlength是指可存储字符串的最大长度,以字节为单位,最大为32767字节,CHAR类型的默认最大长度为1。与VARCHAR2不同,maxlength可以不指定,默认为1。如果赋给CHAR类型的值不足maxlength,则会在其后面用空格补全,这也是不同于VARCHAR2的地方。

注意

数据库类型中的CHAR只有2000字节,所以如果PL/SQL中CHAR类型变量的长度大于2000个字节,则不能赋给数据库中的CHAR。

(3)LONG类型

LONG类型表示一个可变的字符串,最大长度是32767字节,而数据库类型的LONG最大长度可达2GB,所以几乎任何字符串变量都可以赋值给它。

(4)NCHAR和NVARCHAR2类型

NCHAR和NVARCHAR2类型是PL/SQL8.0以后才加入的类型,它们的长度要根据各国字符集来确定,只能具体情况具体分析。

3.日期类型

日期类型只有一种—DATE类型,用来存储日期和时间信息,DATE类型的存储空间是7个字节,分别使用一个字节存储世纪、年、月、天、小时、分钟和秒。

4.布尔类型

布尔类型也只有一种—即BOOLEAN,主要用于程序的流程控制和业务逻辑判断,其变量值可以是TRUE、FALSE或NULL中的一种。

5.2.2 特殊数据类型

为了提高用户的编程效率和解决复杂的业务逻辑需求,PL/SQL语言除了可以使用Oracle规定的基本数据类型外,还提供了3种特殊的数据类型,但这3种类型仍然是建立在基本数据类型基础之上的。

1.%TYPE类型

使用%TYPE关键字可以声明一个与指定列相同的数据类型,它通常紧跟在指定列名的后面。

【例5.5】 声明了一个与emp表中job列的数据类型完全相同的变量var_job,代码如下。

        declare
          var_job emp.job%type;

在上面的代码中,若emp.job列的数据类型为VARCHAR2(10),那么变量var_job的数据类型也是VARCHAR2(10),甚至可以把“emp.job%type”就看做是一种能够存储指定列类型的特殊数据类型。

使用%TYPE定义变量有两个好处:第一,用户不必查看表中各个列的数据类型,就可以确保所定义的变量能够存储检索的数据;第二,如果对表中已有列的数据类型进行修改,则用户不必考虑对已定义的变量所使用的数据类型进行更改,因为%TYPE类型的变量会根据列的实际类型自动调整自身的数据类型。

【例5.6】 在scott模式下,使用%type类型的变量输出emp表中编号为7369的员工名称和职务信息,代码如下(实例位置:光盘\TM\sl\5\2)

        SQL> set serveroutput on
        SQL> declare
          2   var_ename emp.ename%type;                                 --声明与ename列类型相同的变量
          3   var_job emp.job%type;                                     --声明与job列类型相同的变量
          4  begin
          5   select ename, job
          6   into var_ename, var_job
          7   from emp
          8   where empno=7369;                                         --检索数据,并保存在变量中
          9   dbms_output.put_line(var_ename||’的职务是’||var_job);    --输出变量的值
         10  end;
         11  /

本例运行结果如图5.2所示。

图5.2 使用%type类型定义变量并输出

另外,在上面代码中使用into子句,它位于select子句的后面,用于设置将从数据库检索的数据存储到哪个变量中。

注意

由于into子句中的变量只能存储一个单独的值,所以要求select子句只能返回一行数据,这个由where子句进行了限定。若SELECT子句返回多行数据,则代码运行后会返回错误信息。

2.RECORD类型

单词RECORD有“记录”之意,因此RECORD类型也称作“记录类型”,使用该类型的变量可以存储由多个列值组成的一行数据。在声明记录类型变量之前,首先需要定义记录类型,然后才可以声明记录类型的变量。记录类型是一种结构化的数据类型,它使用type语句进行定义,在记录类型的定义结构中包含成员变量及其数据类型,其语法格式如下。

        type record_type is record
        (
        var_member1 data_type [not null] [:=default_value],
        …
        var_membern data_type [not null] [:=default_value])

record_type:表示要定义的记录类型名称。

var_member1:表示该记录类型的成员变量名称。

data_type:表示成员变量的数据类型。

从上面的语法结构中可以看出,记录类型的声明类似于C或C++中的结构类型,并且成员变量的声明与普通PL/SQL变量的声明相同。下面通过一个实例来了解如何声明和使用RECORD类型。

【例5.7】 声明一个记录类型emp_type,然后使用该类型的变量存储emp表中的一条记录信息,并输出这条记录信息,代码如下(实例位置:光盘\TM\sl\5\3)

        SQL> set serveroutput on
        SQL> declare
          2   type emp_type is record                --声明record类型emp_type
          3   (
          4     var_ename varchar2(20),             --定义字段/成员变量
          5     var_job varchar2(20),
          6     var_sal number
          7   );
          8   empinfo  emp_type;                  --定义变量
          9  begin
         10   select ename, job, sal
         11   into empinfo
         12   from emp
         13   where empno=7369;                  --检索数据
         14   /*输出雇员信息*/
         15      dbms_output.put_line(' 雇员 '||empinfo.var_ename||' 的职务是 '||empinfo.var_job||' 、工资是
        '||empinfo.var_sal);
         16  end;
         17  /

本例运行结果如图5.3所示。

图5.3 定义和使用记录类型

3.%ROWTYPE类型

%ROWTYPE类型的变量结合了“%TYPE类型”和“记录类型”变量的优点,它可以根据数据表中行的结构定义一种特殊的数据类型,用来存储从数据表中检索到的一行数据。它的语法形式很简单,如下所示。

        rowVar_name table_name%rowtype;

rowVar_name:表示可以存储一行数据的变量名。

table_name:指定的表名。

在上面的语法结构中,可以不恰当地把“table_name%rowtype”看做是一种能够存储表中一行数据的特殊类型。下面通过一个实例来看一下如何定义和使用%ROWTYPE类型。

【例5.8】 声明一个%ROWTYPE类型的变量rowVar_emp,然后使用该变量存储emp表中的一行数据,代码如下(实例位置:光盘\TM\sl\5\4)

        SQL> set serveroutput on
        SQL> declare
          2   rowVar_emp emp%rowtype;             --定义能够存储emp表中一行数据的变量rowVar_emp
          3  begin
          4   select*
          5   into rowVar_emp
          6   from emp
          7   where empno=7369;                   --检索数据
          8   /*输出雇员信息*/
          9       dbms_output.put_line(' 雇员 '||rowVar_emp.ename||' 的编号是 '||rowVar_emp.empno||', 职务是
        '||rowVar_emp.job);
         10  end;
         11  /

本例运行结果如图5.4所示。

图5.4 定义和使用%ROWTYPE类型

从上面的运行结果可以看出,变量rowVar_emp的存储结构与emp表的数据结构完全相同,这时用户完全可以使用rowVar_emp变量来代替emp表的某一行数据进行编程操作。

5.2.3 定义变量和常量

在上面的章节中,已经逐步将变量的定义和使用方法介绍给大家,相信读者对变量并不陌生,本节将主要是对定义变量的规范进行总结。另外,常量在PL/SQL编程中也经常用到,本节也做相应的介绍。

1.定义变量

变量是指其值在程序运行过程中可以改变的数据存储结构,定义变量必需的元素就是变量名和数据类型,另外还有可选择的初始值,其标准语法格式如下:

        <变量名> <数据类型> [(长度):=<初始值>];

可见,与很多面向对象的编程语言不同,PL/SQL中的变量定义要求变量名在数据类型的前面,而不是后面;语法中的长度和初始值是可选项,需要根据实际情况而定。

【例5.9】 定义一个用于存储国家名称的可变字符串变量var_countryname,该变量的最大长度是50,并且该变量的初始值为“中国”,代码如下。

        var_countryname varchar2(50):=’中国’;

2.定义常量

常量是指其值在程序运行过程中不可改变的数据存储结构,定义常量必需的元素包括常量名、数据类型、常量值和constant关键字,其标准语法格式如下:

        <常量名> constant <数据类型>:=<常量值>;

对于一些固定的数值,比如圆周率、光速等,为了防止其不慎被改变,最好定义成常量。

【例5.10】 定义一个常量con_day,用来存储一年的天数,代码如下。

        con_day constant integer:=365;

3.变量初始化

许多语言没有规定未经过初始化的变量中应该存放什么内容。因此在运行时,未初始化的变量就可能包含随机的或者未知的取值。在一种语言中,运行使用未初始化变量并不是一种很好的编程风格。一般而言,如果变量的取值可以被确定,那么最好为其初始化一个数值。

但是,PL/SQL定义了一个未初始化变量应该存放的内容,其被赋值为NULL。NULL意味着“未定义或未知的取值”。换句话讲,NULL可以被默认地赋值给任何未经过初始化的变量。这是PL/SQL的一个独到之处,许多其他程序设计语言没有定义未初始化变量的取值。

5.2.4 PL/SQL表达式

表达式不能独立构成语句,表达式的结果是一个值,如果不给这个值安排一个存放的位置,则表达式本身毫无意义。通常,表达式作为赋值语句的一部分出现在赋值运算符的右边,或者作为函数的参数等。

例如,123*23-24+33就是一个表达式,它是由运算符串连起来的一组数,按照运算符的意义运算会得到一个运算结果,这就是表达式的值。

“操作数”是运算符的参数。根据所拥有的参数个数,PL/SQL运算符可分为一元运算符(一个参数)和二元运算符(两个参数)。表达式按照操作对象的不同,也可以分为字符表达式和布尔表达式两种。

1.字符表达式

唯一的字符运算符就是并置运算符“||”,它的作用是把几个字符串连在一起,如表达式:'Hello'||'World'||'! ’的值等于’Hello World! '。

2.布尔表达式

PL/SQL控制结构都涉及布尔表达式。布尔表达式是一个判断结果为真还是为假的条件,它的值只有TRUE、FALSE或NULL,如以下表达式所示。

        (x>y);
        NULL;
        (4>5)OR(-1<0);

布尔表达式有3个布尔运算符:AND、OR和NOT,与高级语言中的逻辑运算符一样,它们的操作对象是布尔变量或者表达式。如:

        A AND B OR 1 NOT C

其中,A、B、C都是布尔变量或者表达式。表达式TRUE AND NULL的值为NULL,因为不知道第二个操作数是否为TRUE。

布尔表达式中的算术运算符如表5.2所示。

表5.2 布尔表达式中的算术运算符

此外,between操作符可以划定一个范围,在范围内则为真,否则为假。如:

1 between 0 and 100表达式的值为真。

IN操作符判断某一元素是否属于某个集合,如:

'Scott'IN('Mike', 'Jone', 'Mary')为假。