Hey!! Sky!

Aug 01, 2006

Oracle PL/SQL Programming 读书笔记(Numbers)

Numbers


1.基本数字类型
  NUMBER
    可以存储任何大小的 integer, fixed-point, or floating-point numbers。他是平台无关的,在任何硬件平台上,在 NUMBER 上的计算结果都是相同的。Oracle database engin 和 PL/SQL engin 都支持。
    DECLARE x NUMBER;                     --floating-point number
            y NUMBER (precision, scale)   --fixed-point number 
              precision 1 ~ 38   scale -84 ~ 127
              三种情况:
               (1)precision > scale > 0  NUMBER(9,2)
                    precision-scale.scale   000000000.00 ~ 9999999.99
               (2)precision < scale       NUMBER(9,11)  可以存储很小的数,精确度很高
                    precisionE-scale        0.00000000000 ~ 0.00999999999
               (3)scale < 0               NUMBER(9,-11) 可以存储很大的数,但精确度很低
                    precisionE-scale        00000000000 ~ 99999999900000000000
            z NUMBER(precision,0); = z NUMBER(precision); --integer number


  PLS_INTEGER and BINARY_INTEGER(只由 PL/SQL engin 支持)
    PLS_INTEGER:
      Values are represented using your hardware platform's native integer format.
      范围:-2,147,483,647 ~ 2,147,483,647
      使用 native machine arithmetic 进行计算,所以速度很快。但当其和 NUMBER 进行频繁转换时会降低性能,所以在进行整数计算,或者循环计数器时,应该一开始就使用 PLS_INTEGER。
    BINARY_INTEGER:
      以二进制形式存储带符号整数。
      在 Oracle Database 10g Release 1 之前,BINARY_INTEGER 是平台无关的;自 10g Release 1 开始,他和 PLS_INTEGER 是一样的。
      一般不用 BINARY_INTEGER,除非使用 Oracle 7.3 之前的版本,在那之前没有 PLS_INTEGER。


  BINARY_FLOAT and BINARY_DOUBLE(PL/SQL and the database engine 都支持)
    10g 之后引入的 floating-point types。
                                        BINARY_FLOAT       BINARY_DOUBLE              NUMBER
    Maximum absolute value              3.40282347E+38F    1.7976931348623157E+308    9.999...999E+121 (38 9s total)
    Minimum absolute value              1.17549435E-38F    2.2250748585072014E-308    1.0E-127
    Number of bytes used for the value  4 (32 bits)        8 (64 bits)                varies from 1 to 20
    Number of length bytes              0                  0                          1
    Representation                      Binary, IEEE-754   Binary, IEEE-754           Decimal
    Literal suffix                      f                  d                          None
 
    不建议在不需要精确表示或计算小数的地方使用这两个类型,比如货币。当进行大数据量计算(extensive calculations.)时,这两个数据类型的性能更好。


    当混合使用 BINARY_DOUBLE, BINARY_FLOAT, and NUMBER 时,他们的优先顺序是 BINARY_DOUBLE > BINARY_FLOAT > NUMBER,当计算时默认会把表达式中的不同类型,转换为优先顺序高的数据类型,当然你可以通过 TO_NUMBER, TO_BINARY_FLOAT, and TO_BINARY_DOUBLE 等按自己的意愿显示转换。



2.数字子类型
  子类型是为了兼容 ISO SQL, SQL/DS, and DB2 的数据类型而产生的,基本上是三大基本数字类型的别名或子集。
  Subtype                      Compatibility   Corresponding Oracle datatype/notes
  DEC (precision, scale)       ANSI            NUMBER (precision, scale)
  DECIMAL (precision, scale)   IBM             NUMBER (precision, scale)
  DOUBLE PRECISION             ANSI            NUMBER, with 126 binary digits of precision
  FLOAT                        ANSI, IBM       NUMBER, but with a precision of 126 binary digits
  FLOAT (binary_precision)     ANSI, IBM       NUMBER, but with a binary_precision of up to 126 (the default)
  INT                          ANSI            NUMBER
  INTEGER                      ANSI,           IBM NUMBER
  NATURAL                      N/A             PLS_INTEGER*, but allows only nonnegative values (0 and higher)
  NATURALN                     N/A             Same as NATURAL, but with the additional restriction of never being NULL
  NUMERIC (precision, scale)   ANSI            NUMBER (precision, scale)
  POSITIVE                     N/A             PLS_INTEGER*, but allows only positive values (1 and higher)
  POSITIVEN                    N/A             Same as POSITIVE, but with the additional restriction of never being NULL
  REAL                         ANSI            NUMBER, with 63 binary digits of precision.
  SIGNTYPE                     N/A             PLS_INTEGER*, limited to the values -1, 0, and 1
  SMALLINT                     ANSI, IBM       NUMBER (38)
 
  * BINARY_INTEGER prior to Oracle Database 10g
 


