前言: 使用变量可以保存计算机需要处理的数据,为了给该变量分配适当的内存空间,还需要指定数据类型,有的数据类型还需要指定长度,如字符串。 有些类型可以用于建表(如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 |