上海网络平台网站建设网络服务提供者知道或者应当知道
不吐不快:
本来以为清华大学出版的书,质量上应该没的说,但是,通过调试示例程序,还是发现不少问题:
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,意为赋值时小数点的移动位数,正数表示向右移动;负数表示向左移动
DECLAREv_num1 NUMBER:=3.1415926; --结果:3.1415926v_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.927v_num5 NUMBER(4,-3):=3145611.789; --由于为负3,要小数点左侧进行舍入3位结果为3146000v_num5_1 NUMBER(4,-3):=314.567895; --舍入后的结果为0v_num6 NUMBER(4,-1):=31451; --舍入后结果31450 v_num6_1 NUMBER(4,-1):=3145123; --错误,精度太高:ORA-06502:PL/SQL:数字或值错误:数值精度太高
BEGINDBMS_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的使用示例
DECLAREv_num1 PLS_INTEGER :=2147483647;
BEGIN--当为v_num1+1时,产生了溢出,会触发异常v_num1:=v_num1+1-1;EXCEPTIONWHEN OTHERS THEN--输出:ORA-01426: 数字溢出DBMS_OUTPUT.put_line(SQLERRM);
END;--BINARY_INTEGER使用示例
--实际调试结果:会产生编译错误
DECLAREv_num1 BINARY_INTEGER :=2147483647;
BEGIN --以下论述与实际调试结果不符:--当为v_num1+1时,产生了溢出,--此时v_num1会被当作NUMBER进行处理,不会触发异常v_num1:=v_num1+1-1;EXCEPTIONWHEN 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.
DECLAREv_weekday DATE := trunc(SYSDATE) - to_char(SYSDATE, 'D') + 1;v_now DATE := SYSDATE;
BEGINdbms_output.put_line('上个星期天的日期为:'||to_char(v_weekday, 'yyyy-mm-dd'));dbms_output.put_line('当前时间:'||to_char(v_now, 'yyyy-mm-dd hh24:mi:ss'));
END;--代码3.14 TIMESTAMP类型使用示例
DECLAREv_now TIMESTAMP(8) := SYSDATE;v_nowdate DATE := SYSDATE;
BEGINdbms_output.put_line(v_now);dbms_output.put_line(v_nowdate);
END;--代码3.15 TIMESTATMP WITH TIME ZONE类型使用示例
DECLAREv_timestamp TIMESTAMP; --定义日期类型的变量v_timestampwithzone TIMESTAMP WITH TIME ZONE;v_timestampwithlocalzone TIMESTAMP WITH LOCAL TIME ZONE;
BEGINv_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类型使用示例
DECLAREv_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;
BEGINv_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 布尔类型使用示例
DECLAREv_condition BOOLEAN;
BEGINv_condition := TRUE;-- v_condition := 'FALSE';IF v_conditionTHENdbms_output.put_line('布尔值为True');END IF;
END;--代码3.18 弱类型REF CURSOR使用示例
CREATE OR REPLACE FUNCTION selectallemploymentsRETURN sys_refcursor --定义一个返回sys_refcursor的函数
ASst_cursor sys_refcursor;
BEGINOPEN st_cursor FOR --使用该函数查询所有的员工记录SELECT *FROM emp;--返回指向游标的指针RETURN st_cursor;
END;--代码3.19 使用引用游标示例
DECLAREx sys_refcursor; --定义引用游标变量v_emp emp%ROWTYPE; --定义获取游标结果的记录类型
BEGINx := selectallemployments;--调用函数获取游标指针--循环遍历游标指针LOOPFETCH x --提取游标数据INTO v_emp;--当没有找到游标记录时则退出EXIT WHEN x%NOTFOUND;--输出记录信息DBMS_OUTPUT.put_line ( '员工编号:'|| v_emp.empno|| ' 员工名称:'|| v_emp.ename);END LOOP;
END;--代码3.20 用户自定义类型示例
DECLARESUBTYPE empcounttype IS INTEGER;empcount empcounttype;
BEGINSELECT COUNT(*)INTO empcountFROM emp;dbms_output.put_line('员工人数为:' || empcount);
END;