rman备份数据库后到另一台机器上恢复的例子

rman备份数据库后到另一台机器上恢复的过程

1.先查询并记录源数据库的dbid号和数据文件名

SQL> select dbid from v$database;

      DBID
----------
2674069457

SQL> select file#,name from v$datafile
  2  ;

     FILE# NAME
---------- --------------------------------------------------------------------------------
         1 D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\SYSTEM01.DBF
         2 D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\UNDOTBS01.DBF
         3 D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\SYSAUX01.DBF
         4 D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\USERS01.DBF
         5 D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\EXAMPLE01.DBF
         6 D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\HYGEIA01.DBF
         7 D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\HYGEIA02.DBF

7 rows selected

2.在新机器上使用和源数据库版本相同的oracle安装软件创建一个和源数据库同名的实例使用dbca来创建(生成的数据文件删除掉)或 使用如下命令来创建

复制一个pfile文件,放到C:\oracle\product\10.2.0\db_1\database目录下,并启动数据库到nomount状态(需要设置内存参数, 否则无法unmount,会无法分内存,报ORA-04031错误)并修改initcc.ora文件的内容来达到你要的设置要求

C:\Documents and Settings\Administrator>e:
C:\>cd E:\oracle\product\10.2.0\db_1\BIN
C:\oracle\product\10.2.0\db_1\BIN>orapwd file=C:\oracle\product\10.2.0\db_1\data
base\pwdCC.ora password=oracle entries=5;

E:\oracle\product\10.2.0\db_1\BIN>oradim -new -sid CC -pfile C:\oracle\product\10.2.0\db_1\database\initcc.ora
执行处理已建立.

修改机器上的监听,以便能够对实例CC进行监听
原内容为:

SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = C:oracle92ora92)
(PROGRAM = extproc)
)
(SID_DESC =
(GLOBAL_DBNAME = logicdg)
(ORACLE_HOME = C:oracle92ora92)
(SID_NAME = logicdg)
)
)

更改以后的内容为:

SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PLSExtProc)
(ORACLE_HOME = C:oracle92ora92)
(PROGRAM = extproc)
)
(SID_DESC =
(GLOBAL_DBNAME = logicdg)
(ORACLE_HOME = C:oracle92ora92)
(SID_NAME = logicdg)
)
(SID_DESC =
(GLOBAL_DBNAME = CC
(ORACLE_HOME = D:\ORADATA\OCP)
(SID_NAME = CC
)
)


C:\oracle\product\10.2.0\db_1\BIN>set ORACLE_SID=CC
C:\oracle\product\10.2.0\db_1\BIN>sqlplus "/as sysdba"

联机至闲置的执行处理.

可以连接DB了

3.启动实例到nomount状态

SQL>startup pfile='C:\oracle\product\10.2.0\db_1\database\initcc.ora' nomount;
ORACLE执行处理已启动.

Total System Global Area 163577856 bytes
Fixed Size                 1247852 bytes
Variable Size            104859028 bytes
Database Buffers          50331648 bytes
Redo Buffers               7139328 bytes
4.恢复控制文件
C:\Documents and Settings\Administrator>rman target/

恢复管理器: Release 10.2.0.1.0 - Production on 星期六 3月 17 10:53:10 2012

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

连接到目标数据库: ocp (未装载)

RMAN> startup nomount

数据库已经启动

RMAN> restore controlfile from 'D:\t\O1_MF_NCSNF_TAG20120316T161306_7P5Y9JQG_.BK
P';

启动 restore 于 17-3月 -12
使用目标数据库控制文件替代恢复目录
分配的通道: ORA_DISK_1
通道 ORA_DISK_1: sid=156 devtype=DISK

通道 ORA_DISK_1: 正在复原控制文件
通道 ORA_DISK_1: 恢复完成, 用时: 00:00:04
输出文件名=D:\ORADATA\OCP\CONTROL01.CTL
输出文件名=D:\ORADATA\OCP\CONTROL02.CTL
输出文件名=D:\ORADATA\OCP\CONTROL03.CTL
完成 restore 于 17-3月 -12

5. 将新数据库的dbid设置成源数据库的dbid

RMAN> set dbid=2674069457;

正在执行命令: SET DBID

6.启动数据库到mount状态

RMAN> alter database mount;

数据库已装载
释放的通道: ORA_DISK_1

7.将备份集的信息加入到catalog,因为从远端数据库拷贝过来的备份集存放于目录D:\t而不是和源数据库备份集在相同的目录下

RMAN>  catalog start with 'D:\t';

启动 implicit crosscheck backup 于 17-3月 -12
分配的通道: ORA_DISK_1
通道 ORA_DISK_1: sid=155 devtype=DISK
已交叉检验的 1 对象
完成 implicit crosscheck backup 于 17-3月 -12

启动 implicit crosscheck copy 于 17-3月 -12
使用通道 ORA_DISK_1
完成 implicit crosscheck copy 于 17-3月 -12

搜索恢复区域中的所有文件
正在编制文件目录...
没有为文件编制目录

搜索与样式 D:\t 匹配的所有文件

数据库未知文件的列表
=====================================
文件名: D:\t\O1_MF_NCSNF_TAG20120316T161306_7P5Y9JQG_.BKP
文件名: D:\t\O1_MF_NNNDF_TAG20120316T161306_7P5XJMHN_.BKP

是否确实要将上述文件列入目录 (输入 YES 或 NO)? yes
正在编制文件目录...
目录编制完毕

已列入目录的文件的列表
=======================
文件名: D:\t\O1_MF_NCSNF_TAG20120316T161306_7P5Y9JQG_.BKP
文件名: D:\t\O1_MF_NNNDF_TAG20120316T161306_7P5XJMHN_.BKP

8.恢复数据文件,因为恢复的路径跟源库的数据文件路径不一致,需要用set newname转换路径.

RMAN> run{
2> set newname for datafile 1 to 'D:\oradata\ocp\SYSTEM01.DBF';
3> set newname for datafile 2 to 'D:\oradata\ocp\UNDOTBS01.DBF';
4> set newname for datafile 3 to 'D:\oradata\ocp\SYSAUX01.DBF';
5> set newname for datafile 4 to 'D:\oradata\ocp\USERS01.DBF';
6> set newname for datafile 5 to 'D:\oradata\ocp\EXAMPLE01.DBF';
7> set newname for datafile 6 to 'D:\oradata\ocp\HYGEIA01.DBF';
8> set newname for datafile 7 to 'D:\oradata\ocp\HYGEIA02.DBF';
9> restore database;
10> switch datafile all;
11> }

正在执行命令: SET NEWNAME

正在执行命令: SET NEWNAME

正在执行命令: SET NEWNAME

正在执行命令: SET NEWNAME

正在执行命令: SET NEWNAME

正在执行命令: SET NEWNAME

正在执行命令: SET NEWNAME

启动 restore 于 17-3月 -12
使用通道 ORA_DISK_1

通道 ORA_DISK_1: 正在开始恢复数据文件备份集
通道 ORA_DISK_1: 正在指定从备份集恢复的数据文件
正将数据文件00001恢复到D:\ORADATA\OCP\SYSTEM01.DBF
正将数据文件00002恢复到D:\ORADATA\OCP\UNDOTBS01.DBF
正将数据文件00003恢复到D:\ORADATA\OCP\SYSAUX01.DBF
正将数据文件00004恢复到D:\ORADATA\OCP\USERS01.DBF
正将数据文件00005恢复到D:\ORADATA\OCP\EXAMPLE01.DBF
正将数据文件00006恢复到D:\ORADATA\OCP\HYGEIA01.DBF
正将数据文件00007恢复到D:\ORADATA\OCP\HYGEIA02.DBF
通道 ORA_DISK_1: 正在读取备份段 D:\T\O1_MF_NNNDF_TAG20120316T161306_7P5XJMHN_.BK
P
通道 ORA_DISK_1: 已恢复备份段 1
段句柄 = D:\T\O1_MF_NNNDF_TAG20120316T161306_7P5XJMHN_.BKP 标记 = TAG20120316T16
1306
通道 ORA_DISK_1: 恢复完成, 用时: 00:20:25
完成 restore 于 17-3月 -12

数据文件 1 已转换成数据文件副本
输入数据文件副本 recid=9 stamp=778160312 文件名=D:\ORADATA\OCP\SYSTEM01.DBF
数据文件 2 已转换成数据文件副本
输入数据文件副本 recid=10 stamp=778160312 文件名=D:\ORADATA\OCP\UNDOTBS01.DBF
数据文件 3 已转换成数据文件副本
输入数据文件副本 recid=11 stamp=778160312 文件名=D:\ORADATA\OCP\SYSAUX01.DBF
数据文件 4 已转换成数据文件副本
输入数据文件副本 recid=12 stamp=778160312 文件名=D:\ORADATA\OCP\USERS01.DBF
数据文件 5 已转换成数据文件副本
输入数据文件副本 recid=13 stamp=778160312 文件名=D:\ORADATA\OCP\EXAMPLE01.DBF
数据文件 6 已转换成数据文件副本
输入数据文件副本 recid=14 stamp=778160313 文件名=D:\ORADATA\OCP\HYGEIA01.DBF
数据文件 7 已转换成数据文件副本
输入数据文件副本 recid=15 stamp=778160313 文件名=D:\ORADATA\OCP\HYGEIA02.DBF

9.打开数据库

RMAN> alter database open resetlogs;
RMAN> alter database open resetlogs;
MAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: alter db 命令 (在 03/17/2012 11:41:10 上) 失败
ORA-00344: 无法重新创建联机日志 'D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\REDO01.LOG'

ORA-27040: 文件创建错误, 无法创建文件
OSD-04002: 无法打开文件
O/S-Error: (OS 3) 系统找不到指定的路径。

这里报找不到redo日志文件的错误,因为数据库是非归档的,日志文件没有备份,在新库中也没有redo日志文件,这里需要重新创建日志

SQL> alter database drop logfile group 1;
alter database drop logfile group 1
*
第 1 行出现错误:
ORA-01623: 日志 1 是实例 ocp (线程 1) 的当前日志 - 无法删除
ORA-00312: 联机日志 1 线程 1: 'D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\REDO01.LOG'


SQL> alter database drop logfile group 2;

数据库已更改。

SQL> alter database add logfile group 2 'D:\oradata\ocp\redo02.log';
alter database add logfile group 2 'D:\oradata\ocp\redo02.log'
*
第 1 行出现错误:
ORA-00301: 添加日志文件 'D:\oradata\ocp\redo02.log' 时出错 - 无法创建文件
ORA-17610: 文件 'D:\oradata\ocp\redo02.log' 不存在, 大小也未指定
ORA-27041: 无法打开文件
OSD-04002: 无法打开文件
O/S-Error: (OS 2) 系统找不到指定的文件。


SQL> alter database add logfile group 2 'D:\oradata\ocp\redo02.log' size 50M;

数据库已更改。

SQL> alter database drop logfile group 3;

数据库已更改。

SQL> alter database add logfile group 3 'D:\oradata\ocp\redo03.log' size 50M;

数据库已更改。

SQL> alter system switch logfile;
alter system switch logfile
*
第 1 行出现错误:
ORA-01109: 数据库未打开

下面试着修改日志文件的在控制文件中的路径(restore回来的控制文件中记录的日志文件路径是源端日志文件的路径)
由于redo01.log是当前重做日志组所要先复制一个重做日志文件命为’D:\oradata\ocp\redo01.log’再执行修改日志文件的路径

SQL> alter database rename file 'D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\REDO01.LOG
' to 'D:\oradata\ocp\REDO01.log';

SQL> alter database open resetlogs;

数据库已更改。

10.处理临时表空间文件
先创建一个新临时表空间

sql>CREATE TEMPORARY TABLESPACE hygeiatemp  Tempfile 'D:\oradata\ocp\hygeiatemp01.dbf' size 500M;

修改新建的临时表空间为缺省的临时表空间

sql> Alter Database  Default Temporary Tablespace hygeiatemp;

再删除原来的临时表空间

sql> Drop Tablespace  temp;

再新建原来的临时表空间

sql> CREATE TEMPORARY TABLESPACE temp Tempfile 'D:\oradata\ocp\temp01.dbf' size 500M;

再将新建的原来的临时表空间修改为缺省的临时表空间

sql> Alter Database  Default Temporary Tablespace temp;

使用oracle sqlldr导入文本数据的例子

一:sql loader使用例子

car.csv要导入的数据格式如下
姓名性 别身份证号码人员类别未登帐时间
张宏华男432401511011201有工作(区)2011.04-2012.03
胡祥胜男有工作(41市 2011.04-2012.03
杨长保男430702195111221011有工作(区)2011.04-2012.03
刘新翁男432401511125001有工作(41市2011.04-2012.03
周家胜男432401511123001有工作((市)2011.04-2012.03
顾春茂男432401510210301有工作(市)2011.04-2012.03
王跃志男432401195102200015有工作(41区2011.04-2012.03
潘伯伦男432401195112237516老市“4050”2011.04-2012.03
a.创建表(将上面的数据导入到这个表中)

create table jy_20120308
(
username varchar2(40),
sex      varchar2(10),
idcard   varchar2(20),
rylb     varchar2(50),
sj       varchar2(50)
)

a.创建SQL*Loader输入数据所需要的文件,均保存到C:\,用记事本编辑:
控制文件:input.ctl,内容如下:

   load data            --1、控制文件标识
   infile  'D:\sqlldr\tx.csv'    --2、要输入的数据文件名为car.csv
   append into table jy_20120308 --3、向表test中追加记录
   fields terminated by ","      --4、字段以逗号分隔
   (username,sex,idcard,rylb,sj) -----定义列对应顺序

a、insert,为缺省方式,在数据装载开始时要求表为空
b、append,在表中追加新记录
c、replace,删除旧记录,替换成新装载的记录
d、truncate,同上
在DOS窗口下使用SQL*Loader命令实现数据的输入

C:\>sqlldr userid=system/manager@orcl control=input.ctl

默认日志文件名为:input.log
默认坏记录文件为:input.bad

也可以使用下面形式

创建SQL*Loader输入数据所需要的文件,均保存到C:\,用记事本编辑:
控制文件:input.ctl,内容如下:

   load data            --1、控制文件标识
   infile  *                                               --2、可以在控制文件内或在执行命令时指定                                                                     --数据内容或数据文件名
   append into table jy_20120308 --3、向表test中追加记录
   fields terminated by ","      --4、字段以逗号分隔
   (username,sex,idcard,rylb,sj) -----定义列对应顺序
sqlldr 'DBUser/Password control=/export/home/imp.ctl'
data=  D:\sqlldr\tx.csv' log=port.log

C:\>sqlldr userid=system/manager@orcl control=input.ctl
data=/export/home/port.txt log=port.log

b)在控制文件中直接导入数据
1、控制文件test.ctl的内容

LOAD DATA
INFILE *
BADFILE 'C:\Documents and Settings\Jackey\桌面\WMCOUNTRY.BAD'
DISCARDFILE 'C:\Documents and Settings\Jackey\桌面\WMCOUNTRY.DSC'
INSERT INTO TABLE EMCCOUNTRY
Fields terminated by ";" Optionally enclosed by '"'
(
COUNTRYID NULLIF (COUNTRYID="NULL"),
COUNTRYCODE,
COUNTRYNAME,
CONTINENTID NULLIF (CONTINENTID="NULL"),
MAPID NULLIF (MAPID="NULL"),
CREATETIME DATE "MM/DD/YYYY HH24:MI:SS" NULLIF (CREATETIME="NULL"),
LASTMODIFIEDTIME DATE "MM/DD/YYYY HH24:MI:SS" NULLIF (LASTMODIFIEDTIME="NULL")
)
BEGINDATA
1;"JP";"Japan";1;9;"09/16/2004 16:31:32";NULL
2;"CN";"China";1;10;"09/16/2004 16:31:32";NULL
3;"IN";"India";1;11;"09/16/2004 16:31:32";NULL
4;"AU";"Australia";6;12;"09/16/2004 16:31:32";NULL
5;"CA";"Canada";4;13;"09/16/2004 16:31:32";NULL
6;"US";"United States";4;14;"09/16/2004 16:31:32";NULL
7;"MX";"Mexico";4;15;"09/16/2004 16:31:32";NULL
8;"GB";"United Kingdom";3;16;"09/16/2004 16:31:32";NULL
9;"DE";"Germany";3;17;"09/16/2004 16:31:32";NULL
10;"FR";"France";3;18;"09/16/2004 16:31:32";NULL
11;"IT";"Italy";3;19;"09/16/2004 16:31:32";NULL
12;"ES";"Spain";3;20;"09/16/2004 16:31:32";NULL
13;"FI";"Finland";3;21;"09/16/2004 16:31:32";NULL
14;"SE";"Sweden";3;22;"09/16/2004 16:31:32";NULL
15;"IE";"Ireland";3;23;"09/16/2004 16:31:32";NULL
16;"NL";"Netherlands";3;24;"09/16/2004 16:31:32";NULL
17;"DK";"Denmark";3;25;"09/16/2004 16:31:32";NULL
18;"BR";"Brazil";5;85;"09/30/2004 11:25:43";NULL
19;"KR";"Korea, Republic of";1;88;"09/30/2004 11:25:43";NULL
20;"NZ";"New Zealand";6;89;"09/30/2004 11:25:43";NULL
21;"BE";"Belgium";3;79;"09/30/2004 11:25:43";NULL
22;"AT";"Austria";3;78;"09/30/2004 11:25:43";NULL
23;"NO";"Norway";3;82;"09/30/2004 11:25:43";NULL
24;"LU";"Luxembourg";3;81;"09/30/2004 11:25:43";NULL
25;"PT";"Portugal";3;83;"09/30/2004 11:25:43";NULL
26;"GR";"Greece";3;80;"09/30/2004 11:25:43";NULL
27;"IL";"Israel";1;86;"09/30/2004 11:25:43";NULL
28;"CH";"Switzerland";3;84;"09/30/2004 11:25:43";NULL
29;"A1";"Anonymous Proxy";0;0;"09/30/2004 11:25:43";NULL
30;"A2";"Satellite Provider";0;0;"09/30/2004 11:25:43";NULL
31;"AD";"Andorra";3;0;"09/30/2004 11:25:43";NULL
32;"AE";"United Arab Emirates";1;0;"09/30/2004 11:25:43";NULL
33;"AF";"Afghanistan";1;0;"09/30/2004 11:25:43";NULL
34;"AG";"Antigua and Barbuda";7;0;"09/30/2004 11:25:43";NULL
35;"AI";"Anguilla";7;0;"09/30/2004 11:25:43";NULL
36;"AL";"Albania";3;0;"09/30/2004 11:25:43";NULL
37;"AM";"Armenia";3;0;"09/30/2004 11:25:43";NULL
38;"AN";"Netherlands Antilles";3;0;"09/30/2004 11:25:43";NULL
39;"AO";"Angola";2;0;"09/30/2004 11:25:43";NULL
40;"AP";"Asia/Pacific Region";2;0;"09/30/2004 11:25:43";NULL
41;"AQ";"Antarctica";8;0;"09/30/2004 11:25:43";NULL
42;"AR";"Argentina";5;0;"09/30/2004 11:25:43";NULL
43;"AS";"American Samoa";6;0;"09/30/2004 11:25:43";NULL
44;"AW";"Aruba";5;0;"09/30/2004 11:25:43";NULL
45;"AZ";"Azerbaijan";1;0;"09/30/2004 11:25:43";NULL
46;"BA";"Bosnia and Herzegovina";3;0;"09/30/2004 11:25:43";NULL
47;"BB";"Barbados";5;0;"09/30/2004 11:25:43";NULL
48;"BD";"Bangladesh";1;0;"09/30/2004 11:25:43";NULL
49;"BF";"Burkina Faso";2;0;"09/30/2004 11:25:43";NULL
50;"BG";"Bulgaria";3;0;"09/30/2004 11:25:43";NULL
51;"BH";"Bahrain";1;0;"09/30/2004 11:25:43";NULL
52;"BI";"Burundi";2;0;"09/30/2004 11:25:43";NULL
53;"BJ";"Benin";2;0;"09/30/2004 11:25:43";NULL
54;"BM";"Bermuda";4;0;"09/30/2004 11:25:43";NULL
55;"BN";"Brunei Darussalam";1;0;"09/30/2004 11:25:43";NULL
56;"BO";"Bolivia";5;0;"09/30/2004 11:25:43";NULL
57;"BS";"Bahamas";7;0;"09/30/2004 11:25:43";NULL
58;"BT";"Bhutan";1;0;"09/30/2004 11:25:43";NULL
59;"BV";"Bouvet Island";5;0;"09/30/2004 11:25:43";NULL
60;"BW";"Botswana";2;0;"09/30/2004 11:25:43";NULL
61;"BY";"Belarus";3;0;"09/30/2004 11:25:43";NULL

2、执行导入命令

C:\>sqlldr userid=system/manager control=test.ctl

c)复杂格式的导入
Sqlldr
sql loader可以把一些以文本格式存放的数据顺利的导入到oracle数据库中,
是一种在不同数据库之间进行数据迁移的非常方便而且通用的工具。
缺点就速度比较慢,另外对blob等类型的数据就有点麻烦了。
用法: SQLLDR keyword=value [,keyword=value,…]
有效的关键字:
userid — ORACLE username/password
control – 控制文件
log – 记录的日志文件
bad – 坏数据文件
data – 数据文件
discard – 丢弃的数据文件
discardmax – 允许丢弃数据的最大值 (全部默认)
skip — Number of logical records to skip (默认0)
load — Number of logical records to load (全部默认)
errors – 允许的错误记录数 (默认50)
rows — Number of rows in conventional path bind array or between direct path data saves
(每次提交的记录数,默认: 常规路径 64, 所有直接路径)
bindsize — Size of conventional path bind array in bytes(默认256000)
每次提交记录的缓冲区的大小(字节为单位,默认256000)
silent –禁止输出信息 (header,feedback,errors,discards,partitions)
direct – 使用直通路径方式导入 (默认FALSE) 某日读了一篇文章,说是如果选择导入方式为true或是y,则会绕过了SGA,直接写datafile,而且是直接在HWM以上写。这就导致了HWM会被不断抬高,这样即使后来delete掉了这批数据,HWM依然没有被降下来。HWM不断被抬高的直接表现就是在做全表扫描的时候会越来越慢
parfile — parameter file: name of file that contains parameter specifications
parallel — 并行导入 (默认FALSE)
file — File to allocate extents from
与bindsize成对使用,其中较小者会自动调整到较大者
sqlldr先计算单条记录长度,乘以rows,如小于bindsize,不会试图扩张rows以填充bindsize;如超出,则以bindsize为准。
external_table
— use external table for load; NOT_USED, GENERATE_ONLY, EXECUTE(默认NOT_USED)
columnarrayrows
— Number of rows for direct path column array(默认5000)
streamsize — Size of direct path stream buffer in bytes(默认256000)
multithreading
— use multithreading in direct path
resumable — enable or disable resumable for current session(默认FALSE)
resumable_name
— text string to help identify resumable statement
resumable_timeout
— wait time (in seconds) for RESUMABLE(默认7200)
date_cache — size (in entries) of date conversion cache(默认1000)
注意:有两种方式可以指定命令行参数:通过位置或者通过关键字。前者的例子:’sqlldr scott/tiger foo’;
后者的例子:’sqlldr control=foo userid=scott/tiger’;
不能前面使用关键字指定后面通过位置制定的混合方式;
比如:’sqlldr scott/tiger control=foo logfile=log’ 是允许的,
但’sqlldr scott/tiger control=foo log’不允许。
为清楚起见最好所有命令行参数都用关键字指定。
控制文件:
一个控制命令的脚本文件,通常以ctl结尾,内容如下:
LOAD DATA
INFILE ‘t.dat’ 要导入的文件
// INFILE ‘tt.date’ 导入多个文件
// INFILE * 表示要导入的内容就在control文件里 下面的BEGINDATA后面就是导入的内容
INTO TABLE table_name 指定装入的表
BADFILE ‘c:\bad.txt’ 可选,指定坏文件地址,缺省在当前目录下生成与原文件名一致的.bad文件
************* 以下是4种装入表的方式
APPEND 原先的表有数据 就加在后面
INSERT 装载空表 如果原先的表有数据 sqlloader会停止 默认值
REPLACE 原先的表有数据 原先的数据会全部删除
TRUNCATE 指定的内容和replace的相同 会用truncate语句删除现存数据
************* 指定分隔符
FIELDS TERMINATED BY ‘,’ OPTIONALLY ENCLOSED BY ‘”‘
// TERMINATED BY WRITESPACE 以空白分割
TRAILING NULLCOLS 表的字段没有对应的值时允许为空
************* 下面是表的字段
(
col_1 , col_2 ,col_filler FILLER // FILLER 关键字 此列的数值不会被装载
// 如: lg,lg,not 结果 lg lg
)
如果没声明FIELDS TERMINATED BY ‘,’ 时,可以用下面两种方式实现同样功能:
1.为每一列指定分隔符
(
col_1 [interger external] TERMINATED BY ‘,’ ,
col_2 [date “dd-mon-yyy”] TERMINATED BY ‘,’ ,
col_3 [char] TERMINATED BY ‘,’ OPTIONALLY ENCLOSED BY ‘lg’
)
2.用位置告诉字段装载数据
(
col_1 position(1:2),
col_2 position(3:10),
col_3 position(*:16), // 这个字段的开始位置在前一字段的结束位置
col_4 position(1:16),
col_5 position(3:10) char(8) // 指定字段的类型
)
BEGINDATA 对应开始的 INFILE * 要导入的内容就在control文件里
10,Sql,what
20,lg,show

启用约束时使用exceptions表来跟踪不符合约束的数据并修正

启用约束时使用exceptions表来跟踪不符合约束的数据并修正

使用 EXCEPTIONS 表
1. 创建 EXCEPTIONS 表 (utlexcpt.sql)
2. 使用 EXCEPTIONS 子句执行 ALTER TABLE
3. 使用 EXCEPTIONS 子查询查找包含无效数据的行
4. 纠正错误
5. 再次执行 ALTER TABLE 以启用约束

如何识别行违反
EXCEPTIONS 子句帮助识别任何违反已启用的约束的行按下列步骤检测违反
约束的行为纠正它们并重新启用约束
1 如果还未创建请在管理目录中运行 utlexcpt.sql 脚本以创建异常表

SQL> @?/rdbms/admin/utlexcpt
Statement processed.
SQL> DESCRIBE exceptions
Name Null?Type
-------------------------- ------- ----------------
ROW_ID UNDEFINED
OWNER VARCHAR2(30)
TABLE_NAME VARCHAR2(30)
CONSTRAINT VARCHAR2(30)

在 Windows NT 中该脚本位于

%ORACLE_HOME%\RDBMS\ADMIN 目录下

2 使用 EXCEPTIONS 子句执行 ALTER TABLE 命令

SQL> ALTER TABLE summit.employee
2 ENABLE VALIDATE CONSTRAINT employee_dept_id_fk
3 EXCEPTIONS INTO system.exceptions;
ALTER TABLE summit.employee
*
ORA-02298:cannot enable (summit.EMP_DEPT_FK) - parent keys not
found

如果 EXCEPTIONS 表未用所有者姓名限定则它必须属于正改变
的表的所有者
将行插入 EXCEPTIONS 表中如果重新运行该命令将截断
EXCEPTIONS 表以删除全部现有的行
3 使用 EXCEPTIONS 表上的子查询标识无效数据

SQL> SELECT rowid, id, last_name, dept_id
2 FROM summit.employee
3 WHERE ROWID in (SELECT row_id
4 FROM exceptions)
5 FOR UPDATE;
ROWID ID LAST_NAME DEPT_ID
------------------- ----- --------------- --------
AAAAeyAADAAAAA1AAA 1003 Pirie 50
1 row selected.

4 更正数据中的错误

SQL> UPDATE summit.employee
2 SET id=10
3 WHERE rowid='AAAAeyAADAAAAA1AAA';
1 row processed.
SQL> COMMIT;
Statement processed.

5 截断 EXCEPTIONS 表并重新启用约束

SQL> TRUNCATE TABLE exceptions;
Statement processed.
SQL> ALTER TABLE summit.employee
2 ENABLE VALIDATE CONSTRAINT employee_dept_id_fk
3 EXCEPTIONS INTO system.exceptions;
Statement processed

忘记oracle的sys用户密码怎么修改

一、忘记除SYS、SYSTEM用户之外的用户的登录密码。

用SYS (或SYSTEM)用户登录: CONN SYS/PASS_WORD AS SYSDBA;
使用如下语句修改用户的密码: ALTER USER user_name IDENTIFIED BY “newpass”;
注意:密码不能全是数字。并且不能是数字开头。否则会出现:ORA-00988: 口令缺失或无效
二、忘记SYS用户,或者是SYSTEM用户的密码。
如果是忘记SYSTEM用户的密码,可以用SYS用户登录。然后用ALTER USER 命令修改密码:

 CONN SYS/PASS_WORD AS SYSDBA;
 ALTER USER SYSTEM IDENTIFIED BY "newpass";
 

如果是忘记SYS用户的密码,可以用SYSTEM用户登录。然后用ALTER USER 命令修改密码。

 CONN SYSTEM/PASS_WORD ;
 ALTER USER SYSTEM IDENTIFIED BY "newpass";
 

三、如果SYS,SYSTEM用户的密码都忘记或是丢失。
可以使用ORAPWD.EXE 工具修改密码。输入如下命令:

 orapwd file=D:\oracle10g\database\pwdctcsys.ora password=newpass
 

这个命令重新生成了数据库的密码文件。密码文件的位置在ORACLE_HOME目录下的\database目录下。
这个密码是修改sys用户的密码。除sys其他用户的密码不会改变。
不过Oracle提供了两种验证方式,一种是OS验证,另一种密码文件验证方式,如果是第一种方式用以下方法修改密码:

  sqlplus /nolog;
  connect / as sysdba
  alter user sys identified by ;
  alter user system identified by ;

  如果是第二种方法就用上述方式修改,也可以下方法修改密码:
  orapwd file=pwdxxx.ora password=你设定的新密码 entries=10
  设定完后,重新启动服务,再次登陆就可以了。
oracle 11g
在本机安装完Oracle以后,不记得sys用户的密码了,采用如下方法可以修改密码:
1.打开cmd,输入

sqlplus /nolog,

回车;
输入

conn / as sysdba

输入

alter user sys identified by 新密码

注意:新密码最好以字母开头,否则可能出现错误Ora-00988。有了这个方法后,只要自己对oracle服务器有管理员权限,不记得密码的时候就可以随意修改密码了。
2.在命令行执行如下命令:

sqlplus “/@服务名 as sysdba”

然后在sqlplus中

alter user sys identified by 新密码;
alter user system identified by 新密码;

3.运行到C盘根目录
1)输入:SET ORACLE_SID = 你的SID名称
2)输入:sqlplus/nolog
3)输入:connect/as sysdba
4)输入:alert user sys identified by sys
5)输入:alert user system identified by system
6)更改完成,密码是Oracle数据库初始密码
4.首先,在CMD下输入SQLPLUS/NOLOG然后再在出来的界面中打入CONN/AS SYSDBA,这样就会以本地系统登录的用户为信任用户进入数据库的操作.解决这个问题的方式有两种,一个是:ALTER USER (USERNAME) IDENTIFIED BY “密码”;这个是可以改变USERNAME的密码.当然这个USERNAME必须已经存在的
另一种是:CREATE USER (USERNAME) IDENTIFIED BY “密码”;改变用户权限的命令是:GRANT ROLES TO (USERNAME);以上2种方法都是针对ORACLE 9I的版本 。
5.用orapwd.exe命令,可以修改命令。

