ORACLE数据库管理员基础
第十章 其它一些常见问题及技巧
下面给出一些对于初学者来是常见问题的一点描述,目的是使那些使用Oracle 系统时间不长 的人员能尽快适应在Oracle 环境下的开发。 10.1 一些常见问题
下面是一些初学者常遇到的问题的解释。如果你是一位Oracle 的老手可以不阅读本章的 内容。
10.1.1 Oracle 与2000 年问题 oracle 约定
oracle 在系统中一直用YYYY:MM:DD HH24:MI:SS 表示日期和时间 ORACLE7 server 和ORACLE8 server 提供一种年格式掩码RR 规则转换如下表:
当前年度(最后两位数) 指定的两位数年 (机器设置为) RR 返回的年 0~49 0~49 50~99 0~49 0~49 50~99 50~99 50~99 当前世纪(19XX) 下个世纪(20XX) 上个世纪(18XX) 当前世纪(19XX)
当前年是在 50~99 后半世纪
1)如果输入00 和99 之间,oracle 将被记为下个世纪,如在1996 年输02,则被记为2002 年。
2)如果输入50 和99 之间,oracle 将被记为当前世纪,如在1996 年输97,则被记为1997 年。
当前年是在 00~49 前半世纪
1)如果输入00 和49 之间,oracle 将被记为当前世纪,如在2001 年时输02,则被记为2002 年。 205
2)如果输入的两位年在50 和99 之间,oracle 将被记为上个世纪,如在2001 年输97,则被 记为1997 年。 例子
Create table abc(datefld date) Insert into abcValue('01-JAN-11'); Insert into abcValue('01-JAN-90'); 转换成1911 年和1990 年 Update abc
Set Datefld(d=To_date(To_datefld,'DD-MON-YY HH24:MI:SS'), 'DD_MON_RR HH24:MI:SS');
Select To_char(Datefld,'DD-MON-YYYY') Datefld from abc; 01-JAN-2011 01-JAN-1990
建议:2000 年问题在开发中的建议任何时应采用4 位年表示如果用两位一定用YY 或RR 表示 输入界面最好作判断和提示。
10.1.2 如何正确插入日期数据
许多初学者都可能遇到这样的问题,就是往DATE 类型的列插入日期数据时,经常被提 示错误。
比如有下面的 ABC 表结构: SQL>descabc 名称 空? 类型
----------------------------------------- -------- ------------ RQ DATE
NAME VARCHAR2(20)
当用下面命令插入数据到 ABC 表时,系统提示如下信息: SQL> insert into abc values('02-JAN-2002','赵元杰'); insert into abc values('02-JAN-2002','赵元杰') *
ERROR 位于第 1 行: ORA-01843: 无效的月份
这是由于系统安装时的默认字符集引起的。虽然上面语句看上去没有错误,但是它不符合当 206
前系统的日期格式要求。那么当前系统的日期格式是什么呢?我们可以用下面语句来查询: SQL> select sysdate from dual; SYSDATE ---------- 01-2 月 -02
既然系统的日期格式是中文的月份,则将上面语句改为中文的月即可: SQL> insert into abc values('02-2 月-2002','赵元杰');
已创建 1 行。
当然,你可以用alter session 命令修改当前系统的日期格式为你喜欢的格式,如: SQL> alter session set nls_date_format='yyyy/mm/dd'; 会话已更改。
SQL> insert into abc values('2002/02/02','赵元杰'); 已创建 1 行。
SQL> select * from abc; RQ NAME
---------- -------------------- 2002/02/02 赵元杰 2002/02/02 赵元杰
关于日期格式的有关资料,请参见《Oracle8I 数据库管理员》--赵元杰著 10.1.3 在查询中只返回满足条件的部分记录
有时,我们关心的查询结果不是所有的记录,而是关心所查询的内容的存在性。如果 我们不加特别的限制,满足条件的所有记录会源源不断地显示在屏幕上。为了只显示少量的 内容,oracle 提供rownum伪列来限制在查询时返回的记录数。例如: Select * from dict where rownum< 10 Rownum 是要显示的记录数 207 注意:
该用法在 PL/SQL 和Pro*C 中常常不能用 ; 在条件中可以用 <= ,但不能用 = 或 > 作判断。 10.1.4 快速大量删除数据Truncate
在数据库管理操作中,经常需要将某个表的所有记录都删除而只保留表结构,这样的要求如
果用delete 进行删除的话,Oracle 系统会自动为该操作分配回滚段。如果回滚段较小,则 可能导致操作失败。即使回滚段足够大,删除操作也需要较长的时间才能完成。为了加快删 除操作,Oracle 提供了一个特别的命令TRUNCATE,可以快速地完成对某个表的所有记录的删 除。TRUNCATE 的语法如下: TRUNCATE [TABLE | CLUSTER]
schema.[table][cluster] [DROP | REUSE STORAGE]
删除表中或簇中的所有行,REUSE STORAGE 保留被删除的空间作为该表的新行使用:缺省 为DROP storge 即收回被删除的空间给系统。
特点:不可恢复。即不需rollback segment,不在日志文件中记录信息。 10.1.5 Rowid 的使用
oracle 为每个表的每一条记录赋予一个唯一的标识号rowid; 它是一个伪列,虽然在定义表结构时并不声明它,但它自动地建立; 用 desc 查看表结构时并不显示该字段;
ROWID 在进行UPDATE 或DELETE 操作中速度最快; Oracle7 和Oracle8 的ROWID 不同。
SQL>select name,sex,sal,rowid from emp;
SQL>delete from emp where rowid='...XXXX.XX.XXXX'; Oracle7 的Rowid 由三个部分组成,结构为: block.row.file 格式为:
BBBBBBBB.RRRR.FFFF
BBBBBBBB 是文件的块号;RRRR 块中的行号;FFFF 是文件的绝对号。 例0000000F.0000.00002
第15 数据块.第1 行.第二个数据文件