2分六合

IT技术互动交流平台

源码PL/SQL从入门到精通第三章变量和类型Part2

来源:IT165收集  发布日期:2016-07-14 22:04:40

不吐不快:

本来以为清华大学出版的书,质量上应该没的说,但是,通过调试示例程序,还是发现不少问题:

1. 个别概念解释不清,容易误导读者

2. 有些文字词不达意,不准确

3。 代码解释中有错别字,有的代码标题张冠李戴

之前说过的问题就不提了。总之,目前看到的最好的教材还是Java how to program,堪称完美!

代码如下:

 

--代码3.11 NUMBER类型声明示例
--说明:根据调试结果,基本可以确认Number(precesion,scale)中的precesion(精度)是指有效数字的位数,而不能简单理解为数字的长度。
--如,v_num6 NUMBER(4,-1):=31451;输出结果为31450,数字长度为5,而不是4(31450=3.145*10^1,科学计数法中的有效数字个数)。
--而另一参数-scale,意为赋值时小数点的移动位数,正数表示向右移动;负数表示向左移动
DECLARE
   v_num1 NUMBER:=3.1415926;           --结果:3.1415926
   v_num2 NUMBER(3):=3.1415926;        --四舍五入等于3
 --v_num2_1 NUMBER(3):=3145.1415926;   --错误,精度太高:ORA-06502:PL/SQL:数字或值错误:数值精度太高   
   v_num3 NUMBER(4,3):=3.1415926;      --结果:3.142
 --v_num3_1 NUMBER(4,3):=314.123;      --错误,精度太高:ORA-06502:PL/SQL:数字或值错误:数值精度太高   
   v_num4 NUMBER(8,3):=31415.9267;     --四舍五入3位小数,结果为:31415.927
   v_num5 NUMBER(4,-3):=3145611.789;   --由于为负3,要小数点左侧进行舍入3位结果为3146000
   v_num5_1 NUMBER(4,-3):=314.567895;  --舍入后的结果为0
   v_num6 NUMBER(4,-1):=31451;         --舍入后结果31450  
   v_num6_1 NUMBER(4,-1):=3145123;     --错误,精度太高:ORA-06502:PL/SQL:数字或值错误:数值精度太高   
BEGIN
  DBMS_OUTPUT.put_line('v_num1:='||v_num1);
  DBMS_OUTPUT.put_line('v_num2:='||v_num2);
  DBMS_OUTPUT.put_line('v_num3:='||v_num3);
  DBMS_OUTPUT.put_line('v_num4:='||v_num4);      
  DBMS_OUTPUT.put_line('v_num5:='||v_num5);    
  DBMS_OUTPUT.put_line('v_num5_1:='||v_num5_1);  
  DBMS_OUTPUT.put_line('v_num6:='||v_num6);   
 -- DBMS_OUTPUT.put_line('v_num6_1:='||v_num6);         
END; 

--代码3.12 PLS_INTEGER与BINARY_INTEGER的使用示例
DECLARE
   v_num1 PLS_INTEGER :=2147483647;   
BEGIN
   --当为v_num1+1时,产生了溢出,会触发异常
   v_num1:=v_num1+1-1;
   EXCEPTION
     WHEN OTHERS THEN
       --输出:ORA-01426: 数字溢出
       DBMS_OUTPUT.put_line(SQLERRM);
END;


--BINARY_INTEGER使用示例 
--实际调试结果:会产生编译错误
DECLARE
   v_num1 BINARY_INTEGER :=2147483647;
BEGIN   
   --以下论述与实际调试结果不符:
   --当为v_num1+1时,产生了溢出,
   --此时v_num1会被当作NUMBER进行处理,不会触发异常
   
   v_num1:=v_num1+1-1;
      EXCEPTION
     WHEN OTHERS THEN
       --输出:ORA-01426: 数字溢出
       DBMS_OUTPUT.put_line(SQLERRM);
END;

select power(2,8) from dual;
select * from product_component_version;
select * from v$instance;
select * from V$VERSION