orapwd file=’/oracle/pwdsid.ora’ password=123456

这个命令是修改sys用户的密码。你把生成的文件覆盖原来的密码文件。除sys其他用户的密码不会改变。
6.

su - oracle
sqlplus /nolog
conn / as sysdba
startup (如果数据库不是处于启动状态则启动)
alter user sys identified by 123456

然后就可以使用sys用户密码登陆了

操作系统认证方式

conn / as sysdba
alter user sys identified by xxx

oracle字符集

一、什么是Oracle字符集

Oracle字符集是一个字节数据的解释的符号集合,有大小之分,有相互的包容关系。ORACLE支持国家语言的体系结构允许你使用本地化语言来存储,处理,检索数据。它使数据库工具,错误消息,排序次序,日期,时间,货币,数字,和日历自动适应本地化语言和平台。
影响Oracle数据库字符集最重要的参数是NLS_LANG参数。
它的格式如下: NLS_LANG = language_territory.charset
它有三个组成部分(语言、地域和字符集),每个成分控制了NLS子集的特性。
其中:
Language:指定服务器消息的语言,影响提示信息是中文还是英文
Territory:指定服务器的日期和数字格式,
Charset:指定字符集。
如:AMERICAN _ AMERICA. ZHS16GBK
从NLS_LANG的组成我们可以看出,真正影响数据库字符集的其实是第三部分。
所以两个数据库之间的字符集只要第三部分一样就可以相互导入导出数据,前面影响的只是提示信息是中文还是英文。
二.字符集的相关知识:
2.1字符集
实质就是按照一定的字符编码方案,对一组特定的符号,分别赋予不同数值编码的集合。Oracle数据库最早支持的编码方案是US7ASCII。
Oracle的字符集命名遵循以下命名规则:

即: < 语言>< 比特位数>< 编码>
比如: ZHS16GBK表示采用GBK编码格式、16位(两个字节)简体中文字符集

2.2字符编码方案