3.类型转换
  TO_NUMBER、TO_BINARY_FLOAT、TO_BINARY_DOUBLE (后两者与第一个相似) Function
  语法:TO_NUMBER(string [,format [,nls_params]])
        其中 string 是一个表示数字的字符串,对于 TO_BINARY_FLOAT、TO_BINARY_DOUBLE 来说,可以用 'INF' and '-INF' 表示正负无穷大,'NaN' 表示 "not a number."
       
        符合以下情况时,可以不指定 format 直接转换:
          1.string 只包含数字和一个小数点
          2.如果开头是符号,必须是 +/-
          3.科学表示法,必须符合以下形式:1.25E2
        当使用 format 时,fortmat 中小数点左边右边的位数,不能小于 string 中相应的位数,但可以大于。
          几个 format 参数:
            D:decimal character       (NLS_NUMERIC_CHARACTER 第一个符号决定)
            G:group separator         (NLS_NUMERIC_CHARACTER 第二个符号决定)
            L:local currency symbol   (NLS_CURRENCY 决定)
            例子:a := TO_NUMBER('$123,456.78','L999G999G999D99');
       
        nls_params:可以用 nls_params 覆盖默认的 NLS 参数,但只能使用 NLS_NUMERIC_CHARACTERS, NLS_CURRENCY, and NLS_ISO_CURRENCY 三个参数(应该避免在代码中使用该参数,而在 session 级别作修改)。
       
  TO_CHAR Function
  语法:TO_CHAR(number [,format [,nls_params]])
    几个 format 参数:
      B:使 0 为空白,不管 '0' 参数
      0:使用 0 填补位数
      例子:
        DECLARE
           b VARCHAR2(30);
           c VARCHAR2(30);
        BEGIN
           b := TO_CHAR(123.01,'LB000G000G009D99');
           DBMS_OUTPUT.PUT_LINE(b);


           b := TO_CHAR(0,'LB000G000G009D99');
           DBMS_OUTPUT.PUT_LINE(b);
        END;
       
        The output is:
        $000,000,123.01


    当转换为 string 时,如果 format 中小数点左边的位数比实际的少,Oracle 会输出 '#',但如果小数点右边的少,Oracle 会自动四舍五入。
    如果为正数,转换之后,Oracle 默认会在 string 的第一个数字前面预留一个空白字符,为了和负数保持统一。如果使用 'PR' 参数,则前后都会预留。可以使用 'TM' 参数(8i 之后),或者 LTRIM/RTRIM 消除预留空格。


  CAST Function
  语法:CAST (expression AS datatype)
  可以在数字、字符串之间自由转换,但不支持 format models,他是 ISO SQL standard 中的。


 
4.数字相关的函数
  所有的相关函数都定义在 STANDARD 包中(standard.sql)
  4.1 Rounding and Truncation Functions
      Function     Summary
      CEIL         返回大于或等于指定值的最小整数。
      FLOOR        返回小于或等于指定值的最大整数。
      ROUND        ROUND ( number [, integer ] ) 四舍五入。integer 默认为 0,四舍五入为整数;若 integer > 0,四舍五入至小数点右边 integer 位;若 integer < 0,四舍五入至小数点左边 integer 位。
      TRUNC        TRUNC ( n [, m] ) 截断。m 默认为 0,截断小数部分;若 m > 0,截断至小数点右边 m 位;若 m < 0,截断至小数点左边 m 位。
 
  4.2 三角函数
      三角函数中用的参数全都是弧度不是角度。
      转换:
          radians = p * degrees / 180 -- From degrees to radians
          degrees = radians * 180 / p -- From radians to degrees
      p 的表示方法:
          p = ACOS (-1)

