变量的作用域:   变量可以使用的程序单元部分


可见性: 当一个变量在它的作用域中可以用一个不限定的名字来引用时



1.CONSTANT  声明一个常量

2.NOT NULL 约束变量不能为空

3.:=value 用于为变量附初始值


例如

v_name DATE NOT NULL := SYSDATE

v_name INT  NOT NULL DEFAULT 7369

变量在没有被初始化的时候 变量会被初始化成null值  即使+1   依然还是null值 




%TYPE

例子  用于定义相同类型的变量   用于绑定单个列的值

     v_empno emp.empno%TYPE


%ROETYPE

      用于绑定一整行的 所有列

     v_emp emp%ROWTYPE


%TYPE 和 %ROWTYPE  只提供类型信息  并不能保证NOT NULL 约束



本地变量:在PLSQL块或子程序中定义的变量仅在本地可用,如果在块之外访问变量是非法的,这种变量称为本地变量 当超出其作用域时,变量使用的内存将会被释放,直到变量被重新定义并初始化


外部块中定义的变量对于子块来说是全局的,如果全局变量在子块中又被重新声明,那么全局变量和本地声明的变量在子块的作用域是存在的,要访问外部块的全局变量,需要使用限定修饰符。


当外部块和内部快都同时声明同一变量  优先访问本地的


12-8-5                

<<outer>>                     

declare

v_empname varchar2(20);

begin

v_empname:='张三';

<<inner>>

declare

v_empname varchar2(20);

begin

v_empname:='李四';

dbms_output.put_line('内层块的员工名称:' || v_empname );

dbms_output.put_line('外层块的员工名称:' || outer.v_empname);

end;

dbms_output.put_line('outer员工名称:' || v_empname);

end;



12-9-1 

数据类型

PLSQL 是一种静态类型化的程序设计语言,静态类型化又称为强类型化,也就是说类型会在编译时被检查,而不是在运行时,增强程序的稳定性


标量类型:用来保存单个值的数据类型,包含字符型,数字型,布尔型和日期型

复合类型:记录 嵌套表 索引表和变长数组

引用类型:REF CURSOR 和REF 2种

LOB类型:用来处理二进制和大于4GB的字符串


每个oracle数据库表都有一个名为ROWID的伪列。

SQL> select rowidtochar(rowid),ename,empno from emp;


ROWIDTOCHAR(ROWID) ENAME           EMPNO

------------------ ---------- ----------

AAAQ+jAAEAAAAAeAAA SMITH            7369

AAAQ+jAAEAAAAAeAAB ALLEN            7499

AAAQ+jAAEAAAAAeAAC WARD             7521

AAAQ+jAAEAAAAAeAAD JONES            7566

AAAQ+jAAEAAAAAeAAE MARTIN           7654

AAAQ+jAAEAAAAAeAAF BLAKE            7698



ROWID:物理ROWID和逻辑ROWID

  物理:标识普通数据表中的一行信息   逻辑:能够标识索引组织表中的一行信息


UROWID 可以存储 物理  逻辑  以及非 oracle 的ROWID  


ROWID 可以显著的加速数据检索的性能。只要行存在 物理ROWID 值就不会改变。


declare

v_empname ROWID;

v_othersname VARCHAR(18);

begin

select ROWID into v_empname from emp where empno=&empno;

dbms_output.put_line(v_empname);

v_othersname:=ROWIDTOCHAR(v_empname);

dbms_output.put_line(v_othersname);

end;


数字类型 NUMBER:精度:所允许的的总长度 刻度:小数点右边多少位 如果为负值 及小数点左边多少位


指定刻度超过 四舍五入



v_num NUMBER(4,-1):=31451      41450

v_num NUMBER(4.3):= 3.1415926  3.142


用来存储符号整型值 PLS_INTEGER   BINARY_INTEGER

PLS_INTEGER 相对于NUMBER 来说需要更少的内存 来存储数据而且在计算方面比NUMBER更有效率


NUMBER数据类型是以十进制格式进行存储的 为了进行数学运算 需要转换成二进制 所以速度会慢。


PLS_INTEGER 和 BINARY_INTEGER  都是以2的补码格式进行计算的  PLS_INTEGER 在溢出时会触发异常报错   而 BINARY_INTEGER 会转换成NUMBER  不会报错。


SQL> select sessiontimezone from dual;


SESSIONTIMEZONE

---------------------------------------

+08:00


获得当前时区


12-9-2

INTERVAL 类型 

INTERVAL YEAR TO MONTH  用来存储和操纵年和月之间的时间间隔

INTERVAL DAY TO SECOND  用来存储和操纵天数,小时,分钟和秒之间的时间间隔。


declare

v_start timestamp;

v_end timestamp;

v_interval interval year to month;

v_year number;

v_month number;

begin

v_start := TO_TIMESTAMP('2010-05-12','YYYY-MM-dd');

v_end := CURRENT_TIMESTAMP;

v_interval := (v_end - v_start) YEAR TO MONTH;

v_year := EXTRACT(YEAR FROM v_interval);

v_month := EXTRACT(MONTH FROM v_interval);

dbms_output.put_line('当前的interval值为:' || v_interval);

