数据库

位置:IT落伍者 >> 数据库 >> 浏览文章

Oracle FAQ 2003.02精华


发布日期:2018年12月11日
 
Oracle FAQ 2003.02精华

Q: 如何使用NID来更改数据库名称?

A:

在Oraclei二版以前要想更改数据库名称我们必须重建控制文件具体更改过程参见我网站上的文章

在Oraclei二版中我们可以使用一个新的工具NID来完成这个任务值得一体的是这个工具同时还可以修改同一主机上低版本的数据库名称

下面是将现有数据库更名为gototop的详细过程

Shutdown database

Startup mount

$ nid target=/ dbname=gototop

Shutdown database

Change initora/spfile name ie: initgototopora

Change db_name parameter in initora/spfile ie: db_name=gototop

Change ORACLE_SID to point to new database name (如果没有做这一步同样可以不做)

Startup mount

Alter database open resetlogs

Take a backup

和很多情况类似对数据库的修改都需要在EXCLUSIVELY模式下进行如果试运行在RAC环境中则会出现下面的错误提示

NID: Database should be mounted exclusively

解决方法也很简单可以先注释掉相关RAC的参数

Q: 如何将数字转换成大写?

A:

SQL> select to_char(to_date(J)JSP) from dual;

TO_CHAR(TO_DATE(J)JSP)

ONE MILLION TWO HUNDRED THIRTYFOUR THOUSAND FIVE HUNDRED SIXTYSEVEN

这是英文的大写可以实现从之间数字的转换中文大写我们可以通过下面的两个函数来实现

CREATE OR REPLACE FUNCTION ZH(N NUMBER) RETURN CHAR AS

T VARCHAR():=零壹贰三肆伍陆柒捌玖;

BEGIN

RETURN SUBSTR(TN+);

END;

/

CREATE OR REPLACE FUNCTION DX(N NUMBER) RETURN VARCHAR AS

B VARCHAR():=拾万千百拾元角分;

C VARCHAR();

G VARCHAR();

BEGIN

C:=REPLACE(LPAD(LTRIM(TO_CHAR(N))));

FOR I IN LOOP

G:=G||ZH(SUBSTR(CI))||SUBSTR(BI);

END LOOP;

RETURN G;

END;

/

Q:如何确定当前的Oracle版本?

A:

当一个系统中安装有多个版本的ORACLE时可以按照下面的方法来确定当前的Oracle版本

比较/etc/oratab与$ORACLE_HOME环境变量

进入ORACLE数据库中执行SELECT * FROM V$INSTANCE;

Q:如何知道hidden参数的含义?

A:

在initora中有时会用到类似下面以_开头的hidden参数

_corrupted_rollback_segments=(rrrr)

_allow_resetlogs_corruption=ture

这些参数一般都是由oracle support建议才会使用的没有公布这方面的文档我们可以通过下面的语句看到一些解释

select * from X$KSPPI where KSPPINM=_corrupted_rollback_segments;

select * from X$KSPPI where KSPPINM=_allow_resetlogs_corruption;

Q:如何使用rownum进行分页?

A:

下面是我们单位开发人员提出的分页方法

更为简单清晰的ORACLE分页SQL

select * from t_xxx where rownum < minus select * from t_xxx where rownum < 101”

下面是我的回复:

这样的SQL是令人担忧的!

原因基于两点:

1、我们知道rownum是oracle输出结果中的虚行,即在实际的表中并没有相应的存储结构存在;

2、minus运算是在两次操作结果的基础上进行的,因此在非不得不的情况下,我们一贯主张避免使用类似的操作;

由此可以看出楼主提出的SQL:

select * from t_xxx where rownum < 201 minus select * from t_xxx where rownum < 101;

为了取出100条纪录实际上执行了两次SELECT共300条纪录,举个简单的例子,如果共1000条纪录,分页为100条,那么全部SELECT总数据量是

100+(200+100)+(300+200)+。Tw.WInGwiT.CoM。。

共是10000条,整整是10倍的数据量!如果是几万、几十万的数量级,再加上实际操作中的ORDER BY以及相关的WHERE条件,更不敢想象这样SQL的效率。

在实际中针对分页比较典型的做法是:

select * from