Jul 25, 2006

Oracle PL/SQL Programming 读书笔记(Strings)

Working with Strings

1.常量字符串:

单引号(')在字符串中用两个来表示('')
10G 中可以用 q' 来表示字符串的开始和结束:q'!fjsk'djfd!' or q'[kdfjs'kdlfj]'


2.ASCII代码:
CHR(10) 返回 ASCII 码对应的字符
ASCII(char(1)) 返回对应的 ASCII


3.字符串操作:
CONCAT(char,char) = char||char 连接字符串
LOWER UPPER INITCAP 大小写处理,INITCAP 将字符串中每个单词的开头字母大写。
NLS_COMP NLS_SORT 参数指定字符串的比较和排序规则,默认都是 BINARY,根据二进制转换后的结果进行比较和排序。可以在 session 或整个数据库层面改变该参数,来影响比较和排序的结果,还可以用 NLSSORT 函数。
补充:NLS_SORT/NLSSORT 非常有用,比如需要按照拼音顺序排列可以通过下面的语句实现:
    select descr from dmdunit order by nlssort(descr,'NLS_SORT = GBK')
当然也可以在 session / database 级别设置 NLS_SORT 参数来实现。后面的 nlspara 可以通过查询 V$NLS_VALID_VALUES 来获得(也可以查看 Globalization Support Guide 附录中的 Locale Data 的 Linguistic Sorting,9.2 的文档地址为 http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96529/appa.htm#958872),在 10g 中,还可以在后面加后缀 _CI (case insensitivity) or _AI (accent-insensitive and case-insensitive),10g 之前好像不行,只能通过 upper/lower 来忽略大小写了。更详细的可以查看 Globalization Support Guide 或者 http://www.oracle.com/technology/tech/globalization/index.html
LPAD/RPAD(string,n[,char]) 将 string 用 char 向左/向右不足 n 位,char 不指定则用空格,如果 n 小于 string 长度,会将 string 从左/从右截断。
LTRIM/RTRIM(string[,set]) 将 string 左边/右边的 set 删除,set 不指定则将空格删除。
一种有趣的用法:
    DECLARE
       a VARCHAR2(40) := 'This sentence has too many periods......';
       b VARCHAR2(40) := 'The number 1';
    BEGIN
       DBMS_OUTPUT.PUT_LINE(   RTRIM(a,'.')   );
       DBMS_OUTPUT.PUT_LINE(
          LTRIM(b, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz')
       );
    END;


And the output is:
This sentence has too many periods
1


TRIM([leading/trailing/both] trim_char from source_string)
trim_char 为需要去掉的字符,如果不指定 [leading/trailing/both] 默认为 both。


4.查找、提取、替代字符串:
INSTR(string,substring[,position,occurrence])
position 为负数的话,从字符串末尾向开头查找,返回的结果依然是从开头开始计数。


SUBSTR(string,position[,substring_length])
position 为负数的话,从字符串末尾开始计数,然后再向末尾取子串。


REPLACE(string,search_string[,replacement_string])
replacement_string 不指定的话,相当于删除 search_string


5.空字符
pl/sql:
declare ch char(10):='';
        vch varchar2(10):=''
ch is null             --false,因为自动扩展为 10 个空格
vch is null            --true
'' is null             --true


sql:
create table vc (ch char(2), vch varchar2(2));
insert into vc values('','');
commit;
select * from where ch is null or vch is null;    --返回行
select * from where ch ='' or vch ='' or ch='  '; --不返回行


6.char/varchar2 操作、比较
char 赋值给 varchar2 末尾空格保留
varchar2 赋值给 char 自动填补末尾空格


当 char 和 char 比较时,自动将长度短的 char 末尾补空格至和较长的长度相等,再比较(在 '' 中的字符串属于固定长度字符串,因此,属于 char)
当 char 和 varchar2 比较时,不会补充长度,直接比较。
(注:补充空格只是在比较时,不会真正把字符串补充长度。)
例子:
DECLARE
company_name CHAR(30):= 'Feuerstein and Friends';
char_parent_company_name CHAR(35):= 'Feuerstein and Friends';
varchar2_parent_company_name VARCHAR2(35):= 'Feuerstein and Friends';
company_name = char_parent_company_name       --true,company_name 补充到 35 个字符再比较
company_name = varchar2_parent_company_name   --false


create table vc(a char(10),b varchar2(10));
insert into vc values('fd','fd');
commit;
select * from vc where a=b;      --不返回行,a 为 'fd      ',b 为 'fd'
select * from vc where a='fd';   --返回行,'fd' 自动补充空格至 10 个字符。


create table cc(a char(2),b char(5));
insert into cc values('f','f');
commit;
select * from cc where a=b;      -- 返回行,a 自动补充至 5 个字符

Jul 03, 2006

NLS 视图的研究

    Oracle 中有这么几个关于 NLS 的视图:

NLS_DATABASE_PARAMETERS
NLS_INSTANCE_PARAMETERS
NLS_SESSION_PARAMETERS
V$NLS_PARAMETERS
V$NLS_VALID_VALUES

    可以通过 V$FIXED_VIEW_DEFINITION 和 DBA_VIEWS 来看看,他们的定义,来了解他们可以给我们反映一些什么信息:



STSC@MLIV> SELECT TEXT FROM DBA_VIEWS
  2  WHERE VIEW_NAME='NLS_DATABASE_PARAMETERS';


TEXT
-------------------------------------------------------------


select name, substr(value$, 1, 40)
from props$
where name like 'NLS%'

STSC@MLIV> ED
Wrote file afiedt.buf


  1  SELECT TEXT FROM DBA_VIEWS
  2* WHERE VIEW_NAME='NLS_INSTANCE_PARAMETERS'
STSC@MLIV> /


TEXT
-------------------------------------------------------------


select substr(upper(name), 1, 30), substr(value, 1, 40)
from v$parameter
where name like 'nls%'

STSC@MLIV> SELECT TEXT FROM DBA_VIEWS
  2  WHERE VIEW_NAME='NLS_SESSION_PARAMETERS';


TEXT
-------------------------------------------------------------


select substr(parameter, 1, 30), substr(value, 1, 40)
from v$nls_parameters
where parameter != 'NLS_CHARACTERSET' and
 parameter != 'NLS_NCHAR_CHARACTERSET'


    可以看到,NLS_DATABASE_PARAMETERS、NLS_INSTANCE_PARAMETERS、NLS_SESSION_PARAMETERS
分别来自于 props$、v$parameters、v$nls_parameters,props$ 存储的是数据库创建时的各项参数选项,也就是数据库的属性;v$parameters 来自于 init 参数,是实例的属性,v$nls_parameters 可以再通过以下的过程,研究它来自于何处:



STSC@MLIV> select view_definition from V$FIXED_VIEW_DEFINITION
  2  where VIEW_NAME='V$NLS_PARAMETERS';


VIEW_DEFINITION
----------------------------------------------------------------------------------------------------
select  PARAMETER , VALUE from GV$NLS_PARAMETERS where inst_id = USERENV('Instance')

STSC@MLIV> ed
Wrote file afiedt.buf


  1  select view_definition from V$FIXED_VIEW_DEFINITION
  2* where VIEW_NAME='GV$NLS_PARAMETERS'
STSC@MLIV> /


VIEW_DEFINITION
----------------------------------------------------------------------------------------------------
select inst_id,parameter, value from x$nls_parameters where parameter != 'NLS_SPECIAL_CHARS'



SYS@MLIV> SELECT * FROM x$nls_parameters;


ADDR           INDX    INST_ID PARAMETER
-------- ---------- ---------- -------------------------------------------
---------------
VALUE
----------------------------------------------------------------
5E315788          0          1 NLS_LANGUAGE
AMERICAN


5E315788          1          1 NLS_TERRITORY
CHINA


5E315788          2          1 NLS_CURRENCY
RMB


5E315788          3          1 NLS_ISO_CURRENCY
CHINA


5E315788          4          1 NLS_NUMERIC_CHARACTERS
.,


5E315788          5          1 NLS_CALENDAR
GREGORIAN


5E315788          6          1 NLS_DATE_FORMAT
RRRR-MM-DD


5E315788          7          1 NLS_DATE_LANGUAGE
AMERICAN


5E315788          8          1 NLS_CHARACTERSET
ZHS16GBK


5E315788          9          1 NLS_SORT
BINARY


5E315788         10          1 NLS_TIME_FORMAT
HH.MI.SSXFF AM


5E315788         11          1 NLS_TIMESTAMP_FORMAT
DD-MON-RR HH.MI.SSXFF AM


5E315788         12          1 NLS_TIME_TZ_FORMAT
HH.MI.SSXFF AM TZH:TZM


5E315788         13          1 NLS_TIMESTAMP_TZ_FORMAT
DD-MON-RR HH.MI.SSXFF AM TZH:TZM


5E315788         14          1 NLS_DUAL_CURRENCY
RMB


5E315788         15          1 NLS_SPECIAL_CHARS
|@


5E315788         16          1 NLS_NCHAR_CHARACTERSET
ZHS16GBK


5E315788         17          1 NLS_COMP
BINARY



18 rows selected.


SYS@MLIV> alter session set NLS_LANGUAGE='SIMPLIFIED CHINESE';


靠靠靠


SYS@MLIV> SELECT * FROM x$nls_parameters;


ADDR           INDX    INST_ID PARAMETER
-------- ---------- ---------- -------------------------------------------
---------------
VALUE
----------------------------------------------------------------
5E315788          0          1 NLS_LANGUAGE
SIMPLIFIED CHINESE


5E315788          1          1 NLS_TERRITORY
CHINA


5E315788          2          1 NLS_CURRENCY
RMB


5E315788          3          1 NLS_ISO_CURRENCY
CHINA


5E315788          4          1 NLS_NUMERIC_CHARACTERS
.,


5E315788          5          1 NLS_CALENDAR
GREGORIAN


5E315788          6          1 NLS_DATE_FORMAT
RRRR-MM-DD


5E315788          7          1 NLS_DATE_LANGUAGE
SIMPLIFIED CHINESE


5E315788          8          1 NLS_CHARACTERSET
ZHS16GBK


5E315788          9          1 NLS_SORT
BINARY


5E315788         10          1 NLS_TIME_FORMAT
HH.MI.SSXFF AM


5E315788         11          1 NLS_TIMESTAMP_FORMAT
DD-MON-RR HH.MI.SSXFF AM


5E315788         12          1 NLS_TIME_TZ_FORMAT
HH.MI.SSXFF AM TZH:TZM


5E315788         13          1 NLS_TIMESTAMP_TZ_FORMAT
DD-MON-RR HH.MI.SSXFF AM TZH:TZM


5E315788         14          1 NLS_DUAL_CURRENCY
RMB


5E315788         15          1 NLS_SPECIAL_CHARS
|@


5E315788         16          1 NLS_NCHAR_CHARACTERSET
ZHS16GBK


5E315788         17          1 NLS_COMP
BINARY



靠?8靠


SYS@MLIV> SELECT * FROM NLS_SESSION_PARAMETERS;


PARAMETER
------------------------------------------------------------
VALUE
--------------------------------------------------------------------------


NLS_LANGUAGE
SIMPLIFIED CHINESE


NLS_TERRITORY
CHINA


NLS_CURRENCY
RMB


NLS_ISO_CURRENCY
CHINA


NLS_NUMERIC_CHARACTERS
.,


NLS_CALENDAR
GREGORIAN


NLS_DATE_FORMAT
RRRR-MM-DD


NLS_DATE_LANGUAGE
SIMPLIFIED CHINESE


NLS_SORT
BINARY


NLS_TIME_FORMAT
HH.MI.SSXFF AM


NLS_TIMESTAMP_FORMAT
DD-MON-RR HH.MI.SSXFF AM


NLS_TIME_TZ_FORMAT
HH.MI.SSXFF AM TZH:TZM


NLS_TIMESTAMP_TZ_FORMAT
DD-MON-RR HH.MI.SSXFF AM TZH:TZM


NLS_DUAL_CURRENCY
RMB


NLS_COMP
BINARY



靠?5靠


    可以看到,用 alter  session 对客户端的参数的改变会反映到基表 x$nls_parameters 上。


结论:
NLS_DATABASE_PARAMETERS                显示数据库各属性参数
NLS_INSTANCE_PARAMETERS                  显示实例参数(由 init 指定)
NLS_SESSION_PARAMETERS                    来自于 V$NLS_PARAMETERS,显示客户端的参数
V$NLS_PARAMETERS                                显示客户端的参数
V$NLS_VALID_VALUES                               所有可用的 NLS 参数

注:V$NLS_PARAMETERS 中的 NLS_CHARACTERSET 和 NLS_NCHAR_CHARACTERSET 不会因为客户端环境变量 NLS_LANG 的指定而改变,他和 NLS_DATABASE_PARAMETERS 中这两个参数的区别是,前者影响导入操作,后者影响数据存储,详细可参考 eygle 的《字符集问题的初步探讨(五)》。

参考:
http://www.eygle.com/special/NLS_CHARACTER_SET_05.htm


http://www.dbanotes.net/X$tables.htm

Jun 28, 2006

DBMS_METADATA.GET_DDL 错误解决

    Oracle 9i 开始,提供了 DBMS_METADATA 包,可以方便的获得对象的 DDL 语句。

SQL> DESC DBMS_METADATA
FUNCTION GET_DDL RETURNS CLOB
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 OBJECT_TYPE                    VARCHAR2                IN
 NAME                           VARCHAR2                IN
 SCHEMA                         VARCHAR2                IN     DEFAULT
 VERSION                        VARCHAR2                IN     DEFAULT
 MODEL                          VARCHAR2                IN     DEFAULT
 TRANSFORM                      VARCHAR2                IN     DEFAULT

    今天,使用 GET_DDL 时,出现了问题:

SQL> select dbms_metadata.get_ddl('TABLE','A') from dual;
ERROR:
ORA-06502: PL/SQL: numeric or value error
LPX-00210: expected '<' instead of 'n'
ORA-06512: at "SYS.UTL_XML", line 0
ORA-06512: at "SYS.DBMS_METADATA_INT", line 3296
ORA-06512: at "SYS.DBMS_METADATA_INT", line 4148
ORA-06512: at "SYS.DBMS_METADATA", line 458
ORA-06512: at "SYS.DBMS_METADATA", line 615
ORA-06512: at "SYS.DBMS_METADATA", line 1221
ORA-06512: at line 1

    自从上次把 Oracle 升级到 9.2.0.6 感觉数字字典一直有问题,google 了一下,发现 Fenng 的一篇文章,上面提到了是个 BUG,不过再仔细一看,发现错误并不相同。于是继续 google,终于找到了解决方法:Reload the XML API。
步骤:


1. enable restricted database session
2. run:
(from $ORACLE_HOME/rdbms/admin):
catnomet.sql
rmxml.sql
to remove the xml subsystem and after that:
catxml
utlcxml.sql
prvtcxml.plb
catmet.sql
to reload it.

问题解决:


SQL> select dbms_metadata.get_ddl('TABLE','A') from dual;
DBMS_METADATA.GET_DDL('TABLE',
-----------------------------------------------------------------------
  CREATE TABLE "SKY"."A"
   (    "C" NUMBER(*,0)
   ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
  TABLESPACE "EXAMPLE"

另外,从 Fenng 那篇文章还知道了,屏蔽不需要的 DDL 子句:



SQL> EXECUTE DBMS_METADATA.SET_TRANSFORM_PARAM(DBMS_METADATA.SESSION_TRANSFORM,'
STORAGE',false);


PL/SQL procedure successfully completed.


SQL> select dbms_metadata.get_ddl('TABLE','A') from dual;


DBMS_METADATA.GET_DDL('TABLE',
--------------------------------------------------------------------------------
  CREATE TABLE "SKY"."A"
   (    "C" NUMBER(*,0)
   ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
  TABLESPACE "EXAMPLE"


参考:
http://www.dbanotes.net/Oracle/DBMS_METADATA_DDL.htm
http://www.mydatabasesupport.com/forums/showthread.php?t=235

Jun 15, 2006

自动回滚段管理改为手工管理

    自动回滚段管理是 9i 的新特性,通过创建 undo 表空间,设置 undo_management 和 undo_tablespace 两个参数,可以让 Oracle 来自动管理回滚段,非常方便。


    当然,有些人认为自动撤销管理存在很多问题,比如经常不能自动释放回滚段等等。此时,可以从自动管理改为手工管理,修改过程很简单,但也要按照步骤来,否则更改会失败。


步骤:
1. 将 UNDO_MANAGEMENT 改为 MANUAL


alter system set undo_management=manual scope=spfile;
    在 auto 下直接创建回滚段会报错:

SQL> create rollback segment rbs4 tablespace RBS_TS;
create rollback segment rbs4 tablespace RBS_TS
*
ERROR at line 1:
ORA-30019: Illegal rollback Segment operation in Automatic Undo mode

    即使将 undo_suppress_errors 设为 true,虽然不再报错,但实际上回滚段不会创建。


2. 重启数据库,在系统表空间或者任何一个字典管理的表空间中创建一个回滚段。
    当重启数据库后,undo 表空间中,所有的回滚段应该都是 offline 了,只有一个系统回滚段是 online 的,此时只能操作 system 表空间中的事务。



SQL> select segment_name,owner,status from dba_rollback_segs;


SEGMENT_NAME                   OWNER  STATUS
------------------------------ ------ ----------------
SYSTEM                         SYS    ONLINE
_SYSSMU1$                      PUBLIC OFFLINE
_SYSSMU2$                      PUBLIC OFFLINE
_SYSSMU3$                      PUBLIC OFFLINE
_SYSSMU4$                      PUBLIC OFFLINE
_SYSSMU5$                      PUBLIC OFFLINE
_SYSSMU6$                      PUBLIC OFFLINE
_SYSSMU7$                      PUBLIC OFFLINE
_SYSSMU8$                      PUBLIC OFFLINE
_SYSSMU9$                      PUBLIC OFFLINE
_SYSSMU10$                     PUBLIC OFFLINE

    此时,如果直接在一个 LMT 上创建回滚段会发生错误:

SQL> create rollback segment rbs01 tablespace RBS_TS;
create rollback segment rbs01 tablespace RBS_TS
*
ERROR 位于第 1 行:
ORA-01552: 非系统表空间 'RBS_TS' 无法使用系统回退段

    在 system 表空间中先创建一个回滚段:



SQL> ed
Wrote file afiedt.buf


  1  CREATE ROLLBACK SEGMENT rbs_dummy
  2  TABLESPACE system
  3* STORAGE (INITIAL 10k NEXT 10k MINEXTENTS 2)
SQL> /


Rollback segment created.
SQL> alter rollback segment RBS_DUMMY online;


Rollback segment altered.


    也可以在 DMT 上创建,但如果 SYSTEM 表空间是 LMT 的,那其它表空间就不能是 DMT 了(除了只读表空间)。


3. 创建一个单独存放回滚段的表空间
    将回滚段单独放在一个表空间可以方便管理,也防止资源争用。由于回滚段的 initial next 要相等,且 pctincrease 为 0,所以可以指定表空间的 UNIFORM SIZE。注:表空间不能使用 ASSM,否则会报错 ORA-30574。


CREATE TABLESPACE rbs_ts
   DATAFILE 'rbs01.dbf' SIZE 10M
   EXTENT MANAGEMENT LOCAL UNIFORM SIZE 100K;


4. 创建回滚段,并设置 rollback_segments:



SQL> create rollback segment rbs1 tablespace RBS_TS;


Rollback segment created.


SQL> create rollback segment rbs2 tablespace RBS_TS;


Rollback segment created.


SQL> create rollback segment rbs3 tablespace RBS_TS;


Rollback segment created.

SQL> alter system set rollback_segments='rbs1','rbs2','rbs3' scope=spfile;


System altered.

    如果表空间使用了 ASSM 此时会报错:

create rollback segment user_rbs tablespace rbs
2 storage(initial 250k next 250k minextents 2 optimal 1M);
create rollback segment user_rbs tablespace rbs
创建回滚段时出错。
ERROR 位于第 1 行:
ORA-30574: 无法利用 AUTO 段空间管理在表空间中创建回退段

    如果创建的回滚段是 PUBLIC 的,可以不设置 rollback_segments,而通过 transactions 和 transactions_per_rollback_segment 来控制使用 PUBLIC 回滚段的数量。


5. 如果确定 UNDO 表空间不再用了,可以将其 OFFLINE 并 Drop 掉。


通过以上步骤,修改成功。

参考:
http://www.itpub.net/114159,1.html
http://www.oracle.com.cn/viewthread.php?tid=62906