2.2.1单字节编码
(1)单字节7位字符集,可以定义128个字符,最常用的字符集为US7ASCII
(2)单字节8位字符集,可以定义256个字符,适合于欧洲大部分国家
例如:WE8ISO8859P1(西欧、8位、ISO标准8859P1编码)
2.2.2多字节编码
(1)变长多字节编码
某些字符用一个字节表示,其它字符用两个或多个字符表示,变长多字节编码常用于对亚洲语言的支持,例如日语、汉语、印地语等
例如:AL32UTF8(其中AL代表ALL,指适用于所有语言)、zhs16cgb231280
(2)定长多字节编码
每一个字符都使用固定长度字节的编码方案,目前oracle唯一支持的定长多字节编码是AF16UTF16,也是仅用于国家字符集
2.2.3unicode编码
Unicode是一个涵盖了目前全世界使用的所有已知字符的单一编码方案,也就是说Unicode为每一个字符提供唯一的编码。UTF-16是unicode的16位编码方式,是一种定长多字节编码,用2个字节表示一个unicode字符,AF16UTF16是UTF-16编码字符集。
UTF-8是unicode的8位编码方式,是一种变长多字节编码,这种编码可以用1、2、3个字节表示一个unicode字符,AL32UTF8,UTF8、UTFE是UTF-8编码字符集

2.3字符集超级
当一种字符集(字符集A)的编码数值包含所有另一种字符集(字符集B)的编码数值,并且两种字符集相同编码数值代表相同的字符时,则字符集A是字符集B的超级,或称字符集B是字符集A的子集。
Oracle8i和oracle9i官方文档资料中备有子集-超级对照表(subset-superset pairs),例如:WE8ISO8859P1是WE8MSWIN1252的子集。由于US7ASCII是最早的Oracle数据库编码格式,因此有许多字符集是US7ASCII的超集,例如WE8ISO8859P1、ZHS16CGB231280、ZHS16GBK都是US7ASCII的超集。

2.4数据库字符集(oracle服务器端字符集)
数据库字符集在创建数据库时指定,在创建后通常不能更改。在创建数据库时,可以指定字符集(CHARACTER SET)和国家字符集(NATIONAL CHARACTER SET)。
2.4.1字符集
(1)用来存储CHAR, VARCHAR2, CLOB, LONG等类型数据
(2)用来标示诸如表名、列名以及PL/SQL变量等
(3)用来存储SQL和PL/SQL程序单元等
2.4.2国家字符集:
(1)用以存储NCHAR, NVARCHAR2, NCLOB等类型数据
(2)国家字符集实质上是为oracle选择的附加字符集,主要作用是为了增强oracle的字符处理能力,因为NCHAR数据类型可以提供对亚洲使用定长多字节编码的支持,而数据库字符集则不能。国家字符集在oracle9i中进行了重新定义,只能在unicode编码中的AF16UTF16和UTF8中选择,默认值是AF16UTF16
2.4.3查询字符集参数
可以查询以下数据字典或视图查看字符集设置情况
nls_database_parameters、props$、v$nls_parameters
查询结果中NLS_CHARACTERSET表示字符集,NLS_NCHAR_CHARACTERSET表示国家字符集
2.4.4修改数据库字符集
按照上文所说,数据库字符集在创建后原则上不能更改。不过有2种方法可行。
1.如果需要修改字符集,通常需要导出数据库数据,重建数据库,再导入数据库数据的方式来转换。
2.通过ALTER DATABASE CHARACTER SET语句修改字符集,但创建数据库后修改字符集是有限制的,只有新的字符集是当前字符集的超集时才能修改数据库字符集,例如UTF8是US7ASCII的超集,修改数据库字符集可使用ALTER DATABASE CHARACTER SET UTF8。

2.5客户端字符集(NLS_LANG参数)

2.5.1客户端字符集含义
客户端字符集定义了客户端字符数据的编码方式,任何发自或发往客户端的字符数据均使用客户端定义的字符集编码,客户端可以看作是能与数据库直接连接的各种应用,例如sqlplus,exp/imp等。客户端字符集是通过设置NLS_LANG参数来设定的。
2.5.2NLS_LANG参数格式
NLS_LANG=_.
Language:显示oracle消息,校验,日期命名
Territory:指定默认日期、数字、货币等格式
Client character set:指定客户端将使用的字符集
例如:NLS_LANG=AMERICAN_AMERICA.US7ASCII
AMERICAN是语言,AMERICA是地区,US7ASCII是客户端字符集
2.5.3客户端字符集设置方法
1)UNIX环境
$NLS_LANG=“simplified chinese”_china.zhs16gbk
$export NLS_LANG
编辑oracle用户的profile文件
2)Windows环境
编辑注册表
Regedit.exe —》HKEY_LOCAL_MACHINE —》SOFTWARE —》ORACLE–》HOME
2.5.4NLS参数查询
Oracle提供若干NLS参数定制数据库和用户机以适应本地格式,例如有NLS_LANGUAGE,NLS_DATE_FORMAT,NLS_CALENDER等,可以通过查询以下数据字典或v$视图查看。
NLS_DATABASE_PARAMETERS:显示数据库当前NLS参数取值,包括数据库字符集取值
NLS_SESSION_PARAMETERS:显示由NLS_LANG设置的参数,或经过alter session改变后的参数值(不包括由NLS_LANG设置的客户端字符集)
NLS_INSTANCE_PARAMETE:显示由参数文件init.ora定义的参数
V$NLS_PARAMETERS:显示数据库当前NLS参数取值
2.5.5修改NLS参数
使用下列方法可以修改NLS参数
(1)修改实例启动时使用的初始化参数文件
(2)修改环境变量NLS_LANG
(3)使用ALTER SESSION语句,在oracle会话中修改
(4)使用某些SQL函数
NLS作用优先级别:Sql function > alter session >环境变量或注册表>参数文件>数据库默认参数
三.EXP/IMP与字符集
3.1 EXP/IMP
Export和Import是一对读写Oracle数据的工具。Export将Oracle数据库中的数据输出到操作系统文件中, Import把这些文件中的数据读到Oracle数据库中,由于使用exp/imp进行数据迁移时,数据从源数据库到目标数据库的过程中有四个环节涉及到字符集,如果这四个环节的字符集不一致,将会发生字符集转换。
EXP
____________ _________________ _____________
|imp导入文件|< -|环境变量NLS_LANG|<-|数据库字符集| ------------ ----------------- ------------- IMP ____________ _________________ _____________ |imp导入文件|->|环境变量NLS_LANG|->|数据库字符集|
———— —————– ————-
四个字符集是
(1)源数据库字符集
(2)Export过程中用户会话字符集(通过NLS_LANG设定)
(3)Import过程中用户会话字符集(通过NLS_LANG设定)
(4)目标数据库字符集

3.2导出的转换过程
在Export过程中,如果源数据库字符集与Export用户会话字符集不一致,会发生字符集转换,并在导出文件的头部几个字节中存储Export用户会话字符集的ID号。在这个转换过程中可能发生数据的丢失。

例:如果源数据库使用ZHS16GBK,而Export用户会话字符集使用US7ASCII,由于ZHS16GBK是16位字符集,而US7ASCII是7位字符集,这个转换过程中,中文字符在US7ASCII中不能够找到对等的字符,所以所有中文字符都会丢失而变成“?? ”形式,这样转换后生成的Dmp文件已经发生了数据丢失。
因此如果想正确导出源数据库数据,则Export过程中用户会话字符集应等于源数据库字符集或是源数据库字符集的超集

3.3导入的转换过程
(1)确定导出数据库字符集环境
通过读取导出文件头,可以获得导出文件的字符集设置
(2)确定导入session的字符集,即导入Session使用的NLS_LANG环境变量
(3)IMP读取导出文件
读取导出文件字符集ID,和导入进程的NLS_LANG进行比较
(4)如果导出文件字符集和导入Session字符集相同,那么在这一步骤内就不需要转换,如果不同,就需要把数据转换为导入Session使用的字符集。可以看出,导入数据到数据库过程中发生两次字符集转换

第一次:导入文件字符集与导入Session使用的字符集之间的转换,如果这个转换过程不能正确完成,Import向目标数据库的导入过程也就不能完成。
第二次:导入Session字符集与数据库字符集之间的转换。
四.查看数据库字符集
涉及三方面的字符集,
1. oracelserver端的字符集;
2. oracle client端的字符集;
3. dmp文件的字符集。
在做数据导入的时候,需要这三个字符集都一致才能正确导入。
4.1查询oracle server端的字符集
有很多种方法可以查出oracle server端的字符集,比较直观的查询方法是以下这种:

SQL> select userenv('language') from dual;
USERENV('LANGUAGE')
----------------------------------------------------
SIMPLIFIED CHINESE_CHINA.ZHS16GBK
SQL>select userenv(‘language’) from dual;
AMERICAN _ AMERICA. ZHS16GBK

4.2如何查询dmp文件的字符集
用oracle的exp工具导出的dmp文件也包含了字符集信息,dmp文件的第2和第3个字节记录了dmp文件的字符集。如果dmp文件不大,比如只有几M或几十M,可以用UltraEdit打开(16进制方式),看第2第3个字节的内容,如0354,然后用以下SQL查出它对应的字符集:

SQL> select nls_charset_name(to_number('0354','xxxx')) from dual;
ZHS16GBK

如果dmp文件很大,比如有2G以上(这也是最常见的情况),用文本编辑器打开很慢或者完全打不开,可以用以下命令(在unix主机上):

cat exp.dmp |od -x|head -1|awk '{print $2 $3}'|cut -c 3-6

然后用上述SQL也可以得到它对应的字符集。
4.3查询oracle client端的字符集
在windows平台下,就是注册表里面相应OracleHome的NLS_LANG。还可以在dos窗口里面自己设置,
比如: set nls_lang=AMERICAN_AMERICA.ZHS16GBK
这样就只影响这个窗口里面的环境变量。
在unix平台下,就是环境变量NLS_LANG。
$echo $NLS_LANG
AMERICAN_AMERICA.ZHS16GBK
如果检查的结果发现server端与client端字符集不一致,请统一修改为同server端相同的字符集。
补充:
(1).数据库服务器字符集

select * from nls_database_parameters

来源于props$,是表示数据库的字符集。
(2).客户端字符集环境

select * from nls_instance_parameters

其来源于v$parameter,表示客户端的字符集的设置,可能是参数文件,环境变量或者是注册表
(3).会话字符集环境

select * from nls_session_parameters

来源于v$nls_parameters,表示会话自己的设置,可能是会话的环境变量或者是alter session完成,如果会话没有特殊的设置,将与nls_instance_parameters一致。
(4).客户端的字符集要求与服务器一致,才能正确显示数据库的非Ascii字符。
如果多个设置存在的时候,NLS作用优先级别:Sql function > alter session >环境变量或注册表>参数文件>数据库默认参数
字符集要求一致,但是语言设置却可以不同,语言设置建议用英文。如字符集是zhs16gbk,则nls_lang可以是American_America.zhs16gbk。
五.修改oracle的字符集
按照上文所说,数据库字符集在创建后原则上不能更改。因此,在设计和安装之初考虑使用哪一种字符集十分重要。对数据库server而言,错误的修改字符集将会导致很多不可测的后果,可能会严重影响数据库的正常运行,所以在修改之前一定要确认两种字符集是否存在子集和超集的关系。一般来说,除非万不得已,我们不建议修改oracle数据库server端的字符集。特别说明,我们最常用的两种字符集ZHS16GBK和ZHS16CGB231280之间不存在子集和超集关系,因此理论上讲这两种字符集之间的相互转换不受支持。
不过修改字符集有2种方法可行。
1.通常需要导出数据库数据,重建数据库,再导入数据库数据的方式来转换。
2.通过ALTER DATABASE CHARACTER SET语句修改字符集,但创建数据库后修改字符集是有限制的,只有新的字符集是当前字符集的超集时才能修改数据库字符集,例如UTF8是US7ASCII的超集,修改数据库字符集可使用ALTER DATABASE CHARACTER SET UTF8。
5.1修改server端字符集(不建议使用)
1.关闭数据库