dbms_output.put_line('INTERVAL年份为:' || v_year || CHR(13)||CHR(10)|| 'INTERVAL月份为:'|| v_month );

v_interval := INTERVAL '01-03' YEAR TO MONTH;

dbms_output.put_line('当前INTERVAL值为:' || v_interval);

v_interval := INTERVAL '01' YEAR;

dbms_output.put_line('当前的INTERVAL值为:' || v_interval);

v_year := EXTRACT(YEAR FROM v_interval);

v_month := EXTRACT(MONTH FROM v_interval);

dbms_output.put_line('INTERVAL年份为' || v_year || CHR(13)|| CHR(10)||'INTERVAL月份为:'|| v_month );

v_interval := INTERVAL '03' MONTH;

dbms_output.put_line('当前的INTERVAL的值为:' || v_interval);

end;


结果:

当前的interval值为:+04-07

INTERVAL年份为:4

INTERVAL月份为:7

当前INTERVAL值为:+01-03

当前的INTERVAL值为:+01-00

INTERVAL年份为1

INTERVAL月份为:0

当前的INTERVAL的值为:+00-03



引用类型

1.REF CURSOR 类型的变量通常称为游标变量

create or replace function selectallemployments

return sys_refcursor

as

st_cursor sys_refcursor;

begin

open st_cursor for select * from emp;

return st_cursor;

end;


declare

x sys_refcursor;

v_emp emp%ROWTYPE;

begin

x := selectallemployments;

loop

fetch x

into v_emp;

exit when x%NOTFOUND;

dbms_output.put_line('员工编号:' || v_emp.empno || '员工名称:' || v_emp.ename);

end loop;

end;


用户自定义类型

引用游标使用示例

declare

subtype empcounttype is integer;

empcount empcounttype;

begin

select count(*) into empcount from emp;

dbms_output.put_line('员工人数为:' ||  empcount);

end;



使用%TYPE


declare

TYPE empnamelist is table of varchar2(20);

subtype namelist is empnamelist;

type emprec is record(

empno number(4),

ename varchar2(20)

);

subtype emprecord is emprec;

subtype empno is emp.empno%TYPE;

subtype emprow is emp%ROWTYPE;

begin

null;

end;


子类型具有的优势:

1.可以检查数值是否越界,这样可以提高应用程序的可靠性。例如如果想要让某个数字类型在0~9这个范围之间,可以基于NUMBER类型定义一个子类型,这样在赋值时,如果数据溢出,编译器会弹出错误提示


declare

subtype numtype is number(1,0);

x_value numtype;

y_value numtype;

begin

x_value := 3;

y_value := 10;              因为10 报错  精度太高

end;


2.未约束的子类型可以和它的基本类型交互使用

declare

subtype numtype is number;

x_value number;

y_value numtype;

begin

x_value:= 10;

y_value := x_value;

end;

3.如果基类相同 那么子类型可以交互使用

declare

subtype numtype is varchar2(200);

x_value varchar2(20);

y_value numtype;

begin

x_value:='This is a word';

y_value:=x_value;

end;



12-10  数据类型转换  

显示转换

declare

v_startdate DATE;

v_enddate DATE;

v_resultdate NUMBER;

begin

v_startdate:=TO_DATE('2007-10-11','yyyy-MM-dd');

v_enddate:=TRUNC(SYSDATE);

v_resultdate:=v_enddate-v_startdate;

dbms_output.put_line('起始日期:' 

|| TO_CHAR(v_startdate,'yyyy-MM-dd') 

|| CHR(13)

||CHR(10)

||'结束日期:'

||TO_CHAR(v_enddate,'yyyy-MM-dd')

||CHR(13)

||CHR(10)

||'相差天数:'

||TO_CHAR(v_resultdate));

end;


隐示转换

declare

v_startdate char(10);

v_enddate char(10);

v_result NUMBER(5);

begin

select min(hiredate) into v_startdate from emp;

select trunc(sysdate) into v_enddate from dual;

dbms_output.put_line('起始日期:'

|| v_startdate

|| CHR(13)

|| CHR(10)

|| '结束日期:'

|| v_enddate );

v_startdate:='200';

v_enddate:='400';

v_result:=v_enddate-v_startdate;

end;


表达式

declare

v_sal NUMBER;

v_result NUMBER;

begin

select sal into v_sal from emp where empno=&empno;

v_result:=v_sal * (1+0.15);

end;


运算符类型

赋值运算符,连接运算符,逻辑运算符,比较运算符。


PLSQL中一个左值仅能有一个右值  val1:=val2:=val3:=val4=0  这样是错误的


连接运算符

declare

x varchar2(8):='你好';

y varchar2(8):='中国';

z varchar2(10);

begin

dbms_output.put_line(x || z || NULL || y);

end;

执行结果   因为z没有赋值 所以是一个null   连接一个null   2个就都不显示

SQL> declare

  2     x varchar2(8):='你好';

  3     y varchar2(8):='中国';

  4     z varchar2(10);

  5  begin

  6     dbms_output.put_line(x || z || NULL || y);

  7  end;

  8  /

你好中国


PL/SQL 过程已成功完成。