ORACLE之常用FAQ

 

ORACLE之常用FAQ V1.0
第一部分、 SQL&PL/SQL
##########[Q]
么样查询 特殊字符,如通配符 % _
**********[A]select * from table where name like 'A/_%' escape '/'

##########[Q]
如何插入 引号到数据 表中
**********[A]
可以用 ASCII 码处 理,其它特殊字符如 & 也一 ,如
insert into t values('i'||chr(39)||'m'); -- chr(39)
代表字符 '
或者用两个 引号表示一个
or insert into t values('I''m'); --
两个 '' 可以表示一个 '

##########[Q]
样设 置事 一致性
**********[A]set transaction [isolation level] read committed;
认语 一致性
set transaction [isolation level] serializable;
read only;
务级 一致性

##########[Q]
么样 利用游 更新数据
**********[A]cursor c1 is
select * from tablename
where name is null for update [of column]
……
update tablename set column = ……
where current of c1;

##########[Q]
自定 异常
**********[A] pragma_exception_init(exception_name,error_number);
如果立即抛出异常
raise_application_error(error_number,error_msg,true|false);
其中 number -20000 -20999 错误 信息最 2048B
异常
SQLCODE
错误
SQLERRM
错误 信息

##########[Q]
制与十六 制的 转换
**********[A]8i
以上版本:
to_char(100,'XX')
to_number('4D','XX')
8i
以下的 制之 转换 参考如下脚本
create or replace function to_base( p_dec in number, p_base in number )
return varchar2
is
l_str varchar2(255) default NULL;
l_num number default p_dec;
l_hex varchar2(16) default '0123456789ABCDEF';
begin
if ( p_dec is null or p_base is null ) then
return null;
end if;
if ( trunc(p_dec) <> p_dec OR p_dec < 0 ) then
raise PROGRAM_ERROR;
end if;
loop
l_str := substr( l_hex, mod(l_num,p_base)+1, 1 ) || l_str;
l_num := trunc( l_num/p_base );
exit when ( l_num = 0 );
end loop;
return l_str;
end to_base;
/
create or replace function to_dec
( p_str in varchar2,
p_from_base in number default 16 ) return number
is
l_num number default 0;
l_hex varchar2(16) default '0123456789ABCDEF';
begin
if ( p_str is null or p_from_base is null ) then
return null;
end if;
for i in 1 .. length(p_str) loop
l_num := l_num * p_from_base + instr(l_hex,upper(substr(p_str,i,1)))-1;
end loop;
return l_num;
end to_dec;
/

##########[Q]
能不能介 SYS_CONTEXT 详细 用法
**********[A]
利用以下的 查询 ,你就明白了
select
SYS_CONTEXT('USERENV','TERMINAL') terminal,
SYS_CONTEXT('USERENV','LANGUAGE') language,
SYS_CONTEXT('USERENV','SESSIONID') sessionid,
SYS_CONTEXT('USERENV','INSTANCE') instance,
SYS_CONTEXT('USERENV','ENTRYID') entryid,
SYS_CONTEXT('USERENV','ISDBA') isdba,
SYS_CONTEXT('USERENV','NLS_TERRITORY') nls_territory,
SYS_CONTEXT('USERENV','NLS_CURRENCY') nls_currency,
SYS_CONTEXT('USERENV','NLS_CALENDAR') nls_calendar,
SYS_CONTEXT('USERENV','NLS_DATE_FORMAT') nls_date_format,
SYS_CONTEXT('USERENV','NLS_DATE_LANGUAGE') nls_date_language,
SYS_CONTEXT('USERENV','NLS_SORT') nls_sort,
SYS_CONTEXT('USERENV','CURRENT_USER') current_user,
SYS_CONTEXT('USERENV','CURRENT_USERID') current_userid,
SYS_CONTEXT('USERENV','SESSION_USER') session_user,
SYS_CONTEXT('USERENV','SESSION_USERID') session_userid,
SYS_CONTEXT('USERENV','PROXY_USER') proxy_user,
SYS_CONTEXT('USERENV','PROXY_USERID') proxy_userid,
SYS_CONTEXT('USERENV','DB_DOMAIN') db_domain,
SYS_CONTEXT('USERENV','DB_NAME') db_name,
SYS_CONTEXT('USERENV','HOST') host,
SYS_CONTEXT('USERENV','OS_USER') os_user,
SYS_CONTEXT('USERENV','EXTERNAL_NAME') external_name,
SYS_CONTEXT('USERENV','IP_ADDRESS') ip_address,
SYS_CONTEXT('USERENV','NETWORK_PROTOCOL') network_protocol,
SYS_CONTEXT('USERENV','BG_JOB_ID') bg_job_id,
SYS_CONTEXT('USERENV','FG_JOB_ID') fg_job_id,
SYS_CONTEXT('USERENV','AUTHENTICATION_TYPE') authentication_type,
SYS_CONTEXT('USERENV','AUTHENTICATION_DATA') authentication_data
from dual

##########[Q]
么获 得今天是星期几, 还关 于其它日期函数用法
**********[A]
可以用 to_char 来解决,如
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day') from dual;
取之前可以 置日期 言,如
ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';
可以在函数中指定
select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual;
其它更多用法,可以参考 to_char to_date 函数
得完整的 时间 格式
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
随便介 几个其它函数的用法:
本月的天数
SELECT to_char(last_day(SYSDATE),'dd') days FROM dual
今年的天数
select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual
下个星期一的日期
SELECT Next_day(SYSDATE,'monday') FROM dual

##########[Q]
随机抽取前 N 记录 问题
**********[A]8i
以上版本
select * from (select * from tablename order by sys_guid()) where rownum < N;
select * from (select * from tablename order by dbms_random.value) where rownum< N;
注: dbms_random 包需要手工安装,位于 $ORACLE_HOME/rdbms/admin/dbmsrand.sql
dbms_random.value(100,200)
可以 100 200 的随机数

##########[Q]
抽取从 N 行到 M 行的 记录 ,如从 20 行到 30 行的 记录
**********[A]select * from (select rownum id,t.* from table where ……
and rownum <= 30) where id > 20;

##########[Q]
么样 抽取重 复记录
**********[A]select * from table t1 where where t1.rowed !=
(select max(rowed) from table t2
where t1.id=t2.id and t1.name=t2.name)
或者
select count(*), t.col_a,t.col_b from table t
group by col_a,col_b
having count(*)>1
如果想 除重 复记录 ,可以把第一个 句的 select 换为 delete

##########[Q]
么样设 置自治事
**********[A]8i
以上版本,不影响主事
pragma autonomous_transaction;
……
commit|rollback;

##########[Q]
么样 程中 停指定 时间
**********[A]DBMS_LOCK
包的 sleep
如: dbms_lock.sleep(5); 表示 5 秒。

##########[Q]
么样 快速 算事 时间 与日志量
**********[A]
可以采用 似如下的脚本
DECLARE
start_time NUMBER;
end_time NUMBER;
start_redo_size NUMBER;
end_redo_size NUMBER;
BEGIN
start_time := dbms_utility.get_time;
SELECT VALUE INTO start_redo_size FROM v$mystat m,v$statname s
WHERE m.STATISTIC#=s.STATISTIC#
AND s.NAME='redo size';
--transaction start
INSERT INTO t1
SELECT * FROM All_Objects;
--other dml statement
COMMIT;
end_time := dbms_utility.get_time;
SELECT VALUE INTO end_redo_size FROM v$mystat m,v$statname s
WHERE m.STATISTIC#=s.STATISTIC#
AND s.NAME='redo size';
dbms_output.put_line('Escape Time:'||to_char(end_time-start_time)||' centiseconds');
dbms_output.put_line('Redo Size:'||to_char(end_redo_size-start_redo_size)||' bytes');
END;

##########[Q]
样创 临时
**********[A]8i
以上版本
create global temporary tablename(column list)
on commit preserve rows; --
提交保留数据 话临时
on commit delete rows; --
提交 除数据 务临时
临时 是相 于会 的, 的会 看不到 的数据。

##########[Q]
么样 PL/SQL DDL
**********[A]1
8i 以下版本 dbms_sql
2
8i 以上版本 可以用
execute immediate sql;
dbms_utility.exec_ddl_statement('sql');

##########[Q]
么样获 IP 地址
**********[A]
(817 以上 ) utl_inaddr.get_host_address
端: sys_context('userenv','ip_address')