SQL>SHUTDOWN IMMEDIATE

2.启动到Mount

SQL>STARTUP MOUNT;
SQL>ALTER SYSTEM ENABLE RESTRICTED SESSION;
SQL>ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
SQL>ALTER SYSTEM SET AQ_TM_PROCESSES=0;
SQL>ALTER DATABASE OPEN;
--这里可以从父集到子集
SQL>ALTER DATABASE CHARACTER SET ZHS16GBK;
SQL>ALTER DATABASE NATIONAL CHARACTER SET AL16UTF16;
--如果是从子集到父集,需要使用INTERNAL_USE参数,跳过超子集检测
SQL>ALTER DATABASE CHARACTER SET INTERNAL_USE AL32UTF8;
SQL>ALTER DATABASE NATIONAL CHARACTER SET INTERNAL_USE AL16UTF16;

SQL>SHUTDOWN IMMEDIATE;

SQL>STARTUP

注意:如果没有大对象,在使用过程中进行语言转换没有什么影响,(切记设定的字符集必须是ORACLE支持,不然不能start)按上面的做法就可以。
若出现‘ORA-12717: Cannot ALTER DATABASE NATIONAL CHARACTER SET when NCLOB data exists’这样的提示信息,
要解决这个问题有两种方法
1.利用INTERNAL_USE关键字修改区域设置,
2.利用re-create,但是re-create有点复杂,所以请用internal_use

SQL>SHUTDOWN IMMEDIATE;
SQL>STARTUP MOUNT EXCLUSIVE;
SQL>ALTER SYSTEM ENABLE RESTRICTED SESSION;
SQL>ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
SQL>ALTER SYSTEM SET AQ_TM_PROCESSES=0;
SQL>ALTER DATABASE OPEN;
SQL>ALTER DATABASE NATIONAL CHARACTER SETINTERNAL_USEUTF8;
SQL>SHUTDOWN immediate;
SQL>startup;

如果按上面的做法做,National charset的区域设置就没有问题
5.2修改dmp文件字符集
上文说过,dmp文件的第2第3字节记录了字符集信息,因此直接修改dmp文件的第2第3字节的内容就可以‘骗’过oracle的检查。这样做理论上也仅是从子集到超集可以修改,但很多情况下在没有子集和超集关系的情况下也可以修改,我们常用的一些字符集,如US7ASCII,WE8ISO8859P1,ZHS16CGB231280,ZHS16GBK基本都可以改。因为改的只是dmp文件,所以影响不大。
具体的修改方法比较多,最简单的就是直接用UltraEdit修改dmp文件的第2和第3个字节。
比如想将dmp文件的字符集改为ZHS16GBK,可以用以下SQL查出该种字符集对应的16进制代码: SQL> select to_char(nls_charset_id(‘ZHS16GBK’), ‘xxxx’) from dual;
0354
然后将dmp文件的2、3字节修改为0354即可。
如果dmp文件很大,用ue无法打开,就需要用程序的方法了。
5.3客户端字符集设置方法
1)UNIX环境
$NLS_LANG=“simplified chinese”_china.zhs16gbk
$export NLS_LANG
编辑oracle用户的profile文件
2)Windows环境
编辑注册表
Regedit.exe —》HKEY_LOCAL_MACHINE —》SOFTWARE —》ORACLE–》HOME
或者在窗口设置:
set nls_lang=AMERICAN_AMERICA.ZHS16GBK

以上内容整理自其它资料

创建job的一个例子

declare

job_id number;
begin
--sys.dbms_job.submit('USP_WCP',sysdate,'sysdate+1/1440');
sys.dbms_job.submit(job => job_id,
what => 'USP_WCB;',
next_date => to_date('2012-02-27 12:50:00','yyyy-mm-dd hh24:mi:ss'),
interval => 'sysdate+1440'
);
end
;

查看已经创建的job

select * from user_jobs ;

查看任务:

select * from user_jobs;
select * from all_jobs;

查看正在运行的任务(不推荐使用,速度慢):

select * from dba_jobs_running;

另外值得一提的是,在安装oracle配置的时候,有这么一个参数:

job_queue_processes=4& (默认4)

这个参数是定义当前最多可同时运行几个job,它的最大值能设置为36。

除了submit参数外,其余的几个参数有:

&dbms_job.run(v_job); //运行job

dbms_job.broken(v_job,true,next_date); //停止一个job,里面参数true也可是false,next_date(某一时刻停止)也可是sysdate(立刻停止)。

&dbms_job.remove(v_job); //删除某个job

&dbms_job.what(v_job,’sp_fact_charge_code;’); //修改某个job名

dbms_job.next_date(v_job,sysdate); 修改下一次运行时间

例题,设定每天2:10:10运行

trunc(sysdate)+2/24+10/24/60+10/24/60/60 //运行时间

trunc(sysdate)+1+2/24+10/24/60+10/24/60/60 //间隔运行时间

例题,设定每月2号的2:10:10运行

trunc(sysdate,’mm’)+1+2/24+10/24/60+10/24/60/60 //运行时间

trunc(add_mouths(sysdate,1),’mm’)+1+2/24+10/24/60+10/24/60/60 //间隔运行时间

例题,设定每个季度

trunce(sysdate,’Q’)+1+2/24+10/24/60+10/24/60/60 //运行时间

trunce(add_mouths(sysdate,3),’Q’))+1+2/24+10/24/60+10/24/60/60 //间隔运行时间

另外年为’Y’;

例题,设定每周一

next_day(sysdate’星期一’)

DBMS_JOB系统包是Oracle“任务队列”子系统的API编程接口。DBMS_JOB包对于任务队列提供了下面这些功能:提交并且执行一个任务、改变任务的执行参数以及删除或者临时挂起任务等。

DBMS_JOB包是由ORACLE_HOME目录下的rdbms/admin子目录下的DBMSJOB.SQL和PRVTJOB.PLB 这两个脚本文件创建的。这两个文件被CATPROC.SQL脚本文件调用,而CATPROC.SQL这个文件一般是在数据库创建后立即执行的。脚本为DBMS_JOB包创建了一个公共同义词,并给该包授予了公共的可执行权限,所以所有的Oracle用户均可以使用这个包。

下面几个数据字典视图是关于任务队列信息的,主要有DBA_JOBS, USER_JOBS和DBA_JOBS_RUNNING。这些字典视图是由名为CATJOBQ.SQL的脚本文件创建的。该脚本文件和创建DBMS_JOB包的脚本文件一样在ORACLE_HOME目录的rdbms/admin子目录中,同样也是由脚本文件CATPROC.SQL调用。

最后,要使任务队列能正常运行,还必须启动它自己专有的后台过程。启动后台过程是通过在初始化文件init*.ora(实例不同,初始化文件名也略有不同)中设置初始化参数来进行的。下面就是该参数:

JOB_QUEUE_PROCESSES = n

其中,n可以是0到36之间的任何一个数。除了该参数以外,还有几个关于任务队列的初始化参数,本文后面将会对其进行详细讨论。

DBMS_JOB包中包含有许多过程,见表1所示。

表1 DBMS_JOB包

名称类型描述
DBMS_JOB.ISUBMIT过程提交一个新任务,用户指定一个任务号
DBMS_JOB.SUBMIT过程提交一个新任务,系统指定一个任务号
DBMS_JOB.REMOVE过程从队列中删除一个已经存在的任务
DBMS_JOB.CHANGE过程更改用户设定的任务参数
DBMS_JOB.WHAT过程更改PL/SQL任务定义
DBMS_JOB.NEXT_DATE过程更改任务下一次运行时间
DBMS_JOB.INTERVAL过程更改任务运行的时间间隔
DBMS_JOB.BROKEN过程将任务挂起,不让其重复运行
DBMS_JOB.RUN过程在当前会话中立即执行任务
DBMS_JOB.USER_EXPORT过程创建文字字符串,用于重新创建一个任务
三、DBMS_JOB包参数
DBMS_JOB包中所有的过程都有一组相同的公共参数,用于定义任务,任务的运行时间以及任务定时运行的时间间隔。这些公共任务定义参数见表2所示。

表2 DBMS_JOB过程的公共参数

名称类型注释
JobBINARY_INTEGER任务的唯一识别号
WhatVARCHAR2作为任务执行的PL/SQL代码
Next_dateVARCHAR2任务下一次运行的时间
IntervalVARCHAR2日期表达式,用来计算下一次任务运行的时间
下面我们来详细讨论这些参数的意义及用法。

1、job
参数job是一个整数,用来唯一地标示一个任务。该参数既可由用户指定也可由系统自动赋予,这完全取决于提交任务时选用了那一个任务提交过程。DBMS_JOB.SUBMIT过程通过获得序列SYS.JOBSEQ的下一个值来自动赋予一个任务号。该任务号是作为一个OUT参数返回的,所以调用者随后可以识别出提交的任务。而DBMS_JOB.ISUBMIT过程则由调用者给任务指定一个识别号,这时候,任务号的唯一性就完全取决于调用者了。

除了删除或者重新提交任务,一般来说任务号是不能改变的。即使当数据库被导出或者被导入这样极端的情况,任务号也将被保留下来。所以在执行含有任务的数据的导入/导出操作时很可能会发生任务号冲突的现象。

2、what
what参数是一个可以转化为合法PL/SQL调用的字符串,该调用将被任务队列自动执行。在what参数中,如果使用文字字符串,则该字符串必须用单引号括起来。 what参数也可以使用包含我们所需要字符串值的VARCHAR2变量。实际的PL/SQL调用必须用分号隔开。在PL/SQL调用中如果要嵌入文字字符串,则必须使用两个单引号。

what参数的长度在Oracle7.3中限制在2000个字节以内,在Oracle 8.0以后,扩大到了4000个字节,这对于一般的应用已完全足够。该参数的值一般情况下都是对一个PL/SQL存储过程的调用。在实际应用中,尽管可以使用大匿名Pl/SQL块,但建议大家最好不要这样使用。还有一个实际经验就是最好将存储过程调用封装在一个匿名块中,这样可以避免一些比较莫名错误的产生。我来举一个例子,一般情况下,what参数可以这样引用:

what =>’my_procedure(parameter1);’
但是比较安全的引用,应该这样写:

what =>’begin my_procedure(parameter1); end;’
任何时候,我们只要通过更改what参数就可以达到更改任务定义的目的。但是有一点需要注意,通过改变what参数来改变任务定义时,用户当前的会话设置也被记录下来并成为任务运行环境的一部分。如果当前会话设置和最初提交任务时的会话设置不同,就有可能改变任务的运行行为。意识到这个潜在的副作用是非常重要的,无论何时只要应用到任何DBMS_JOB过程中的what参数时就一定要确保会话设置的正确。

3、next_date
Next_date参数是用来调度任务队列中该任务下一次运行的时间。这个参数对于DBMS_JOB.SUBMIT和DBMS_JOB.BROKEN这两个过程确省为系统当前时间,也就是说任务将立即运行。