( select rownum rnm, a.* from

( select * from t where name=&myname order by name,dept) a

where rownum <= &maxrnm )

where rnm >= &minrnm ;

这里有三个变量:

&myname where条件

&maxrnm要查询的最大行号

&minrnm要查询的最小行号

使用这样的SQL在8i以后ORACLE是使用专门的优化来处理的,它需要排序字段预先建有索引,由于索引是已排序好的结构,因此取TOP n的问题,就变为从索引中直接从头提取n个索引关键字,然后再根据索引就可快速的找到记录并返回给用户。从而有效避免了检索全部记录的情况。

按分页计算,如果用户很少浏览后面页面的数据使用上面的SQL效率是很好,否则到某一刻index range scan所有满足条件记录时带来的高成本,CBO甚至认为它高于FULL TABLE SCAN而选择FULL TABLE SCAN。为了避免这一情况,针对经常需要浏览后面分页数据的用户,可以使用下面的SQL来处理:

select * from t where rowid in

( select rid from

( select rownum rno,rowid rid from

( select rowid from t where name = &myname order by name,dept )

where rownum <= &maxrnm )

where rno >= &minrnm )

;

在这一方法中,我们考虑到索引与表相比,数据量大大小于后者,因此我们试图先在索引中搜索出某页记录的物理位置,然后根据这些物理位置(rowid)在表中直接取出相应的记录,这将有利消除上述FULL TABLE SCAN的出现。

当然二者之间的选择要看我们的实际应用以及我们INDEX的情况,以便更好地提高效率。

另外一种做法在ORACLE8.1.6之后可以使用row_number() over()函数来实现:

select * from

(SELECT owner,table_name,row_number() OVER(ORDER BY table_name) rownumber FROM dba_tables)

where rownumber >= 100 and rownumber <= 200;

5.Q: EXP with compress=y是不是总有好处?

A:

在使用EXP时,很多人不分情形,总喜欢使用COMPRESS=Y参数,其实这一种错误的做法。

导出选项COMPRESS=Y 将生成创建初始EXTENT的代码,该初始EXTENT大小等于当前分

配给对象的所有EXTENT的总大小,如果对象上有很多已删除的行或者如果上一个EXTENT有很多未使用的块,这将不必要地分配给对象很多空间。

另外在使用EXP还有以下几点需要注意:

1、可以将常用命令行选项写在参数文件中;

2、仅在小数据量的情况下使用CONSISTENT=Y参数;

3、分配尽量大的BUFFER并使用DIRECT=Y参数。

6.Q: ORACLE常用的数据类型有哪些?

A:

之所以把这个问题也放在这里,是想为使用时提供一个参考:

字段类型 中文说明 限制条件 其它说明

CHAR 固定长度字符串 最大长度2000 bytes

VARCHAR2 可变长度的字符串 最大长度4000 bytes 可做索引的最大长度749

NCHAR 根据字符集而定的固定长度字符串 最大长度2000 bytes

NVARCHAR2 根据字符集而定的可变长度字符串 最大长度4000 bytes

DATE 日期(日-月-年) DD-MM-YY(HH-MI-SS) 经过严格测试,无千虫问题

LONG 超长字符串 最大长度2G(231-1) 足够存储大部头着作

RAW 固定长度的二进制数据 最大长度2000 bytes 可存放多媒体图象声音等

LONG RAW 可变长度的二进制数据 最大长度2G 同上

BLOB 二进制数据 最大长度4G

CLOB 字符数据 最大长度4G

NCLOB 根据字符集而定的字符数据 最大长度4G

BFILE 存放在数据库外的二进制数据 最大长度4G

ROWID 数据表中记录的唯一行号 10 bytes ********.****.****格式,*为0或1

NROWID 二进制数据表中记录的唯一行号 最大长度4000 bytes

NUMBER(P,S) 数字类型 P为整数位,S为小数位

DECIMAL(P,S) 数字类型 P为整数位,S为小数位

INTEGER 整数类型 小的整数

FLOAT 浮点数类型 NUMBER(38),双精度

REAL 实数类型 NUMBER(63),精度更高

上一篇:Oracle认证:巧取Oracle指定记录

下一篇:OracleForm属性、内置子程序、触发器等(1)