ssplyh 发表于 2018-10-23 08:27:48

PL/SQL变量与类型

  变量的作用域:   变量可以使用的程序单元部分
  可见性: 当一个变量在它的作用域中可以用一个不限定的名字来引用时
  1.CONSTANT声明一个常量
  2.NOT NULL 约束变量不能为空
  3.:=value 用于为变量附初始值
  例如
  v_name DATE NOT NULL := SYSDATE
  v_name INTNOT 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
  
  declare
  v_empname varchar2(20);
  begin
  v_empname:='张三';
  
  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_empnameROWID;
  v_othersnameVARCHAR(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.14159263.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_starttimestamp;
  v_end timestamp;
  v_interval interval year to month;
  v_year number;
  v_monthnumber;
  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
  xsys_refcursor;
  v_empemp%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_startdateDATE;
  v_enddateDATE;
  v_resultdateNUMBER;
  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_startdatechar(10);
  v_enddatechar(10);
  v_resultNUMBER(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_salNUMBER;
  v_resultNUMBER;
  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);
  5begin
  6   dbms_output.put_line(x || z || NULL || y);
  7end;
  8/
  你好中国
  PL/SQL 过程已成功完成。

页: [1]
查看完整版本: PL/SQL变量与类型