当将一个任务的next_date参数赋值为null时,则该任务下一次运行的时间将被指定为4000年1月1日,也就是说该任务将永远不再运行。在大多数情况下,这可能是我们不愿意看到的情形。但是,换一个角度来考虑,如果想在任务队列中保留该任务而又不想让其运行,将next_date设置为null却是一个非常简单的办法。

Next_date也可以设置为过去的一个时间。这里要注意,系统任务的执行顺序是根据它们下一次的执行时间来确定的,于是将next_date参数设置回去就可以达到将该任务排在任务队列前面的目的。这在任务队列进程不能跟上将要执行的任务并且一个特定的任务需要尽快执行时是非常有用的。

4、Interval
Internal参数是一个表示Oracle合法日期表达式的字符串。这个日期字符串的值在每次任务被执行时算出,算出的日期表达式有两种可能,要么是未来的一个时间要么就是null。这里要强调一点:很多开发者都没有意识到next_date是在一个任务开始时算出的,而不是在任务成功完成时算出的。

当任务成功完成时,系统通过更新任务队列目录表将前面算出的next_date值置为下一次任务要运行的时间。当由interval表达式算出next_date是null时,任务自动从任务队列中移出,不会再继续执行。因此,如果传递一个null值给interval参数,则该任务仅仅执行一次。

通过给interval参数赋各种不同的值,可以设计出复杂运行时间计划的任务。本文后面的“任务间隔和日期算法”将对interval表达式进行详细讨论,并给出一个实际有用interval表达式的例子。

四、任务队列架构和运行环境
任务队列在Oracle系统中其实是一个子系统,它具有自己特定的后台过程和目录表。该子系统设计的目的是为了能不在用户干预下自动运行PL/SQL过程。

1、任务队列后台过程
任务队列(SNP)后台过程随着Oracle实例的启动而同时启动。在文章前面已经谈到初始化文件init.ora中的参数JOB_QUEUE_PROCESSES,用来设置有几个队列过程。这里设置了几个过程,系统中就会有几个SNP过程被启动。JOB_QUEUE_PROCESSES这个参数,可以是0到36中的任何一个数,也就是说对于每个Oracle实例最多可以有36个SNP过程,也可以不支持队列过程(=0)。在大多数操作系统中,SNP三个字母常作为过程名的一部分出现。如,在unix系统中,如果该Oracle实例名为ora8,有三个任务队列过程,则这三个任务队列过程名称为:

ora_ora8_snp0
ora_ora8_snp1
ora_ora8_snp2
SNP后台过程和其他的Oracle后台过程的一个重要区别就是杀掉一个SNP过程不会影响到Oracle实例。当一个任务队列过程失控或者消耗太多的资源时,就可以将其杀掉,当然这种情况不是经常遇到的。当一个SNP过程被杀掉或者失败时,Oracle就自动启动一个新的SNP过程来代替它。

2、有关任务队列的初始化参数
初始化文件init.ora中的几个参数控制着任务队列后台的运行,下面我们将对其进行详细讨论。

(1)、JOB_QUEUE_INTERVAL
任务队列过程定期唤醒并检查任务队列目录表是否有任务需要执行。参数JOB_QUEUE_INTERVAL决定SNP过程两次检查目录表之间“休眠”多长时间(单位为秒)。间隔设的太小会造成由于SNP过程不断检查目录表而导致不必要的系统吞吐量。相反如果间隔设得太大,SNP过程在特定的时间没有被唤醒,那个时间的任务就不会能被运行。最佳的时间间隔设置要综合考虑系统环境中不同的任务,60秒的确省设置可以满足大多数的应用。

(2)、JOB_QUEUE_KEEP_CONNECTIONS
除了前面介绍的JOB_QUEUE_PROCESS和JOB_QUEUE_INTERVAL两个参数以外,影响SNP后台过程行为的第三个参数是JOB_QUEUE_KEEP_CONNECTIONS。当该参数为TRUE时,SNP过程在两个任务的运行期间(也就是休眠期间),仍然和Oracle保持开放的连接。相反,如果为FALSE时,SNP过程将和数据库断开连接,当唤醒时刻到来时又重新连接并检查任务队列。

选择这两种方法中的那一种,主要是考虑任务队列的有效性和数据库关闭方法。长期保持连接的效率比较高,但任务队列会受到正常关闭数据库的影响。这是因为任务队列过程对于服务器管理器看来和一个普通用户的过程没有什么不同,而正常的关闭数据库需要让所有的用户都断开连接。而断开连接和重新连接又给数据库增加了负荷,但是可定期地使数据库没有可连接SNP过程,也就可以使数据库正常关闭。对于有很多任务或者是任务重复执行的时间间隔较短(一个小时或者更少)的环境,一般将JOB_QUEUE_KEEP_CONNECTIOONS设置为TRUE,并修改关闭数据库的脚本为立即关闭。对于严格要求采用正常方式关闭的数据库或者是任务较少,重复间隔较长的环境,一般将该参数设置为FALSE。最好,要提醒一句,SNP过程仅在没有任何任务运行时才断开,这种情况下,那些需要比较长时间运行的任务SNP将在它们的生命周期内一致保持开放的连接,这就延迟了正常关闭数据库的时间。

3、建立运行环境
当SNP过程唤醒时,它首先查看任务队列目录中所有的任务是否当前的时间超过了下一次运行的日期时间。SNP检测到需要该时间立即执行的任务后,这些任务按照下一次执行日期的顺序依次执行。当SNP过程开始执行一个任务时,其过程如下:

以任务所有者的用户名开始一个新的数据库会话。
当任务第一次提交或是最后一次被修改时,更改会话NLS设置和目前就绪的任务相匹配。
通过interval日期表达式和系统时间,计算下一次执行时间。
执行任务定义的PL/SQL
如果运行成功,任务的下一次执行日期(next_date)被更新,否则,失败计数加1。
经过JOB_QUEUS_INTERVAL秒后,又到了另一个任务的运行时间,重复上面的过程。
在前两步中,SNP过程创建了一个模仿用户运行任务定义的PL/SQL的会话环境。然而,这个模仿的运行环境并不是和用户实际会话环境完全一样,需要注意以下两点:第一,在任务提交时任何可用的非确省角色都将在任务运行环境中不可用。因此,那些想从非确省角色中取得权限的任务不能提交,用户确省角色的修改可以通过在任务未来运行期间动态修改来完成。第二,任何任务定义本身或者过程执行中需要的数据库联接都必须完全满足远程的用户名和密码。SNP过程不能在没有显式指明口令的情况下初始化一个远程会话。显然,SNP过程不能假定将本地用户的口令作为远程运行环境会话设置的一部分。

提交的任务如果运行失败会怎么样呢?当任务运行失败时,SNP过程在1分钟后将再次试图运行该任务。如果这次运行又失败了,下一次尝试将在2分钟后进行,再下一次在4分钟以后。任务队列每次加倍重试间隔直到它超过了正常的运行间隔。在连续16次失败后,任务就被标记为中断的(broken),如果没有用户干预,任务队列将不再重复执行。

五、任务队列字典表和视图
任务队列中的任务信息可以通过表3所示的几个字典视图来查看,这些视图是由CATJOBQ.sql脚本创建的。表4和5是各个视图每个字段的含义。

表3. 任务队列中关于任务的数据字典视图

视图名描述
DBA_JOBS本数据库中定义到任务队列中的任务
DBA_JOBS_RUNNING目前正在运行的任务
USER_JOBS当前用户拥有的任务
表4. DBA_JOBS 和 USER_JOBS.字典视图的字段含义

字段(列)类型描述
JOBNUMBER任务的唯一标示号
LOG_USERVARCHAR2(30)提交任务的用户
PRIV_USERVARCHAR2(30)赋予任务权限的用户
SCHEMA_USERVARCHAR2(30)对任务作语法分析的用户模式
LAST_DATEDATE最后一次成功运行任务的时间
LAST_SECVARCHAR2(8)如HH24:MM:SS格式的last_date日期的小时,分钟和秒
THIS_DATEDATE正在运行任务的开始时间,如果没有运行任务则为null
THIS_SECVARCHAR2(8)如HH24:MM:SS格式的this_date日期的小时,分钟和秒
NEXT_DATEDATE下一次定时运行任务的时间
NEXT_SECVARCHAR2(8)如HH24:MM:SS格式的next_date日期的小时,分钟和秒
TOTAL_TIMENUMBER该任务运行所需要的总时间,单位为秒
BROKENVARCHAR2(1)标志参数,Y标示任务中断,以后不会运行
INTERVALVARCHAR2(200)用于计算下一运行时间的表达式
FAILURESNUMBER任务运行连续没有成功的次数
WHATVARCHAR2(2000)执行任务的PL/SQL块
CURRENT_SESSION_LABELRAW MLSLABEL该任务的信任Oracle会话符
CLEARANCE_HIRAW MLSLABEL该任务可信任的Oracle最大间隙
CLEARANCE_LORAW MLSLABEL该任务可信任的Oracle最小间隙
NLS_ENVVARCHAR2(2000)任务运行的NLS会话设置
MISC_ENVRAW(32)任务运行的其他一些会话参数
表 5. 视图DBA_JOBS_RUNNING的字段含义

列数据类型描述
SIDNUMBER目前正在运行任务的会话ID
JOBNUMBER任务的唯一标示符
FAILURESNUMBER连续不成功执行的累计次数
LAST_DATEDATE最后一次成功执行的日期
LAST_SECVARCHAR2(8)如HH24:MM:SS格式的last_date日期的小时,分钟和秒
THIS_DATEDATE目前正在运行任务的开始日期
THIS_SECVARCHAR2(8)如HH24:MM:SS格式的this_date日期的小时,分钟和秒
六、任务重复运行间隔和间隔设计算法
任务重复运行的时间间隔取决于interval参数中设置的日期表达式。下面就来详细谈谈该如何设置interval参数才能准确满足我们的任务需求。一般来讲,对于一个任务的定时执行,有三种定时要求。

在一个特定的时间间隔后,重复运行该任务。
在特定的日期和时间运行任务。
任务成功完成后,下一次执行应该在一个特定的时间间隔之后。
第一种调度任务需求的日期算法比较简单,即’SYSDATE+n’,这里n是一个以天为单位的时间间隔。表6给出了一些这种时间间隔设置的例子。

表6 一些简单的interval参数设置例子

描述Interval参数值
每天运行一次’SYSDATE + 1′
每小时运行一次’SYSDATE + 1/24′
每10分钟运行一次’SYSDATE + 10/(60*24)’
每30秒运行一次’SYSDATE + 30/(60*24*60)’
每隔一星期运行一次’SYSDATE + 7′
不再运行该任务并删除它NULL
表6所示的任务间隔表达式不能保证任务的下一次运行时间在一个特定的日期或者时间,仅仅能够指定一个任务两次运行之间的时间间隔。例如,如果一个任务第一次运行是在凌晨12点,interval指定为’SYSDATE + 1′,则该任务将被计划在第二天的凌晨12点执行。但是,如果某用户在下午4点手工(DBMS_JOB.RUN)执行了该任务,那么该任务将被重新定时到第二天的下午4点。还有一个可能的原因是如果数据库关闭或者说任务队列非常的忙以至于任务不能在计划的那个时间点准时执行。在这种情况下,任务将试图尽快运行,也就是说只要数据库一打开或者是任务队列不忙就开始执行,但是这时,运行时间已经从原来的提交时间漂移到了后来真正的运行时间。这种下一次运行时间的不断“漂移”是采用简单时间间隔表达式的典型特征。