--代码3.13 Date类型使用示例
--to_char函数中的'D'的含义,当前日期在本周中的天数序号,星期日为第一天(这个可不符合中国人的习惯啊?
--Day of week (1-7). This element depends on the NLS territory of the session.
DECLARE
  v_weekday DATE := trunc(SYSDATE) - to_char(SYSDATE, 'D') + 1;
  v_now     DATE := SYSDATE;
BEGIN
  dbms_output.put_line('上个星期天的日期为:'||to_char(v_weekday, 'yyyy-mm-dd'));
  dbms_output.put_line('当前时间:'||to_char(v_now, 'yyyy-mm-dd hh44:mi:ss'));
END;


--代码3.14 TIMESTAMP类型使用示例
DECLARE
  v_now TIMESTAMP(8) := SYSDATE;
  v_nowdate DATE := SYSDATE;
BEGIN
  dbms_output.put_line(v_now);
  dbms_output.put_line(v_nowdate);
END;


--代码3.15 TIMESTATMP WITH TIME ZONE类型使用示例
DECLARE
   v_timestamp           TIMESTAMP;                      --定义日期类型的变量
   v_timestampwithzone   TIMESTAMP WITH TIME ZONE;
   v_timestampwithlocalzone   TIMESTAMP WITH LOCAL TIME ZONE;
BEGIN
   v_timestamp := SYSDATE;                           --为日期类型的变量赋初值
   v_timestampwithzone := SYSDATE;
   v_timestampwithlocalzone :=SYSDATE;
   DBMS_OUTPUT.put_line (v_timestamp);                             --输出信息
   DBMS_OUTPUT.put_line (v_timestampwithzone);
   DBMS_OUTPUT.put_line ( v_timestampwithlocalzone);  --和timestamp的输出相同
END;

--INTERVAL YEAR TO MONTH类型使用示例
DECLARE
  v_start    TIMESTAMP; --定义起始与结束时间戳类型
  v_end      TIMESTAMP;
  v_interval INTERVAL YEAR TO MONTH;
  v_year     NUMBER;
  v_month    NUMBER;
  v_date     DATE;
  v_uinterv  interval YEAR TO MONTH;
BEGIN
  v_start    := TO_TIMESTAMP('&v_date', 'yyyy-MM-dd'); --赋指定的时间戳值(此处优化了代码,允许用户任意输入一个日期(年月日,如2015-08-03))
  v_end      := CURRENT_TIMESTAMP; --赋当前的时间戳值
  v_interval := (v_end - v_start) YEAR TO MONTH; --YEAR TO MONTH是INTERVAL表达式语法。
  v_year     := EXTRACT(YEAR FROM v_interval); --提取年份和月份
  v_month    := EXTRACT(MONTH FROM v_interval);
  --输出当前的INTERVAL类型的值
  DBMS_OUTPUT.put_line(to_char(v_start, 'yyyy-mm-dd') || '与当前时间的间隔INTERVAL值为:' ||
                       v_interval);
  --输出年份与月份值
  DBMS_OUTPUT.put_line('INTERVAL年份为:' || v_year || CHR(13) || CHR(10) ||
                       'INTERVAL月份为:' || v_month);
 --直接为INTERVAL赋值
--此处增强代码,允许用户任意输入一个间隔(年月,如10年8个月,10-08),并计算经过该间隔定义的年月后的日期,
--如,17年后,您的孩子上大学时,是哪一年呢??
--彩蛋:如何在英文输入法下,输入笑脸?
--答案:1.打开Numlock开关(即小键盘/数字区)
--2. 按住Alt的同时,在小键盘区域连续输入9786,?就会出现*                 
  v_interval := INTERVAL '&v_uinterv' YEAR TO MONTH; 
  --输出INTERVAL的值
  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(v_year||'年'||v_month||'月后的日期为:'||to_char((sysdate+v_interval),'yyyy-mm-dd'));
  v_interval := INTERVAL '01' YEAR; --直接为INTERVAL赋年份值
  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; --直接为INTERVAL赋月份
  --输出月份值
  DBMS_OUTPUT.put_line('当前的INTERVAL值为:' || v_interval);
END;

--代码 3.17 布尔类型使用示例
DECLARE
  v_condition BOOLEAN;
BEGIN
  v_condition := TRUE;
  -- v_condition := 'FALSE';
  IF v_condition
  THEN
    dbms_output.put_line('布尔值为True');
  END IF;
END;

--代码3.18 弱类型REF CURSOR使用示例
CREATE OR REPLACE FUNCTION selectallemployments
   RETURN sys_refcursor           --定义一个返回sys_refcursor的函数
AS
   st_cursor   sys_refcursor;
BEGIN
   OPEN st_cursor FOR             --使用该函数查询所有的员工记录
      SELECT *
        FROM emp;
   --返回指向游标的指针
   RETURN st_cursor;
END;


--代码3.19 使用引用游标示例
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;


--代码3.20 用户自定义类型示例
DECLARE
  SUBTYPE empcounttype IS INTEGER;
  empcount empcounttype;
BEGIN
  SELECT COUNT(*)
  INTO   empcount
  FROM   emp;
  dbms_output.put_line('员工人数为:' || empcount);
END;

 

Tag标签:         
  • 专题推荐

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规