##########[Q]
么样 加密存 储过
**********[A]
wrap 命令,如(假定你的存 储过 程保存 a.sql
wrap iname=a.sql
PL/SQL Wrapper: Release 8.1.7.0.0 - Production on Tue Nov 27 22:26:48 2001
Copyright (c) Oracle Corporation 1993, 2000. All Rights Reserved.
Processing a.sql to a.plb
提示 a.sql 转换为 a.plb 就是加密了的脚本, a.plb 即可生成加密了的存 储过

##########[Q]
么样 ORACLE 中定 运行存 储过
**********[A]
可以利用 dbms_job 包来定 运行作 ,如 行存 储过 程,一个 简单 的例子,提交一个作
VARIABLE jobno number;
BEGIN
DBMS_JOB.SUBMIT(:jobno, 'ur_procedure;',SYSDATE,'SYSDATE + 1');
commit;
END;
之后,就可以用以下 查询 提交的作
select * from user_jobs;

##########[Q]
么样 从数据 得毫秒
**********[A]9i
以上版本,有一个 timestamp 得毫秒,如
SQL>select to_char(systimestamp,'yyyy-mm-dd hh24:mi:ssxff') time1,
to_char(current_timestamp) time2 from dual;

TIME1 TIME2
----------------------------- ----------------------------------------------------------------
2003-10-24 10:48:45.656000 24-OCT-03 10.48.45.656000 AM +08:00
可以看到,毫秒在 to_char 对应 的是 FF
8i
以上版本可以 建一个如下的 java 函数
SQL>create or replace and compile
java source
named "MyTimestamp"
as
import java.lang.String;
import java.sql.Timestamp;

public class MyTimestamp
{
public static String getTimestamp()
{
return(new Timestamp(System.currentTimeMillis())).toString();
}
};
SQL>java created.
注:注意 java 法,注意大小写
SQL>create or replace function my_timestamp return varchar2
as language java
name 'MyTimestamp.getTimestamp() return java.lang.String';
/
SQL>function created.
SQL>select my_timestamp,to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') ORACLE_TIME from dual;
MY_TIMESTAMP ORACLE_TIME
------------------------ -------------------
2003-03-17 19:15:59.688 2003-03-17 19:15:59
如果只想 1/100 (hsecs) 可以 利用 dbms_utility.get_time

##########[Q]
如果存在就更新,不存在就插入可以用一个 实现吗
**********[A]9i
支持了,是 Merge ,但是只支持 select 查询
如果是 条数据 记录 ,可以写作 select …… from dual 的子 查询

MERGE INTO table
USING data_source
ON (condition)
WHEN MATCHED THEN update_clause
WHEN NOT MATCHED THEN insert_clause;

MERGE INTO course c
USING (SELECT course_name, period,
course_hours
FROM course_updates) cu
ON (c.course_name = cu.course_name
AND c.period = cu.period)
WHEN MATCHED THEN
UPDATE
SET c.course_hours = cu.course_hours
WHEN NOT MATCHED THEN
INSERT (c.course_name, c.period,
c.course_hours)
VALUES (cu.course_name, cu.period,
cu.course_hours);

##########[Q]
么实现 ,右 与外
**********[A]
9i 以前可以 这么 :

select a.id,a.name,b.address from a,b
where a.id=b.id(+)
:
select a.id,a.name,b.address from a,b
where a.id(+)=b.id

SELECT a.id,a.name,b.address
FROM a,b
WHERE a.id = b.id(+)
UNION
SELECT b.id,'' name,b.address
FROM b
WHERE NOT EXISTS (
SELECT * FROM a
WHERE a.id = b.id);
9i 以上,已 经开 始支持 SQL99 准,所以,以上 句可以写成:
内部 联结
select a.id,a.name,b.address,c.subject
from (a inner join b on a.id=b.id)
inner join c on b.name = c.name
where other_clause

select a.id,a.name,b.address
from a left outer join b on a.id=b.id
where other_clause

select a.id,a.name,b.address
from a right outer join b on a.id=b.id
where other_clause

select a.id,a.name,b.address
from a full outer join b on a.id=b.id
where other_clause
or
select a.id,a.name,b.address
from a full outer join b using (id)
where other_clause

##########[Q]
么实现 一条 记录 根据条件多表插入
**********[A]9i
以上可以通 Insert all 句完成, 仅仅 是一个 句,如:
INSERT ALL
WHEN (id=1) THEN
INTO table_1 (id, name)
values(id,name)
WHEN (id=2) THEN
INTO table_2 (id, name)
values(id,name)
ELSE
INTO table_other (id, name)
values(id, name)
SELECT id,name
FROM a;
如果没有条件的 完成 个表的插入,如
INSERT ALL
INTO table_1 (id, name)
values(id,name)
INTO table_2 (id, name)
values(id,name)
INTO table_other (id, name)
values(id, name)
SELECT id,name
FROM a;

##########[Q]
如何 实现 行列 转换
**********[A]1
、固定列数的行列 转换

student subject grade
---------------------------
student1
80
student1
数学 70
student1
60
student2
90
student2
数学 80
student2
100
……
转换为
数学
student1 80 70 60
student2 90 80 100
……
句如下:
select student,sum(decode(subject,'
', grade,null)) " ",
sum(decode(subject,'
数学 ', grade,null)) " 数学 ",
sum(decode(subject,'
', grade,null)) " "
from table
group by student

2
、不定列行列 转换

c1 c2
--------------
1

1

1

2

2

3

……
转换为
1
我是
2
知道
3

型的 转换 借助于 PL/SQL 来完成, 一个例子
CREATE OR REPLACE FUNCTION get_c2(tmp_c1 NUMBER)
RETURN VARCHAR2
IS
Col_c2 VARCHAR2(4000);
BEGIN
FOR cur IN (SELECT c2 FROM t WHERE c1=tmp_c1) LOOP
Col_c2 := Col_c2||cur.c2;
END LOOP;
Col_c2 := rtrim(Col_c2,1);
RETURN Col_c2;
END;
/
SQL> select distinct c1 ,get_c2(c1) cc2 from table;
即可

##########[Q]
么样实现 取前 N 记录
**********[A]8i
以上版本,利用分析函数
个部 薪水前三名的 工或 个班成 前三名的学生。
Select * from
(select depno,ename,sal,row_number() over (partition by depno
order by sal desc) rn
from emp)
where rn<=3

##########[Q]
么样 把相 邻记录 合并到一条 记录
**********[A]8i
以上版本,分析函数 lag lead 可以提取后一条或前一天 记录 到本 记录
Select deptno,ename,hiredate,lag(hiredate,1,null) over
(partition by deptno order by hiredate,ename) last_hire
from emp
order by depno,hiredate

##########[Q]
如何取得一列中第 N 大的
**********[A]select * from
(select t.*,dense_rank() over (order by t2 desc) rank from t)
where rank = &N;

##########[Q]
么样 查询 内容 出到文本
**********[A]
spool
sqlplus –s " / as sysdba" <<EOF
set heading off
set feedback off
spool temp.txt
  select * from tab;
dbms_output.put_line(‘test’);
spool off
exit
EOF

##########[Q]
如何在 SQL*PLUS 境中 OS 命令?
**********[A]
比如 入了 SQLPLUS ,启 了数据 ,忽然想起 没有启 ,此 不用退出 SQLPLUS ,也不用另外起一个命令行窗口,直接 入:
SQL> host lsntctl start
或者 unix/linux 平台下
SQL>!
windows
平台下
SQL>$
总结 HOST 可以直接 OS 命令。
注: cd 命令无法正确 行。

##########[Q]
么设 置存 储过 程的 用者
**********[A]
普通存 储过 程都是所有者 限,如果想 用者 限, 参考如下
create or replace
procedure ……()
AUTHID CURRENT_USER
As
begin
……
end;

##########[Q]
快速 得用 个表或表分区的 记录
**********[A]
可以分析 ,然后 查询 user_tables 字典,或者采用如下脚本即可
SET SERVEROUTPUT ON SIZE 20000
DECLARE
miCount INTEGER;
BEGIN
FOR c_tab IN (SELECT table_name FROM user_tables) LOOP
EXECUTE IMMEDIATE 'select count(*) from "' || c_tab.table_name || '"' into miCount;
dbms_output.put_line(rpad(c_tab.table_name,30,'.') || lpad(miCount,10,'.'));
--if it is partition table
SELECT COUNT(*) INTO miCount FROM User_Part_Tables WHERE table_name = c_tab.table_name;
IF miCount >0 THEN
FOR c_part IN (SELECT partition_name FROM user_tab_partitions WHERE table_name = c_tab.table_name) LOOP
EXECUTE IMMEDIATE 'select count(*) from ' || c_tab.table_name || ' partition (' || c_part.partition_name || ')'

INTO miCount;
dbms_output.put_line(' '||rpad(c_part.partition_name,30,'.') || lpad(miCount, 10,'.'));
END LOOP;
END IF;
END LOOP;
END;

**********[A]
Oracle 发邮
##########[Q]
可以利用 utl_smtp 发邮 件,以下是一个 简单邮 件的例子程序
/****************************************************************************
parameter: Rcpter in varchar2
接收者
Mail_Content in Varchar2
件内容
desc: ·
件到指定
·
只能指定一个 箱,如果需要 送到多个 箱,需要另外的 助程序
****************************************************************************/
CREATE OR REPLACE PROCEDURE sp_send_mail( rcpter IN VARCHAR2,
mail_content IN VARCHAR2)
IS
conn utl_smtp.connection;
--write title
PROCEDURE send_header(NAME IN VARCHAR2, HEADER IN VARCHAR2) AS
BEGIN
utl_smtp.write_data(conn, NAME||': '|| HEADER||utl_tcp.CRLF);
END;
BEGIN
--opne connect
conn := utl_smtp.open_connection('smtp.com');
utl_smtp.helo(conn, 'oracle');
utl_smtp.mail(conn, 'oracle info');
utl_smtp.rcpt(conn, Rcpter);
utl_smtp.open_data(conn);
--write title
send_header('From', 'Oracle Database');
send_header('To', '"Recipient" <'||rcpter||'>');
send_header('Subject', 'DB Info');
--write mail content
utl_smtp.write_data(conn, utl_tcp.crlf || mail_content);
--close connect
utl_smtp.close_data(conn);
utl_smtp.quit(conn);
EXCEPTION
WHEN utl_smtp.transient_error OR utl_smtp.permanent_error THEN
BEGIN
utl_smtp.quit(conn);
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
WHEN OTHERS THEN
NULL;
END sp_send_mail;


**********[A]
么样 Oracle 中写操作系 文件,如写日志
##########[Q]
可以利用 utl_file 包,但是,在此之前,要注意 置好 Utl_file_dir 初始化参数
/**************************************************************************
parameter:textContext in varchar2
日志内容
desc: ·
写日志 , 把内容 到服 器指定目
·
配置 Utl_file_dir 初始化参数,并保 日志路径与 Utl_file_dir 路径一致或者是其中一个
****************************************************************************/
CREATE OR REPLACE PROCEDURE sp_Write_log(text_context VARCHAR2)
IS
file_handle utl_file.file_type;
Write_content VARCHAR2(1024);
Write_file_name VARCHAR2(50);
BEGIN
--open file
write_file_name := 'db_alert.log';
file_handle := utl_file.fopen('/u01/logs',write_file_name,'a');
write_content := to_char(SYSDATE,'yyyy-mm-dd hh24:mi:ss')||'||'||text_context;
--write file
IF utl_file.is_open(file_handle) THEN
utl_file.put_line(file_handle,write_content);
END IF;
--close file
utl_file.fclose(file_handle);
EXCEPTION
WHEN OTHERS THEN
BEGIN
IF utl_file.is_open(file_handle) THEN
utl_file.fclose(file_handle);
END IF;
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
END sp_Write_log;

第二部分、 ORACLE 构架体系
##########[Q]ORACLE
的有那些数据
**********[A]
的数据 型有
CHAR
固定 度字符域,最大 度可达 2000 个字
NCHAR
多字 字符集的固定 度字符域, 度随字符集而定,最多 2000 个字符或 2000 个字
VARCHAR2
变长 度字符域,最大 度可达 4000 个字符
NVARCHAR2
多字 字符集的可 变长 度字符域, 度随字符集而定,最多 4000 个字符或 4000 个字
DATE
用于存 全部日期的固定 (7 个字 ) 字符域, 时间 日期的一部分存 其中。除非
过设 init.ora 文件的 NLS_DATE_FORMAT 参数来取代日期格式,否 则查询时 ,日期以
DD-MON-YY
格式表示,如 13-APR-99 表示 1999.4.13
NUMBER
变长 度数 列,允 许值为 0 、正数和 数。 NUMBER 通常以 4 个字 或更少 的字 ,最多 21
LONG
变长 度字符域,最大 度可到 2GB
RAW
表示二 制数据的可 变长 度字符域,最 长为 2000 个字
LONGRAW
表示二 制数据的可 变长 度字符域,最 长为 2GB
MLSLABEL
只用于 TrustedOracle 个数据 行使用 2 5 个字
BLOB
制大 象,最大 4GB
CLOB
字符大 象,最大 4GB
NCLOB
多字 字符集的 CLOB 数据 型,最大 4GB
BFILE
外部二 制文件,大小由操作系 决定
ROWID
表示 RowID 的二 制数据 Oracle8RowID 的数 值为 10 个字 ,在 Oracle7 中使用的限定
RowID
格式 6 个字
UROWID
用于数据 址的二 制数据,最大 4000 个字

##########[Q]Oracle
有哪些常 见关键 字,不能被用于 象名
**********[A]
8i 版本 例,一般保留 关键 字不能用做 象名
ACCESS ADD ALL ALTER AND ANY AS ASC AUDIT BETWEEN BY CHAR CHECK CLUSTER COLUMN COMMENT COMPRESS CONNECT CREATE CURRENT DATE DECIMAL DEFAULT DELETE DESC DISTINCT DROP ELSE EXCLUSIVE EXISTS FILE FLOAT FOR FROM GRANT GROUP HAVING IDENTIFIED IMMEDIATE IN INCREMENT INDEX INITIAL INSERT INTEGER INTERSECT INTO IS LEVEL LIKE LOCK LONG MAXEXTENTS MINUS MLSLABEL MODE MODIFY NOAUDIT NOCOMPRESS NOT NOWAIT NULL NUMBER OF OFFLINE ON ONLINE OPTION OR ORDER PCTFREE PRIOR PRIVILEGES PUBLIC RAW RENAME RESOURCE REVOKE ROW ROWID ROWNUM ROWS SELECT SESSION SET SHARE SIZE SMALLINT START SUCCESSFUL SYNONYM SYSDATE TABLE THEN TO TRIGGER UID UNION UNIQUE UPDATE USER VALIDATE VALUES VARCHAR VARCHAR2 VIEW WHENEVER WHERE WITH
详细 信息可以 v$reserved_words 视图

##########[Q]
么查 看数据 版本
**********[A]select * from v$version
包含版本信息,核心版本信息,位数信息 (32 位或 64 )
至于位数信息,在 linux/unix 平台上,可以通 file 看,如
file $ORACLE_HOME/bin/oracle

##########[Q]
么查 看数据 参数
**********[A]show parameter
参数名
如通 show parameter spfile 可以 9i 是否使用 spfile 文件
或者 select * from v$parameter
除了 部分参数, Oracle 有大量 含参数,可以通 如下 :
SELECT NAME
,VALUE
,decode(isdefault, 'TRUE','Y','N') as "Default"
,decode(ISEM,'TRUE','Y','N') as SesMod
,decode(ISYM,'IMMEDIATE', 'I',
'DEFERRED', 'D',
'FALSE', 'N') as SysMod
,decode(IMOD,'MODIFIED','U',
'SYS_MODIFIED','S','N') as Modified
,decode(IADJ,'TRUE','Y','N') as Adjusted
,description
FROM ( --GV$SYSTEM_PARAMETER
SELECT x.inst_id as instance
,x.indx+1
,ksppinm as NAME
,ksppity
,ksppstvl as VALUE
,ksppstdf as isdefault
,decode(bitand(ksppi***/256,1),1,'TRUE','FALSE') as ISEM
,decode(bitand(ksppi***/65536,3),
1,'IMMEDIATE',2,'DEFERRED','FALSE') as ISYM
,decode(bitand(ksppstvf,7),1,'MODIFIED','FALSE') as IMOD
,decode(bitand(ksppstvf,2),2,'TRUE','FALSE') as IADJ
,ksppdesc as DESCRIPTION
FROM x$ksppi x
,x$ksppsv y
WHERE x.indx = y.indx
AND substr(ksppinm,1,1) = '_'
AND x.inst_id = USERENV('Instance')
)
ORDER BY NAME

##########[Q]
么样查 看数据 字符集
**********[A]
数据 器字符集 select * from nls_database_parameters ,其来源于 props$ ,是表示数据 的字符集。
端字符集 select * from nls_instance_parameters, 其来源于 v$parameter
表示客 端的字符集的 置,可能是参数文件, 量或者是注册表
字符集 select * from nls_session_parameters ,其来源于 v$nls_parameters ,表示会 自己的 置,可能是会 量或者是 alter session 完成,如果会 没有特殊的 置,将与 nls_instance_parameters 一致。
端的字符集要求与服 器一致,才能正确 示数据 的非 Ascii 字符。如果多个 置存在的 候, alter session> > 注册表 > 参数文件
字符集要求一致,但是 置却可以不同, 置建 用英文。如字符集是 zhs16gbk nls_lang 可以是 American_America.zhs16gbk

##########[Q]
么样 修改字符集
**********[A]8i
以上版本可以通 alter database 来修改字符集,但也只限于子集到超集,不建 修改 props$ 表,将可能 错误
Startup nomount;
Alter database mount exclusive;
Alter system enable restricted session;
Alter system set job_queue_process=0;
Alter database open;
Alter database character set zhs16gbk;

##########[Q]
建立基于函数索引
**********[A]8i
以上版本,确保
Query_rewrite_enabled=true
Query_rewrite_integrity=trusted
Compatible=8.1.0
以上
Create index indexname on table (function(field));

##########[Q]
么样 表或表分区
**********[A]
表的
Alter table tablename move
[Tablespace new_name
Storage(initial 50M next 50M
pctincrease 0 pctfree 10 pctused 50 initrans 2) nologging]
分区的
alter table tablename move (partition partname)
[update global indexes]
之后之后必 重建索引
Alter index indexname rebuild
如果表有 Lob 段,那 正常的 Alter 不能移 Lob 段到 的表空 ,而 仅仅 是移 了表段,可以采用如下的方法移 Lob
alter table tablename move
lob(lobsegname) store as (tablespace newts);

##########[Q]
么获 得当前的 SCN
**********[A]9i
以下版本
select max(ktuxescnw*power(2,32)+ktuxescnb) from x$ktuxe;
如果是 9i 以上版本, 可以通 以下
select dbms_flashback.get_system_change_number from dual;

##########[Q]ROWID
构与
**********[A]8
以上版本的 ROWID
OOOOOOFFFBBBBBBRRR
8
以下 ROWID 成(也叫受限 Rowid
BBBBBBBB.RRRR.FFFF
其中, O ID F 是文件 ID B ID R 是行 ID
如果我 们查询 一个表的 ROWID ,根据其中 的信息,可以知道 表确切占用了多少个 而知道占用了多少数据空 (此数据空 不等于表的分配空

##########[Q]
么样获 象的 DDL
**********[A]
第三方工具就不 了主要 一下 9i 以上版本的 dbms_metadata
1
象的 DDL
set heading off
set echo off
set feedback off
set pages off
set long 90000
select dbms_metadata.get_ddl('TABLE','TABLENAME','SCAME') from dual;
如果 取整个用 的脚本,可以用如下
select dbms_metadata.get_ddl('TABLE',u.table_name) from user_tables u;
当然,如果是索引, 需要修改相 table index

##########[Q]
如何 束的索引在 的表空
**********[A]1
、先 建索引,再
2
、利用如下
create table test
(c1 number constraint pk_c1_id primary key
using index tablespace useridex,
c2 varchar2(10)
) tablespace userdate;

##########[Q]
知道那些表没有建立主
**********[A]
一般的情况下,表的主 是必要的,没有主 的表可以 是不符合 设计规 范的。
SELECT table_name
FROM User_tables t
WHERE NOT EXISTS
(SELECT table_name
FROM User_constraints c
WHERE constraint_type = 'P'
AND t.table_name=c.table_name)
其它相 数据字典解
user_tables

user_tab_columns
表的列
user_constraints

user_cons_columns
束与列的
user_indexes
索引
user_ind_columns
索引与列的

##########[Q]dbms_output
提示 冲区不 ,怎 增加
**********[A]dbms_output.enable(20000);
另外,如果 dbms_output 的信息不能 示,
需要
set serveroutput on

##########[Q]
么样 修改表的列名
**********[A]9i
以上版本可以采用 rname 命令
ALTER TABLE UserName.TabName
RENAME COLUMN SourceColumn TO DestColumn
9i
以下版本可以采用 create table …… as select * from SourceTable 的方式。
另外, 8i 以上可以支持 除列了
ALTER TABLE UserName.TabName
SET UNUSED (ColumnName) CASCADE CONSTRAINTS
ALTER TABLE UserName.TabName
DROP (ColumnName) CASCADE CONSTRAINTS

##########[Q]
么样给 sqlplus 安装帮助
**********[A]SQLPLUS
的帮助必 手工安装, shell 脚本 $ORACLE_HOME/bin/helpins
在安装之前,必 SYSTEM_PASS 量,如:
$ setenv SYSTEM_PASS SYSTEM/MANAGER
$ helpins
如果不 该环 量,将在运行脚本的 候提示
当然,除了 shell 脚本, 可以利用 sql 脚本安装,那就不用 量了,但是,我 system
$ sqlplus system/manager
SQL> @?/sqlplus/admin/help/helpbld.sql helpus.sql
安装之后,你就可以象如下的方法使用帮助了
SQL> help index

##########[Q]
么样 快速下 Oracle
**********[A]
得下 器地址,在 http 面上有
ftp://updates.oracle.com
然后用 ftp ,用 名与密 metalink 的用 名与密
如我 知道了 丁号 3095277 (9204 丁集 )
ftp> cd 3095277
250 Changed directory OK.
ftp> ls
200 PORT command OK.
150 Opening data connection for file listing.
p3095277_9204_AIX64-5L.zip
p3095277_9204_AIX64.zip
……
p3095277_9204_WINNT.zip
226 Listing complete. Data connection has been closed.
ftp: 208 bytes received in 0.02Seconds 13.00Kbytes/sec.
ftp>
知道了 个信息,我 用用 flashget ,网 络蚂蚁 就可以下 了。
添加如下
ftp://updates.oracle.com/3095277/p3...04_AIX64-5L.zip
或替 后面的部分 所需要的内容
注意,如果是 flashget ,网 络蚂蚁请输 认证 名及密 ,就是你的 metalink 的用 名与密

##########[Q]
如何移 数据文件
**********[A]1
关闭 数据 ,利用 os
a.shutdown immediate
关闭 数据
b.
os 下拷 数据文件到新的地点
c.Startup mount
mount
d.Alter database rename datafile '
老文件 ' to ' 新文件 ';
e.Alter database open;
数据
2
、利用 Rman 机操作
RMAN> sql "alter database datafile ''file name'' offline";
RMAN> run {
2> copy datafile 'old file location'
3> to 'new file location';
4> switch datafile ' old file location'
5> to datafilecopy ' new file location';
6> }
RMAN> sql "alter database datafile ''file name'' online";
明:利用 OS 也可以 机操作,不 关闭 数据 ,与 rman 步骤 ,利用 rman 与利用 os 的原理一 ,在 rman copy 是拷 数据文件,相当于 OS cp ,而 switch 相当于 alter database rename ,用来更新控制文件。

##########[Q]
如果管理 机日志 与成
**********[A]
以下是常 操作,如果在 OPA/RAC 下注意 线 程号
增加一个日志文件
Alter database add logfile [group n] '
文件全名 ' size 10M;
上增加一个成
Alter database add logfile member '
文件全名 ' to group n;
除一个日志成
Alter database drop logfile member '
文件全名 ';
除整个日志
Alter database drop logfile group n;

##########[Q]
么样计 REDO BLOCK 的大小
**********[A]
算方法 (redo size + redo wastage) / redo blocks written + 16
具体 如下例子
SQL> select name ,value from v$sysstat where name like '%redo%';
NAME VALUE
---------------------------------------------------------------- ----------
redo synch writes 2
redo synch time 0
redo entries 76
redo size 19412
redo buffer allocation retries 0
redo wastage 5884
redo writer latching time 0
redo writes 22
redo blocks written 51
redo write time 0
redo log space requests 0
redo log space wait time 0
redo log switch interrupts 0
redo ordering marks 0
SQL> select (19412+5884)/51 + 16 '"Redo black(byte)" from dual;
Redo black(byte)
------------------
512

##########[Q]
控制文件包含哪些基本内容
**********[A]
控制文件主要包含如下条目,可以通 dump 控制文件内容看到
DATABASE ENTRY
CHECKPOINT PROGRESS RECORDS
REDO THREAD RECORDS
LOG FILE RECORDS
DATA FILE RECORDS
TEMP FILE RECORDS
TABLESPACE RECORDS
LOG FILE HISTORY RECORDS
OFFLINE RANGE RECORDS
ARCHIVED LOG RECORDS
BACKUP SET RECORDS
BACKUP PIECE RECORDS
BACKUP DATAFILE RECORDS
BACKUP LOG RECORDS
DATAFILE COPY RECORDS
BACKUP DATAFILE CORRUPTION RECORDS
DATAFILE COPY CORRUPTION RECORDS
DELETION RECORDS
PROXY COPY RECORDS
INCARNATION RECORDS

##########[Q]
如果 发现 表中有坏 ,如何 索其它未坏的数据
**********[A]
首先需要找到坏 ID (可以运行 dbverify 实现 ),假 设为 ,假定文件 编码为 。运行下面的 查询查 找段名:
SELECT segment_name,segment_type,extent_id,block_id, blocks
from dba_extents t
where
file_id =
AND between block_id and (block_id + blocks - 1)
一旦找到坏段名称,若段是一个表, 最好建立一个 临时 表,存放好的数据。若段是索引, 则删 除它,再重建。
create table good_table
as
select from bad_table where rowid not in
(select rowid
from bad_table where substr(rowid,10,6) = )
里要注意 8 以前的受限 ROWID ROWID 的差
可以使用 断事件 10231
SQL> ALTER SYSTEM SET EVENTS '10231 trace name context forever,level 10';
建一个 临时 good_table 的表中除坏 的数据都 索出来
SQL>CREATE TABLE good_table as select * from bad_table;
最后 关闭诊 断事件
SQL> ALTER SYSTEM SET EVENTS '10231 trace name context off ';
ROWID 构, 可以参考 dbms_rowid.rowid_create 函数。

##########[Q]
建了数据 的所有用 ,我可以 些用 户吗
**********[A]ORACLE
数据 库创 建的 候, 建了一系列默 的用 和表空 ,以下是他 的列表
·SYS/CHANGE_ON_INSTALL or INTERNAL
,数据字典所有者,超 级权 限所有者 (SYSDBA)
建脚本: ?/rdbms/admin/sql.bsq and various cat*.sql
议创 建后立即修改密
此用 不能被
·SYSTEM/MANAGER
数据 管理用 DBA 角色
建脚本: ?/rdbms/admin/sql.bsq
议创 建后立即修改密
此用 不能被
·OUTLN/OUTLN
划的存
建脚本: ?/rdbms/admin/sql.bsq
议创 建后立即修改密
此用 不能被
---------------------------------------------------
·SCOTT/TIGER, ADAMS/WOOD, JONES/STEEL, CLARK/CLOTH and BLAKE/PAPER.
实验 测试 ,含有例表 EMP DEPT
建脚本: ?/rdbms/admin/utlsampl.sql
可以修改密
可以被 除,在 境建 议删 除或
·HR/HR (Human Resources), OE/OE (Order Entry), SH/SH (Sales History).
实验 测试 ,含有例表 EMPLOYEES DEPARTMENTS
建脚本: ?/demo/schema/mksample.sql
可以修改密
可以被 除,在 境建 议删 除或
·DBSNMP/DBSNMP
Oracle Intelligent agent
建脚本: ?/rdbms/admin/catsnmp.sql, called from catalog.sql
可以改 -- 需要放置新密 snmp_rw.ora 文件
如果不需要 Intelligent Agents ,可以
---------------------------------------------------
以下用 都是可 安装用 , 如果不需要,就不需要安装
·CTXSYS/CTXSYS
Oracle interMedia (ConText Cartridge)
管理用
建脚本: ?/ctx/admin/dr0csys.sql
·TRACESVR/TRACE
Oracle Trace server
建脚本: ?/rdbms/admin/otrcsvr.sql
·ORDPLUGINS/ORDPLUGINS
Object Relational Data (ORD) User used by Time Series, etc.
建脚本: ?/ord/admin/ordinst.sql
·ORDSYS/ORDSYS
Object Relational Data (ORD) User used by Time Series, etc
建脚本: ?/ord/admin/ordinst.sql
·DSSYS/DSSYS
Oracle Dynamic Services and Syndication Server
建脚本: ?/ds/sql/dssys_init.sql
·MDSYS/MDSYS
Oracle Spatial administrator user
建脚本: ?/ord/admin/ordinst.sql
·AURORA$ORB$UNAUTHENTICATED/INVALID
Used for users who do not authenticate in Aurora/ORB
建脚本: ?/javavm/install/init_orb.sql called from ?/javavm/install/initjvm.sql
·PERFSTAT/PERFSTAT
Oracle Statistics Package (STATSPACK) that supersedes UTLBSTAT/UTLESTAT
建脚本: ?/rdbms/admin/statscre.sql

第三部分、 份与恢

##########[Q]
如何 / 关闭归
**********[A]
如果 档, log_archive_start=true 启自 动归 档,否 只能手工 档,如果是 关闭 档, 则设 参数 false
注意:如果是 OPS/RAC 境,需要先把 parallel_server = true 掉,然后 行如下 步骤 ,最后用 个参数重新启
1

a.
关闭 数据 shutdown immediate
b. startup mount
c. alter database archivelog
d. alter database opne
2
、禁止
a.
关闭 数据 shutdown immediate
b. startup mount
c. alter database noarchivelog
d. alter database open
档信息可以通 如下
SQL> archive log list
Database log mode Archive Mode
Automatic archival Enabled
Archive destination E:/oracle/ora92/database/archive
Oldest online log sequence 131
Next log sequence to archive 133
Current log sequence 133

##########[Q]
样设 置定 时归
**********[A]9i
以上版本,保 证归 档的最小 隔不超 n
Archive_lag_target = n
位:秒 0~7200

##########[Q]
不同版本怎 么导 /
**********[A]
出用低版本, 入用当前版本
如果版本跨越太大,需要用到中 版本

##########[Q]
不同的字符集之前怎 么导 数据
**********[A]a.
前条件是保 证导 / 入符合其他字符集 准,如客 户环 境与数据 字符集一致。
b. 修改 dmp 文件的 2 3 节为 数据 的字符集,注意要 成十六 制。
参考函数(以下函数中的 ID 是十 制的):
nls_charset_name
根据字符集 ID 得字符集名称
nls_charset_id
根据字符集名称 得字符集 ID

##########[Q]
么样备 份控制文件
**********[A]
线备 一个二 制的文件
alter database backup controlfile to '$BACKUP_DEPT/controlfile.000' [reuse];
文本文件方式
alter database backup controlfile to trace [resetlogs|noresetlogs];

##########[Q]
控制文件 坏如何恢
**********[A]1
、如果是 个控制文件
只需要 关闭 数据 ,拷 一个好的数据文件覆盖掉坏的数据文件即可
或者是修改 init.ora 文件的相 部分
2
、如果是 失全部控制文件, 需要 建控制文件或从 份恢
建控制文件的脚本可以通 alter database backup controlfile to trace 取。

##########[Q]
么样热备 份一个表空
**********[A]Alter tablespace
名称 begin backup;
host cp
个表空 的数据文件 目的地 ;
Alter tablespace
名称 end backup;
如果是 份多个表空 或整个数据 ,只需要一个一个表空 的操作下来就可以了。

##########[Q]
快速得到整个数据 热备 脚本
**********[A]
可以写一段 似的脚本
SQL>set serveroutput on
begin
dbms_output.enable(10000);
for bk_ts in (select distinct t.ts#,t.name from v$tablespace t,v$datafile d where t.ts#=d.ts#) loop
dbms_output.put_line('--'||bk_ts.name);
dbms_output.put_line('alter tablespace '||bk_ts.name||' begin backup;');
for bk_file in (select file#,name from v$datafile where ts#=bk_ts.ts#) loop
dbms_output.put_line('host cp '||bk_file.name||' $BACKUP_DEPT/');
end loop;
dbms_output.put_line('alter tablespace '||bk_ts.name||' end backup;');
end loop;
end;
/

##########[Q]
失一个数据文件,但是没有 份,怎 么样 数据
**********[A]
如果没有 份只能是 数据文件了,会 致相 的数据 失。
SQL>startup mount
--ARCHIVELOG
模式命令
SQL>Alter database datafile 'file name' offline;
--NOARCHIVELOG
模式命令
SQL>Alter database datafile 'file name' offline drop;
SQLl>Alter database open;
注意: 数据文件不能是系 数据文件

##########[Q]
失一个数据文件,没有 份但是有 数据文件 建以来的 档怎
**********[A]
如下条件
a.
不能是系 数据文件
b.
不能 失控制文件
如果 足以上条件,
SQL>startup mount
SQL>Alter database create datafile 'file name' as 'file name' size ... reuse;
SQL>recover datafile n; -
文件号
或者
SQL>recover datafile 'file name';
或者
SQL>recover database;
SQL>Alter database open;

##########[Q]
机日志 坏如何恢
**********[A]1
、如果是非当前日志而且 档,可以使用
Alter database clear logfile group n
建一个新的日志文件
如果 日志 没有 档, 需要用
Alter database clear unarchived logfile group n
2
、如果是当前日志 坏,一般不能 clear 可能意味着 失数据
如果有 份,可以采用 行不完全恢
如果没有 份,可能只能用 _allow_resetlogs_corruption=true 制恢 了,但是, 这样 的方法是不建 的,最好在有 Oracle support 的指 行。

##########[Q]
么样创 RMAN
**********[A]
首先, 建一个数据 ,一般都是 RMAN ,并 recovery_catalog_owner 角色
sqlplus sys
SQL> create user rman identified by rman;
SQL> alter user rman default tablespace tools temporary tablespace temp;
SQL> alter user rman quota unlimited on tools;
SQL> grant connect, resource, recovery_catalog_owner to rman;
SQL> exit;
然后,用 个用 建恢
rman catalog rman/rman
RMAN> create catalog tablespace tools;
RMAN> exit;
最后,你可以在恢 注册目 数据
rman catalog rman/rman target backdba/backdba
RMAN> register database;

##########[Q]
么样 在恢 候移 数据文件,恢 的地点
**********[A]
一个 RMAN 的例子
run {
set until time 'Jul 01 1999 00:05:00';
allocate channel d1 type disk;
set newname for datafile '/u04/oracle/prod/sys1prod.dbf'
to '/u02/oracle/prod/sys1prod.dbf';
set newname for datafile '/u04/oracle/prod/usr1prod.dbf'
to '/u02/oracle/prod/usr1prod.dbf';
set newname for datafile '/u04/oracle/prod/tmp1prod.dbf'
to '/u02/oracle/prod/tmp1prod.dbf';
restore controlfile to '/u02/oracle/prod/ctl1prod.ora';
replicate controlfile from '/u02/oracle/prod/ctl1prod.ora';
restore database;
sql "alter database mount";
switch datafile all;
recover database;
sql "alter database open resetlogs";
release channel d1;
}

##########[Q]
份片( backuppiece )中恢 (restore) 控制文件与数据文件
**********[A]
可以使用如下方法,在 RMAN 中恢 复备 份片的控制文件
restore controlfile from backuppiecefile;
如果是 9i 的自 动备 份,可以采用如下的方法
restore controlfile from autobackup;
但是,如果控制文件全部 失,需要指定 DBID ,如 SET DBID=?
动备 份控制文件的默 格式是 %F 个格式的形式
c-IIIIIIIIII-YYYYMMDD-QQ
,其中 IIIIIIIIII 就是 DBID
至于恢 (restore) 数据文件, oracle 816 始有个包 dbms_backup_restore
nomount 下就可以 行,可以 815 甚至之前的 份片, 出来的文件用于恢
可以在 SQLPLUS 中运行,如下
SQL>startup nomount
SQL> DECLARE
2 devtype varchar2(256);
3 done boolean;
4 BEGIN
5 devtype := dbms_backup_restore.deviceallocate('', params=>'');
6 dbms_backup_restore.restoresetdatafile;
7 dbms_backup_restore.restorecontrolfileto('E:/Oracle/oradata/penny/control01.ctl');
8 dbms_backup_restore.restoreDataFileto(1,'E:/Oracle/oradata/penny/system01.dbf');
9 dbms_backup_restore.restoreDataFileto(2,'E:/Oracle/oradata/penny/UNDOTBS01.DBF');
10 dbms_backup_restore.restoreDataFileto(3,'E:/ORACLE/ORADATA/PENNY/USERS01.DBF');
11 dbms_backup_restore.restorebackuppiece('D:/orabak/BACKUP_1_4_04F4IAJT.PENNY',done=>done);
12 END;
13 /
PL/SQL
程已成功完成。
SQL> alter database mount;

##########[Q]Rman
format 格式中的 %s 似的 西代表什
**********[A]
可以参考如下
%c
份片的拷
%d
数据 名称
%D
位于 月中的第几天 (DD)
%M
位于 年中的第几月 (MM)
%F
一个基于 DBID 唯一的名称 , 个格式的形式 c-IIIIIIIIII-YYYYMMDD-QQ, 其中 IIIIIIIIII 为该 数据 DBID YYYYMMDD 日期, QQ 是一个 1-256 的序列
%n
数据 名称,向右填 到最大八个字符
%u
一个八个字符的名称代表 份集与 时间
%p
该备 份集中的 份片号,从 1 始到 建的文件数
%U
一个唯一的文件名,代表 %u_%p_%c
%s
份集的号
%t
份集 时间
%T
年月日格式 (YYYYMMDD)

##########[Q]
exec dbms_logmnr_d.build('Logminer.ora','file directory') ,提示下 超界,怎 么办
**********[A]
完整 错误 信息如下 ,
SQL> exec dbms_logmnr_d.build('Logminer.ora','file directory')
BEGIN dbms_logmnr_d.build('Logminer.ora','file directory'); END;
*
ERROR
位于第 1 :
ORA-06532:
超出限制
ORA-06512:
"SYS.DBMS_LOGMNR_D", line 793
ORA-06512:
line 1
解决
1.
编辑 位于 "$ORACLE_HOME/rdbms/admin" 下的文件 "dbmslmd.sql"
:
TYPE col_desc_array IS VARRAY(513) OF col_description;

TYPE col_desc_array IS VARRAY(700) OF col_description;
并保存文件
2.
运行改 后的脚本
SQLPLUS> Connect internal
SQLPLUS> @$ORACLE_HOME/rdbms/admin/dbmslmd.sql
3.
重新 编译该
SQLPLUS> alter package DBMS_LOGMNR_D compile body;

##########[Q]
execute dbms_logmnr.start_logmnr(DictFileName=>'DictFileName') 提示 ORA-01843: 无效的月份, 个是什 原因
**********[A]
分析 start_logmnr
PROCEDURE start_logmnr(
startScn IN NUMBER default 0 ,
endScn IN NUMBER default 0,
startTime IN DATE default TO_DATE('01-jan-1988','DD-MON-YYYY'),
endTime IN DATE default TO_DATE('01-jan-2988','DD-MON-YYYY'),
DictFileName IN VARCHAR2 default '',
Options IN BINARY_INTEGER default 0 );
可以知道,如果 TO_DATE('01-jan-1988','DD-MON-YYYY') ,将 致以上 错误
所以解决 法可以
1
Alter session set NLS_LANGUAGE=American
2
、用 似如下的方法
execute dbms_logmnr.start_logmnr (DictFileName=> 'f:/temp2/TESTDICT.ora', starttime => TO_DATE(
'01-01-1988','DD-MM-YYYY'), endTime=>TO_DATE('01-01-2988','DD-MM-YYYY'));

第四部分、性能
##########[Q]
如果 置自 跟踪
**********[A]
system
$ORACLE_HOME/rdbms/admin/utlxplan.sql 划表
$ORACLE_HOME/sqlplus/admin/plustrce.sql plustrace 角色
如果想 划表 让每 个用 都能使用,
SQL>create public synonym plan_table for plan_table;
SQL> grant all on plan_table to public;
如果想 跟踪的角色 让每 个用 都能使用,
SQL> grant plustrace to public;
如下 / 停止跟踪
SET AUTOTRACE ON |OFF
| ON EXPLAIN | ON STATISTICS | TRACEONLY | TRACEONLY EXPLAIN

##########[Q]
如果跟踪自己的会 或者是 人的会
**********[A]
跟踪自己的会 简单
Alter session set sql_trace true|false
Or
Exec dbms_session.set_sql_trace(TRUE);
如果跟踪 人的会 ,需要 用一个包
exec dbms_system.set_sql_trace_in_session(sid,serial#,true|false)
跟踪的信息在 user_dump_dest 下可以找 到或通 如下脚本 得文件名称(适用于 Win 境,如果是 unix 需要做一定修改)
SELECT p1.value||'/'||p2.value||'_ora_'||p.spid||'.ora' filename
FROM
v$process p,
v$session s,
v$parameter p1,
v$parameter p2
WHERE p1.name = 'user_dump_dest'
AND p2.name = 'db_name'
AND p.addr = s.paddr
AND s.audsid = USERENV ('SESSIONID')
最后,可以通 Tkprof 来解析跟踪文件,如
Tkprof
原文件 文件 sys=n


##########[Q]
么设 置整个数据 跟踪
**********[A]
文档上的 alter system set sql_trace=true 是不成功的
但是可以通 过设 置事件来完成 个工作,作用相等
alter system set events
'10046 trace name context forever,level 1';
如果 关闭 跟踪,可以用如下
alter system set events
'10046 trace name context off';
其中的 level 1 与上面的 8 都是跟踪 级别
level 1
:跟踪 SQL 句,等于 sql_trace=true
level 4
:包括 量的 详细 信息
level 8
:包括等待事件
level 12
:包括 量与等待事件

##########[Q]
么样 根据 OS 程快速 DB 程信息与正在 行的
**********[A]
有些 候,我 OS 上操作,象 TOP 之后我 得到的 OS 程,怎 快速根据 OS 信息 DB 信息呢?
可以 写如下脚本:
$more whoit.sh
#!/bin/sh
sqlplus /nolog <
connect / as sysdba
col machine format a30
col program format a40
set line 200
select sid,serial# ,username,osuser,machine,program,process,to_char(logon_time,'yyyy/mm/dd hh24:mi:ss')
from v/$session where paddr in
( select addr from v/$process where spid in($1));

select sql_text from v/$sqltext_with_newlines
where hash_value in
(select SQL_HASH_VALUE from v/$session where
paddr in (select addr from v/$process where spid=$1)
)
order by piece;

exit;
EOF
然后,我 只要 OS 境下如下 行即可
$./whoit.sh Spid

##########[Q]
么样 分析表或索引
**********[A]
命令行方式可以采用 analyze 命令
Analyze table tablename compute statistics;
Analyze index|cluster indexname estimate statistics;
ANALYZE TABLE tablename COMPUTE STATISTICS
FOR TABLE
FOR ALL [LOCAL] INDEXES
FOR ALL [INDEXED] COLUMNS;
ANALYZE TABLE tablename DELETE STATISTICS
ANALYZE TABLE tablename VALIDATE REF UPDATE
ANALYZE TABLE tablename VALIDATE STRUCTURE
[CASCADE]|[INTO TableName]
ANALYZE TABLE tablename LIST CHAINED ROWS [INTO TableName]
等等。
如果想分析整个用 或数据 可以采用工具包, 可以并行分析
Dbms_utility(8i
以前的工具包 )
Dbms_stats(8i
以后提供的工具包 )

dbms_stats.gather_schema_stats(User,estimate_percent=>100,cascade=> TRUE);
dbms_stats.gather_table_stats(User,TableName,degree => 4,cascade => true);
命令与工具包的一些 总结
1
于分区表,建 使用 DBMS_STATS ,而不是使用 Analyze 句。
a) 可以并行 行, 多个用 ,多个 Table
b)
可以得到整个分区表的数据和 个分区的数据。
c) 可以在不同 级别 Compute Statistics 个分区,子分区,全表,所有分区
d)
可以倒出 统计 信息
e)
可以用 收集 统计 信息
2
DBMS_STATS 的缺点
a)
不能 Validate Structure
b)
不能收集 CHAINED ROWS, 不能收集 CLUSTER TABLE 的信息, 两个仍旧需要使用 Analyze 句。
c) DBMS_STATS
索引 Analyze ,因 Cascade False ,需要手工指定 True
3
oracle 9 里面的 External Table Analyze 不能使用,只能使用 DBMS_STATS 来收集信息。

##########[Q]
么样 快速重整索引
**********[A]
rebuild 句,可以快速重整或移 索引到 的表空
rebuild
有重建整个索引数的功能,可以在不 除原始索引的情况下改 索引的存 参数

alter index index_name rebuild tablespace ts_name
storage(……);
如果要快速重建整个用 下的索引,可以用如下脚本,当然,需要根据你自己的情况做相 修改
SQL> set heading off
SQL> set feedback off
SQL> spool d:/index.sql
SQL> SELECT 'alter index ' || index_name || ' rebuild '
||'tablespace INDEXES storage(initial 256K next 256K pctincrease 0);'
FROM all_indexes
WHERE ( tablespace_name != 'INDEXES'
OR next_extent != ( 256 * 1024 )
)
AND owner = USER
SQL>spool off
另外一个合并索引的 句是
alter index index_name coalesce
仅仅 是合并索引中同一 leaf block
消耗不大, 于有些索引中存在大量空 的情况下,有一些作用。

##########[Q]
如何使用 Hint 提示
**********[A]
select/delete/update 后写 /*+ hint */
select /*+ index(TABLE_NAME INDEX_NAME) */ col1...
注意 /* + 不能有空格
如用 hint 指定使用某个索引

select /*+ index(cbotab) */ col1 from cbotab;
select /*+ index(cbotab cbotab1) */ col1 from cbotab;
select /*+ index(a cbotab1) */ col1 from cbotab a;
其中
TABLE_NAME
是必 要写的,且如果在 查询 中使用了表的 名,在 hint 也要用表的 名来代替表名 ;
INDEX_NAME
可以不必写, Oracle 会根据 统计值选 一个索引 ;
如果索引名或表名写 了,那 hint 就会被忽略 ;

##########[Q]
么样 快速 制表或者是插入数据
**********[A]
快速 制表可以指定 Nologging 选项
如: Create table t1 nologging
as select * from t2;
快速插入数据可以指定 append 提示,但是需要注意
noarchivelog
模式下,默 用了 append 就是 nologging 模式的。
archivelog 下,需要把表 置程 Nologging 模式。
insert /*+ append */ into t1
select * from t2
注意:如果在 9i 境中并 置了 FORCE LOGGING 以上操作是无效的,并不会加快,当然,可以通 如下 NO FORCE LOGGING
Alter database no force logging;
是否 启了 FORCE LOGGING ,可以用如下
SQL> select force_logging from v$database;

##########[Q]
避免使用特定索引
**********[A]
在很多 候, Oracle 错误 的使用索引而 致效率的明 下降,我 可以使用一点点技巧而避免使用不 使用的索引,如:
test, 有字段 a,b,c,d ,在 a,b,c 上建立 合索引 inx_a(a,b,c) ,在 b 独建立了一个索引 Inx_b(b)
在正常情况下, where a=? and b=? and c=? 会用到索引 inx_a
where b=?
会用到索引 inx_b
但是, where a=? and b=? and c=? group by b 会用到哪个索引呢?在分析数据不正确(很 长时间 没有分析)或根本没有分析数据的情况下, oracle 往往会使用索引 inx_b 过执 划的分析, 个索引的使用,将大大耗 费查询时间
当然,我 可以通 如下的技巧避免使用 inx_b ,而使用 inx_a
where a=? and b=? and c=? group by b||'' -- 如果 b 是字符
where a=? and b=? and c=? group by b+0 --
如果 b 是数字
过这样简单 的改 ,往往可以是 查询时间 提交很多倍
当然,我 可以使用 no_index 提示,相信很多人没有用 ,也是一个不 的方法:
select /*+ no_index(t,inx_b) */ * from test t
where a=? and b=? and c=? group by b

##########[Q]Oracle
么时 候会使用跳 式索引
**********[A]
9i 的一个新特性跳 式索引 (Index Skip Scan).
例如表有索引 index(a,b,c) ,当 查询 条件
where b=?
候,可能会使用到索引 index(a,b,c)
如, 划中出 如下
INDEX (SKIP SCAN) OF 'TEST_IDX' (NON-UNIQUE)
Oracle
化器 ( 里指的是 CBO) 对查询应 Index Skip Scans 至少要有几个条件 :
1
化器 认为 是合适的。
2 索引中的前 列的唯一 的数量能 足一定的条件(如重 复值 很多)。
3
化器要知道前 列的 分布 ( 分析 / 统计 表得到 )
4 合适的 SQL
等。

##########[Q]
么样创 建使用虚 索引
**********[A]
可以使用 nosegment 选项 ,如
create index virtual_index_name on table_name(col_name) nosegment;
如果在哪个 session 需要 测试 索引,可以利用 含参数来
alter session set "_use_nosegment_indexes" = true;
就可以利用 explain plan for select …… 来看虚 索引的效果
利用 @$ORACLE_HOME/rdbms/admin/utlxpls
最后,根据需要,我 可以 除虚 索引,如普通索引一
drop index virtual_index_name;
注意:虚 索引并不是物理存在的,所以虚 索引并不等同于物理索引,不要用自 跟踪去 测试 索引,因 那是 实际执 行的效果,是用不到虚 索引的。

##########[Q]
样监 控无用的索引
**********[A]Oracle 9i
以上,可以 控索引的使用情况,如果一段 时间 内没有使用的索引,一般就是无用的索引

控: alter index index_name monitoring usage;
检查 使用状 select * from v$object_usage;
停止 控: alter index index_name nomonitoring usage;
当然,如果想 控整个用 下的索引,可以采用如下的脚本:
set heading off
set echo off
set feedback off
set pages 10000
spool start_index_monitor.sql
SELECT 'alter index '||owner||'.'||index_name||' monitoring usage;'
FROM dba_indexes
WHERE owner = USER;
spool off
set heading on
set echo on
set feedback on
------------------------------------------------
set heading off
set echo off
set feedback off
set pages 10000
spool stop_index_monitor.sql
SELECT 'alter index '||owner||'.'||index_name||' nomonitoring usage;'
FROM dba_indexes
WHERE owner = USER;
spool off
set heading on
set echo on
set feedback on

##########[Q]
么样 能固定我的
**********[A]
可以使用 OUTLINE 来固定 SQL 句的
用如下 句可以 建一个 OUTLINE
Create oe replace outline OutLn_Name on
Select Col1,Col2 from Table
where ……
如果要 Outline ,可以采用
Drop Outline OutLn_Name;
于已 经创 建了的 OutLine ,存放在 OUTLN OL$HINTS 表下面
于有些 句,你可以使用 update outln.ol$hints 来更新 outline
update outln.ol$hints(ol_name,'TEST1','TEST2','TEST2','TEST1)
where ol_name in ('TEST1','TEST2');
这样 ,你就把 Test1 OUTLINE Test2 OUTLINE
如果想利用已 存在的 OUTLINE ,需要 置以下参数
Alter system/session set Query_rewrite_enabled = true
Alter system/session set use_stored_outlines = true

##########[Q]v$sysstat
中的 class 代表什
**********[A]
统计类别
1
代表事例活
2
代表 Redo buffer
4
代表
8
代表数据 冲活
16
代表 OS
32
代表并行活
64
代表表 访问
128
代表 调试 信息

##########[Q]
么杀 掉特定的数据
**********[A] Alter system kill session 'sid,serial#';
或者
alter system disconnect session 'sid,serial#' immediate;
win 上, 可以采用 oracle 提供的 orakill 掉一个 线 程(其 就是一个 Oracle 程)
Linux/Unix 上,可以直接利用 kill 掉数据 库进 对应 OS

##########[Q]
快速 等待
**********[A]
数据 是比 费资 源的,特 等待的 候,我 找到 生等待的 ,有可能的 该进 程。
句将 找到数据 中所有的 DML 生的 可以 发现 ,任何 DML 句其 实产 生了两个 ,一个是表 ,一个是行
可以通 alter system kill session ‘sid,serial#’ 掉会
SELECT /*+ rule */ s.username,
decode(l.type,'TM','TABLE LOCK',
'TX','ROW LOCK',
NULL) LOCK_LEVEL,
o.owner,o.object_name,o.object_type,
s.sid,s.serial#,s.terminal,s.machine,s.program,s.osuser
FROM v$session s,v$lock l,dba_objects o
WHERE l.sid = s.sid
AND l.id1 = o.object_id(+)
AND s.username is NOT NULL
如果 生了 等待,我 可能更想知道是 谁锁 了表而引起 的等待
以下的 句可以 查询 谁锁 了表,而 在等待。
SELECT /*+ rule */ lpad(' ',decode(l.xidusn ,0,3,0))||l.oracle_username User_name,
o.owner,o.object_name,o.object_type,s.sid,s.serial#
FROM v$locked_object l,dba_objects o,v$session s
WHERE l.object_id=o.object_id
AND l.session_id=s.sid
ORDER BY o.object_id,xidusn DESC
以上 查询结 果是一个 构,如果有子 点, 表示有等待 生。如果想知道 用了哪个回 段, 可以 关联 V$rollname ,其中 xidusn 就是回 段的 USN

##########[Q]
如何有效的 除一个大表 (extent 数很多的表 )
**********[A]
一个有很多 (100k)extent 的表,如果只是 简单 地用 drop table ,会很大量消耗 CPU Oracle fet$ uet$ 数据字典 行操作),可能会用上几天的 时间 好的方法是分多次 extent ,以减 轻这种 消耗:
1. truncate table big-table reuse storage;
2. alter table big-table deallocate unused keep 2000m (
原来大小的 n-1/n);
3. alter table big-table deallocate unused keep 1500m ;
....
4. drop table big-table;

##########[Q]
如何收 缩临时 数据文件的大小
**********[A]9i
以下版本采用
ALTER DATABASE DATAFILE 'file name' RESIZE 100M
似的
9i
以上版本采用
ALTER DATABASE TEMPFILE 'file name' RESIZE 100M
注意, 临时 数据文件在使用 ,一般不能收 ,除非 关闭 数据 或断 所有会 ,停止 对临时 数据文件的使用。

##########[Q]
清理 临时
**********[A]
可以使用如下
1
使用如下 看一下 认谁 在用 临时
SELECT username,sid,serial#,sql_address,machine,program,
tablespace,segtype, contents
FROM v$session se,v$sort_usage su
WHERE se.saddr=su.session_addr
2
那些正在使用 临时 段的
SQL>Alter system kill session 'sid,serial#';
3
、把 TEMP 表空 一下
SQL>Alter tablespace TEMP coalesce;
可以使用 断事件
1
确定 TEMP 表空 ts#
SQL> select ts#, name FROM v$tablespace;
TS# NAME
-----------------------
0 SYSYEM
1 RBS
2 USERS
3* TEMP
……
2
行清理操作
alter session set events 'immediate trace name DROP_SEGMENTS level TS#+1'
明:
temp
表空 TS# 3*, So TS#+ 1= 4
如果想清除所有表空 临时 段,
TS# = 2147483647

##########[Q]
么样 dump 数据 内部 构,如上面 示的控制文件的
**********[A]
的有
1
、分析数据文件 转储 数据文件 n m
alter system dump datafile n block m
2
、分析日志文件
alter system dump logfile logfilename;
3
、分析控制文件的内容
alter session set events 'immediate trace name CONTROLF level 10'
4
、分析所有数据文件
alter session set events 'immediate trace name FILE_HDRS level 10'
5
、分析日志文件
alter session set events 'immediate trace name REDOHDR level 10'
6
、分析系 ,最好 10 一次,做三次
alter session set events 'immediate trace name SYSTEMSTATE level 10'
7
、分析 程状
alter session set events 'immediate trace name PROCESSSTATE level 10'
8
、分析 Library Cache 详细 情况
alter session set events 'immediate trace name library_cache level 10'

##########[Q]
如何 得所有的事件代
**********[A]
事件代 一般从 10000 to 10999 ,以下列出了 个范 的事件代 与信息
SET SERVEROUTPUT ON
DECLARE
err_msg VARCHAR2(120);
BEGIN
dbms_output.enable (1000000);
FOR err_num IN 10000..10999
LOOP
err_msg := SQLERRM (-err_num);
IF err_msg NOT LIKE '%Message '||err_num||' not found%' THEN
dbms_output.put_line (err_msg);
END IF;
END LOOP;
END;
/
Unix 上,事件信息放在一个文本文件里
$ORACLE_HOME/rdbms/mesg/oraus.msg
可以用如下脚本 看事件信息
event=10000
while [ $event -ne 10999 ]
do
event=`expr $event + 1`
oerr ora $event
done
于已 确保的 / 正在跟踪的事件,可以用如下脚本
SET SERVEROUTPUT ON
DECLARE
l_level NUMBER;
BEGIN
FOR l_event IN 10000..10999
LOOP
dbms_system.read_ev (l_event,l_level);
IF l_level > 0 THEN
dbms_output.put_line ('Event '||TO_CHAR (l_event)||
' is set at level '||TO_CHAR (l_level));
END IF;
END LOOP;
END;
/

##########[Q]
STATSPACK ,我怎 使用它?
**********[A]Statspack
Oracle 8i 以上提供的一个非常好的性能 控与 断工具,基本上全部包含了 BSTAT/ESTAT 的功能,更多的信息
可以参考附 文档 $ORACLE_HOME/rdbms/admin/spdoc.txt
安装 Statspack:
cd $ORACLE_HOME/rdbms/admin
sqlplus "/ as sysdba" @spdrop.sql --
,第一次可以不需要
sqlplus "/ as sysdba" @spcreate.sql --
需要根据提示 入表空
使用 Statspack:
sqlplus perfstat/perfstat
exec statspack.snap; --
行信息收集 统计 次运行都将 生一个快照号
--
得快照号,必 要有两个以上的快照,才能生成
select SNAP_ID, SNAP_TIME from STATS$SNAPSHOT;
@spreport.sql --
入需要 看的 始快照号与 束快照号
其他相 脚本 s:
spauto.sql -
利用 dbms_job 提交一个作 ,自 STATPACK 的信息收集 统计
sppurge.sql -
清除一段范 内的 统计 信息,需要提供 始快照与 束快照号
sptrunc.sql -
清除 (truncate) 所有 统计 信息

第五部分、 ORACLE 与安全
##########[Q]
如何限定特定 IP 访问 数据
**********[A]
可以利用登 器、 cmgw 或者是在 $OREACLE_HOME/network/admin 下新增一个 protocol.ora 文件(有些 os 可能是 . protocol.ora ), 9i 可以直接修改 sqlnet.ora
增加如下内容:
tcp.validnode_checking=yes
#
许访问 ip
tcp.inited_nodes=(ip1,ip2,……)
#
不允 许访问 ip
tcp.excluded_nodes=(ip1,ip2,……)

##########[Q] 如何穿 防火 墙连 接数据
**********[A]
问题 只会在 WIN 平台出 UNIX 平台会自 解决。
解决方法:
在服 器端的 SQLNET.ORA 应类
SQLNET.AUTHENTICATION_SERVICES= (NTS)
NAMES.DIRECTORY_PATH= (TNSNAMES, ONAMES, HOSTNAME)
TRACE_LEVEL_CLIENT = 16
注册表的 HOME0 [HKEY_LOCAL_MACHINE]
USE_SHARED_SOCKET=TRUE

##########[Q]
如何利用 hostname 方式 接数据
host name
方式只支持 tcp/ip 协议 的小局域网
修改 listener.ora 中的如下信息
(SID_DESC =
(GLOBAL_DBNAME = ur_hostname) --
你的机器名
(ORACLE_HOME = E:/oracle/ora92) --oracle home
(SID_NAME = orcl) --sid name
)
然后在客
sqlnet.ora 中,确保有
NAMES.DIRECTORY_PATH= (HOSTNAME)
你就可以利用数据 器的名称 访问 数据

##########[Q]dbms_repcat_admin
来什 安全
**********[A]
如果一个用 dbms_repcat_admin 包,将 得极大的系 统权 限。
以下情况可能 包的 限:
1
、在 sys grant execute on dbms_repcat_admin to public[|user_name]
2
、用 户拥 execute any procedure 限于 9i 以下, 9i 须显 示授
如果用 过执 行如下 句:
exec sys.dbms_repcat_admin.grant_admin_any_schema('user_name');
得极大的系
可以从 user_sys_privs 详细 信息

##########[Q]
在不知道用 候,怎 么样 到另外一个用 户执 行操作后并不影响 ?
**********[A]
如下的方法,可以安全使用 ,然后再跳 回来,在某些 候比 有用
需要 Alter user 限或 DBA 限:
SQL> select password from dba_users where username='SCOTT';
PASSWORD
-----------------------------
F894844C34402B67
SQL> alter user scott identified by lion;
User altered.
SQL> connect scott/lion
Connected.
REM Do whatever you like...
SQL> connect system/manager
Connected.
SQL> alter user scott identified by values 'F894844C34402B67';
User altered.
SQL> connect scott/tiger
Connected.

##########[Q]
如何加固你的数据
**********[A]
要注意以下方面
1.
修改 sys, system 的口令。
2. Lock
,修改, 除默 dbsnmp,ctxsys 等。
3.
REMOTE_OS_AUTHENT 改成 False ,防止 程机器直接登
4.
O7_DICTIONARY_ACCESSIBILITY 改成 False
5.
把一些 限从 PUBLIC Role 取消掉。
6. 检查 数据 的数据文件的安全性。不要 置成 666 的。 检查 其他 dba
7.
把一些不需要的服 (比如 ftp, nfs 关闭 掉)
8.
限制数据 主机上面的用 量。
9. 定期 检查 Metalink/OTN 上面的 security Alert 。比如: http://otn.oracle.com/deploy/security/alerts.htm
10.
把你的数据 用放在一个 独的子网中,要不然你的用 很容易被 sniffer 去。或者采用 advance security 加密。
11.
限止只有某些 ip 才能 访问 你的数据
12. lsnrctl
要加密 ,要不然 人很容易从外面 掉你的 listener
13.
如果可能,不要使用默 1521 端口
<
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值