第二种调度任务需求相对于第一种就需要更复杂的时间间隔(interval)表达式,表7是一些要求在特定的时间运行任务的interval设置例子。

表 7. 定时到特定日期或时间的任务例子

描述INTERVAL参数值
每天午夜12点’TRUNC(SYSDATE + 1)’
每天早上8点30分’TRUNC(SYSDATE + 1) + (8*60+30)/(24*60)’
每星期二中午12点’NEXT_DAY(TRUNC(SYSDATE ), ”TUESDAY” ) + 12/24′
每个月第一天的午夜12点’TRUNC(LAST_DAY(SYSDATE ) + 1)’
每个季度最后一天的晚上11点’TRUNC(ADD_MONTHS(SYSDATE + 2/24, 3 ), ‘Q’ ) -1/24′
每星期六和日早上6点10分’TRUNC(LEAST(NEXT_DAY(SYSDATE, ”SATURDAY”), NEXT_DAY(SYSDATE, “SUNDAY”))) + (6×60+10)/(24×60)’
第三种调度任务需求无论通过怎样设置interval日期表达式也不能满足要求。这时因为一个任务的下一次运行时间在任务开始时才计算,而在此时是不知道任务在何时结束的。遇到这种情况怎么办呢?当然办法肯定是有的,我们可以通过为任务队列写过程的办法来实现。这里我只是简单介绍以下,可以在前一个任务队列执行的过程中,取得任务完成的系统时间,然后加上指定的时间间隔,拿这个时间来控制下一个要执行的任务。这里有一个前提条件,就是目前运行的任务本身必须要严格遵守自己的时间计划。

结论
Oracle中的定时任务是在Oracle系统中是一个非常重要的子系统,运用得当,可以极大的提高我们的系统运行和维护能力。而Oracle数据复制的延迟事务队列管理完全是基于Oracle的队列任务,对其的深刻理解有助于我们更好地管理数据复制。

可以在控制台杀除相应的 snp 调度 Job 的进程

root@erp # ps -ef|grep snp
  ora805  3745     1  6 10:51:52 ?        9:17 ora_snp1_PROD
  ora805  3749     1  4 10:51:52 ?        3:23 ora_snp3_PROD
  ora805  3751     1  6 10:51:52 ?        6:52 ora_snp4_PROD
  ora805  3747     1  6 10:51:52 ?        8:58 ora_snp2_PROD
  ora805  3770     1  4 10:52:56 ?        4:36 ora_snp0_PROD

root@erp # kill -9 3745 3749

杀了某些 job_queue_process 后 Oracle 又会自动启动相应数据的 snp 进程。

sqlplus 中可用 select * from dba_jobs_running 显示正在执行的 Job,记录数一般就是 job_queue_processes 参数的数量。

show parameter job_queue_processes 显示进程数
alter system set job_queue_processes=10 [scope=memory|scope=spfile|scope=both] 来设置调度 job 的进程数

例:在Toad界面下。选择databases->Procedure Editor
//也可以直接在sql界面下执行//也可以直接在isql*plus界面下执行

create procedure bertelsmann as
begin

&& INSERT INTO RECORD SELECT CUSSENT.* FROM CUSSENT WHERE ADDDATE< =TO_DATE(to_char(add_months(sysdate,-3),'yyyy-MM-dd hh24:mi:ss'),'yyyy-mm-dd hh24:mi:ss');
&DELETE FROM CUSSENT WHERE ADDDATE<=TO_DATE (to_char(add_months(sysdate,-3),'yyyy-MM-dd hh24:mi:ss'),'yyyy-mm-dd hh24:mi:ss');

&COMMIT;

end;

-- 以上创建一个名为bertelsmann的过程。作用时向表record中插入cussent表中日期小于当前日期三个月的记录
然后删除cussent表中的数据,删除掉刚才插入record(备份表中的数据)

这样一个过程创建 好了。
在Procedures下面能看到我们所创建的过程。。

然后我要让他每三个月执行一次该备份的功能

declare v_job number:=1;

begin

dbms_job.submit(v_job,'bertelsmann;',sysdate,'sysdate+1/1440');

commit;

end;

使用回闪或不完全恢复来恢复所删除的用户

数据库启用了回闪时恢复删除了用户

rman>shutdown
rman>startup mount;
rman>alter database flashback on;
rman>alter database open;

于 2012-02-24 15:25:08删除用户test

drop user test cascade;

使用回闪恢复数据库

rman>shutdown
rman>startup mount;

使用回闪语句

RMAN> flashback database to time "to_date('2012-02-24 15:24:00','yyyy-mm-dd hh24
:mi:ss')";
RMAN> alter database open resetlogs;

数据库已打开

在归档模式下recover database是将数据库恢复到它可以恢复到出现介质故障的时间点,并会应用到这一时间的所有重做日志文件.
--------------
有完全备份和归档重做日志时恢复删除了用户
RMAN> backup database;

启动 backup 于 2012-02-24 16:36:19
使用通道 ORA_DISK_1
通道 ORA_DISK_1: 启动全部数据文件备份集
通道 ORA_DISK_1: 正在指定备份集中的数据文件
输入数据文件 fno=00004 name=D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\HYGEIA01.DBF
输入数据文件 fno=00005 name=D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\HYGEIA02.DBF
输入数据文件 fno=00001 name=D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\SYSTEM01.DBF
输入数据文件 fno=00003 name=D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\SYSAUX01.DBF
输入数据文件 fno=00002 name=D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\UNDOTBS01.DBF
通道 ORA_DISK_1: 正在启动段 1 于 2012-02-24 16:36:20
通道 ORA_DISK_1: 已完成段 1 于 2012-02-24 16:51:05
段句柄=D:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\OCP\BACKUPSET\2012_02_24\O1_
MF_NNNDF_TAG20120224T163620_7NGM04K2_.BKP 标记=TAG20120224T163620 注释=NONE
通道 ORA_DISK_1: 备份集已完成, 经过时间:00:14:45
通道 ORA_DISK_1: 启动全部数据文件备份集
通道 ORA_DISK_1: 正在指定备份集中的数据文件
备份集中包括当前控制文件
在备份集中包含当前的 SPFILE
通道 ORA_DISK_1: 正在启动段 1 于 2012-02-24 16:51:07
通道 ORA_DISK_1: 已完成段 1 于 2012-02-24 16:51:08
段句柄=D:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\OCP\BACKUPSET\2012_02_24\O1_
MF_NCSNF_TAG20120224T163620_7NGMVVNJ_.BKP 标记=TAG20120224T163620 注释=NONE
通道 ORA_DISK_1: 备份集已完成, 经过时间:00:00:03
完成 backup 于 2012-02-24 16:51:08

于 2012-02-24 16:54:08删除用户test

drop user test cascade;

使用不完全恢复恢复数据库

rman>shutdown
rman>startup nomount;
rman>restore controlfile to 'D:\oracle\product\10.2.0\oradata\ocp\control01.ctl';
rman>startup mount;
rman>restore database;
rman>recover database until time '2012-02-24 16:53:00';
rman>alter database open resetlogs;

另一种写法是

RMAN> run
2> {
3> set until time '2012-02-24 16:52:30';
4> restore database;
5> recover database;
6> }

正在执行命令: SET until clause

启动 restore 于 2012-02-24 17:20:36
使用通道 ORA_DISK_1

通道 ORA_DISK_1: 正在开始恢复数据文件备份集
通道 ORA_DISK_1: 正在指定从备份集恢复的数据文件
正将数据文件00001恢复到D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\SYSTEM01.DBF
正将数据文件00002恢复到D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\UNDOTBS01.DBF
正将数据文件00003恢复到D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\SYSAUX01.DBF
正将数据文件00004恢复到D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\HYGEIA01.DBF
正将数据文件00005恢复到D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\HYGEIA02.DBF
通道 ORA_DISK_1: 正在读取备份段 D:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\OCP
\BACKUPSET\2012_02_24\O1_MF_NNNDF_TAG20120224T163620_7NGM04K2_.BKP
通道 ORA_DISK_1: 已恢复备份段 1
段句柄 = D:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\OCP\BACKUPSET\2012_02_24\O
1_MF_NNNDF_TAG20120224T163620_7NGM04K2_.BKP 标记 = TAG20120224T163620
通道 ORA_DISK_1: 恢复完成, 用时: 00:11:57
完成 restore 于 2012-02-24 17:32:38

启动 recover 于 2012-02-24 17:32:49
使用通道 ORA_DISK_1

正在开始介质的恢复
介质恢复完成, 用时: 00:00:15

完成 recover 于 2012-02-24 17:34:42

RMAN> alter database open resetlogs;

数据库已打开




在非归档模式下不完全恢复

RMAN> backup database;

启动 backup 于 2012-02-25 10:11:09
使用通道 ORA_DISK_1
通道 ORA_DISK_1: 启动全部数据文件备份集
通道 ORA_DISK_1: 正在指定备份集中的数据文件
输入数据文件 fno=00004 name=D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\HYGEIA01.DBF
输入数据文件 fno=00005 name=D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\HYGEIA02.DBF
输入数据文件 fno=00001 name=D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\SYSTEM01.DBF
输入数据文件 fno=00002 name=D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\UNDOTBS01.DBF
输入数据文件 fno=00003 name=D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\SYSAUX01.DBF
通道 ORA_DISK_1: 正在启动段 1 于 2012-02-25 10:11:11
通道 ORA_DISK_1: 已完成段 1 于 2012-02-25 10:26:26
段句柄=D:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\OCP\BACKUPSET\2012_02_25\O1_
MF_NNNDF_TAG20120225T101110_7NJJSZL2_.BKP 标记=TAG20120225T101110 注释=NONE
通道 ORA_DISK_1: 备份集已完成, 经过时间:00:15:15
通道 ORA_DISK_1: 启动全部数据文件备份集
通道 ORA_DISK_1: 正在指定备份集中的数据文件
备份集中包括当前控制文件
在备份集中包含当前的 SPFILE
通道 ORA_DISK_1: 正在启动段 1 于 2012-02-25 10:26:28
通道 ORA_DISK_1: 已完成段 1 于 2012-02-25 10:26:29
段句柄=D:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\OCP\BACKUPSET\2012_02_25\O1_
MF_NCSNF_TAG20120225T101110_7NJKPNL2_.BKP 标记=TAG20120225T101110 注释=NONE
通道 ORA_DISK_1: 备份集已完成, 经过时间:00:00:03
完成 backup 于 2012-02-25 10:26:29

RMAN> alter database open;

数据库已打开

于 2012-02-25 11:01:29 删除test用户

rman>shutdown;
rman>startup mount;
RMAN> restore database;

启动 restore 于 2012-02-25 11:11:20
使用通道 ORA_DISK_1

通道 ORA_DISK_1: 正在开始恢复数据文件备份集
通道 ORA_DISK_1: 正在指定从备份集恢复的数据文件
正将数据文件00001恢复到D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\SYSTEM01.DBF
正将数据文件00002恢复到D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\UNDOTBS01.DBF
正将数据文件00003恢复到D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\SYSAUX01.DBF
正将数据文件00004恢复到D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\HYGEIA01.DBF
正将数据文件00005恢复到D:\ORACLE\PRODUCT\10.2.0\ORADATA\OCP\HYGEIA02.DBF
通道 ORA_DISK_1: 正在读取备份段 D:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\OCP
\BACKUPSET\2012_02_25\O1_MF_NNNDF_TAG20120225T101110_7NJJSZL2_.BKP
通道 ORA_DISK_1: 已恢复备份段 1
段句柄 = D:\ORACLE\PRODUCT\10.2.0\FLASH_RECOVERY_AREA\OCP\BACKUPSET\2012_02_25\O
1_MF_NNNDF_TAG20120225T101110_7NJJSZL2_.BKP 标记 = TAG20120225T101110
通道 ORA_DISK_1: 恢复完成, 用时: 00:12:15
完成 restore 于 2012-02-25 11:23:36

RMAN> recover database until time '2012-02-25 10:30:00';

启动 recover 于 2012-02-25 11:25:16
使用通道 ORA_DISK_1

正在开始介质的恢复
介质恢复完成, 用时: 00:00:03

完成 recover 于 2012-02-25 11:25:31

RMAN> alter database open resetlogs;

数据库已打开

在执行alter database open resetlogs如果报
ORA-01190: 控制文件或数据文件 4 来自最后一个 RESETLOGS 之前
ORA-01110: 数据文件 4: ‘E:\ORACLE\PRODUCT\10.2.0\ORADATA\TEST\USERS01.DBF’
可以设置初始化参数_allow_resetlogs_corruption=true这个参数是允许控制文件与数据文件的scn不一至情况下启动数据库 _allow_terminal_recovery_corruption=ture 允许恢复错误
再执行alter database open resetlogs如果还是报错

CREATE CONTROLFILE   set Database op  Resetlogs
  MAXLOGFILES 16
  MAXLOGMEMBERS 3
  MAXDATAFILES 100
  MAXINSTANCES 8
  MAXLOGHISTORY 292
LOGFILE
GROUP 1 'C:\oracle\product\10.2.0\oradata\op\RED001.LOG'SIZE 50M,
GROUP 2 'C:\oracle\product\10.2.0\oradata\op\RED002.LOG'SIZE 50M,
GROUP 3 'C:\oracle\product\10.2.0\oradata\opRED003.LOG'SIZE 50M
DATAFILE
'D:\oradata\SYSTEM01.DBF',--要恢复的数据所在的dbf文件
'D:\oradata\UNDOTBS01.DBF',--要恢复的数据所在的dbf文件
'D:\oradata\SYSAUX01.DBF',--要恢复的数据所在的dbf文件
'D:\oradata\USERS01.DBF',--要恢复的数据所在的dbf文件
'D:\oradata\EXAMPLE01.DBF',--要恢复的数据所在的dbf文件
'D:\oradata\HYGEIA01.DBF',--要恢复的数据所在的dbf文件
'D:\oradata\HYGEIA02.DBF',--要恢复的数据所在的dbf文件
'D:\oradata\HYGEIA03.DBF'--要恢复的数据所在的dbf文件
CHARACTER SET ZHS16GBK

再执行

alter database open  resetlogs;

重新创建临时表空间
查看恢复后结果

查看当前oracle中正在执行的sql语句

先执行以下查询语句

select a.program, b.spid, c.sql_text,c.SQL_ID
  from v$session a, v$process b, v$sqlarea c
 where a.paddr = b.addr
   and a.sql_hash_value = c.hash_value
   and a.username is not null;
PROGRAM                         SPID    SQL_TEXT                  SQL_ID
---------------------------------------------------------------- -------------
racgimon@cdcj1 (TNS V1-V3)      12      DECLARE     reason_id    65vuzhm491wk9
oracleRLZY@rx6600-2 (TNS V1-V3) 25867   SELECT "AKB020" FROM "KB 09rp36jmgpj5a
oracleRLZY@rx6600-2 (TNS V1-V3) 25869   SELECT "AAC001","BTC102" 00931052n13uq
oracleRLZY@rx6600-2 (TNS V1-V3) 3018    SELECT "AAC001","BTC102" 00931052n13uq
plsqldev.exe                    26531   select a.program, b.spid 5qq47bz3tzfws
JDBC Thin Client                21074   select * from ( select r 686nqabc8sgs2

如上图中的program列中的jdbc thin client代表的是通过jdbc连接执行的sql语句,由于sql_text列没有显示完整
的sql语句.所以找到sql_id:686nqabc8sgs2再查询v$sql

select a.* from v$sql a where a.SQL_ID='686nqabc8sgs2'

可以查看完整的sql文本内容

Oracle使用审计监控用户执行过的SQL语句

监控用户执行过的SQL语句,经常会使用查询V$SQL等视图,但这样查不出来多次执行相同的SQL语句,使用审计可以解决这个问题,这里采用精细审计某个用户的所有表。

用sys用户登记
创建下面的的过程

create or replace procedure auditUser(auditUser in varchar2,oper in int)
is
       policyName varchar2(2000);
       policynum varchar2(20);
       cursor tables is select object_name from dba_objects where wner=auditUser and              object_type='TABLE';
begin

       for tableName in tables loop
           begin
           policynum := 'AUDIT1_';
           policyName := concat(policynum,tableName.Object_Name);
           if per=1 then
           dbms_fga.add_policy(object_schema=>auditUser,object_name=>  tableName.Object_Name,policy_name => policyName,
           statement_types=>'select,insert,update,delete',enable=>true);
           end if;
           if per=0 then
           dbms_fga.drop_policy(object_schema=>auditUser,object_name=>tableName.Object_Name,policy_name => policyName);
           end if;
           exception
              when others then
               NULL;
           end;
       end loop;
       commit;
end;

查询建立的审计策略:

select * from DBA_AUDIT_POLICIES

入参auditUser 表示要审计的用户,oper=1表示审计用户的所有表,oper=0表示删除审计策略
审计完成之后最好删除建立的审计策略。
查询执行过的SQL语句:

select timestamp,db_user,os_user,sql_text from dba_fga_audit_trail order by timestamp desc

系统允许一段时间之后,数据量增加,查询会很慢,可删除表数据

truncate table fga_log$

pl/sql中bulk collect的用法

bulk collect可以将查询结果一次性地加载到collections中,而不用一条一条地处理。
在select into,fetch into,returning into语句使用使用bulk collect时,所有的into变量都必须是collections。

create table jy
(
object_id number(12),
object_name varchar2(20),
object_type varchar2(20)
)

在select into语句中使用bulk collect

declare
type object_list is table of jy.object_name%type;
objs object_list;
begin
select object_name bulk collect
into objs
from jy;
for r in objs.first .. objs.last loop
dbms_output.put_line(''|| objs(r));
end loop;
end;
/

在fetch into中使用bulk collect

declare
type objecttab is table of jy%rowtype;
objs objecttab;
cursor cob is
select object_id, object_name, object_type
from jy;
begin
open cob;
fetch cob bulk collect
into objs;
close cob; -- 把结果集一次fetch到collect中,我们还可以通过limit参数,来分批fetch数据
for r in objs.first .. objs.last loop
dbms_output.put_line(' ' || objs(r).object_name);
end loop;
end;



declare
type objecttab is table of jy%rowtype;
objs objecttab;
cursor cob is
select object_id, object_name, object_type
from jy;
begin
open cob;
loop
fetch cob bulk collect
into objs limit 100;--每次取一百条数据这是可以根据你的数据库性能来决定的
exit when cob%notfound;
dbms_output.put_line('count:' || objs.count || ' first:' || objs.first ||
' last:' || objs.last);
for r in objs.first .. objs.last loop
dbms_output.put_line(' objs(r)=' || objs(r).object_name);
end loop;
end loop;
close cob;
end;

在returning into中使用bulk collect

declare
type id_list is table of jy.object_id%type;
ids id_list;
type name_list is table of jy.object_name%type;
names name_list;
begin
delete from jy  returning object_id, object_name bulk collect into ids,
names;
dbms_output.put_line('deleted ' || sql%rowcount || ' rows:');
for i in ids.first .. ids.last loop
dbms_output.put_line('object #' || ids(i) || ': ' || names(i));
end loop;
end;

ORACLE批量绑定FORALL与BULK COLLECT
FORALL与BULK COLLECT的使用方法:
1.使用FORALL比FOR效率高,因为前者只切换一次上下文,而后者将是在循环次数一样多个上下文间切换。
2.使用BLUK COLLECT一次取出一个数据集合,比用游标条取数据效率高,尤其是在网络不大好的情况下。但BLUK COLLECT需要大量内存。

create table test_forall ( user_id number(10), user_name varchar2(20));

select into 中使用bulk collect

DECLARE
  TYPE table_forall IS TABLE OF test_forall%ROWTYPE;
  v_table table_forall;
BEGIN
    SELECT mub.user_id,mub.user_name
         BULK COLLECT INTO v_table
    FROM mag_user_basic mub
         WHERE mub.user_id BETWEEN 10000 AND 10100;
    FORALL idx IN 1..v_table.COUNT
           INSERT INTO test_forall VALUES v_table(idx);
           --VALUES(v_table(idx).user_id,v_table(idx).user_name);Error
           --在PL/SQL中,BULK In-BIND与RECORD,%ROWTYPE是不能在一块使用的,
           --也就是说,BULK In-BIND只能与简单类型的数组一块使用
    COMMIT;
EXCEPTION
    WHEN OTHERS THEN
        ROLLBACK;

END;

fetch into 中使用bulk collect

DECLARE
  TYPE table_forall IS TABLE OF test_forall%ROWTYPE;
  v_table table_forall;

  CURSOR c1 IS
    SELECT mub.user_id,mub.user_name
         FROM mag_user_basic mub
           WHERE mub.user_id BETWEEN 10000 AND 10100;
BEGIN
   OPEN c1;
   --在fetch into中使用bulk collect
   FETCH c1 BULK COLLECT INTO v_table;

   FORALL idx IN 1..v_table.COUNT
         INSERT INTO test_forall VALUES v_table(idx);
    COMMIT;
EXCEPTION
    WHEN OTHERS THEN
        ROLLBACK;
END;

在returning into中使用bulk collect

CREATE TABLE test_forall2 AS SELECT * FROM test_forall;

—-在returning into中使用bulk collect

DECLARE
   TYPE IdList IS TABLE OF test_forall.User_Id%TYPE;
   enums IdList;
   TYPE NameList IS TABLE OF test_forall.user_name%TYPE;
   names NameList;
BEGIN
   DELETE FROM test_forall2 WHERE user_id = 10100
        RETURNING user_id, user_name BULK COLLECT INTO enums, names;
   dbms_output.put_line('Deleted ' || SQL%ROWCOUNT || ' rows:');
   FOR i IN enums.FIRST .. enums.LAST
   LOOP
     dbms_output.put_line('User #' || enums(i) || ': ' || names(i));
   END LOOP;
   COMMIT;

EXCEPTION
    WHEN OTHERS THEN
        ROLLBACK;

END;

–批量更新中,将for改成forall

DECLARE
    TYPE NumList IS VARRAY(20) OF NUMBER;
    depts NumList := NumList(10, 30, 70, ...);
 -- department numbers
     BEGIN
    
       /*FOR i IN depts.FIRST..depts.LAST
       LOOP
       ...
       --UPDATE statement is sent to the SQL engine
       -- with each iteration of the FOR loop!
         UPDATE emp SET sal = sal * 1.10 WHERE deptno = depts(i);
       END LOOP:
      */
       FORALL i IN depts.FIRST..depts.LAST
        UPDATE emp SET sal = sal * 1.10 WHERE deptno = depts(i);
       commit;
    END;