2007年7月27日星期五

Install discoverer 4i in windows XP

需要调优一个工作簿,参考Metalink上的一篇文章,一种比较方便方法直接更改desktop注册表中的一个条目的值便可以进行诊断。由于是通过Citrix的方式访问Discoverer Desktop,并没有Citrix那台主机的管理员权限,所以想在自己的机器上安装Discoverer Desktop。

下面是安装的过程:
1. 下载Discoverer Desktop4.1.37。
下载Discoverer Desktop Edition, Version 4.1.37 for MS Windows 95/98/NT/2000。

2. 安装Discoverer Desktop4.1.37。
接压安装文件,右健点击Setup.exe,点击“Properties”菜单,在弹出的属性窗口中切换到“Compatibility”页。选中“Compatibility mode”的复选框,然后选择“Windows 2000”作为兼容模式。点击确定。


运行Setup.exe文件安装。

如果以前的机器没有安装Oracle相关产品,可以直接跳到步骤3。由于我的机器原来安装有Oracle 9i,如果在安装的时候新建立一个Oracle Home,安装会提示让你必须选在Oracle 9i所对应的Oracle Home。这个时候,如果选择Oracle 9i对应的Oracle Home,安装会提示目录已经存在就是不让你继续。

在网上找到答案,根本的原因就是安装数据库的时候,没有使用DEFAULT_HOEM。有两种方法。
方法一,删除Oracle数据库,现安装Discoverer,再安装数据库,其实不简单。
方法二,修改注册表中。找到注册表中的健值,HKEY_LOCAL_MACHINE/SOFTWARE/ORACLE/ALL_HOMES,建立一个new key,并建立对应的String value(NAME,NLS_LANG,PATH-等)。例如:NAME: Oracle_Default,NLS_LANG :NA,PATH: C:\Oracle_Default其中PATH为自己定义的DEFAULT目录。

将ALL_HOMES下的Oracle_Default的值改为刚才上面定义的“Oracle_Default”。原来的值为Oracle9i的Oracle Home。

运行Oracle Home Selector,选中Oracle_Default。
然后再运行安装程序,选中Oracle_Default进行安装。

3. 安装补丁3201601,将版本升级到4.1.48.6.0。
同样需要更改兼容性。如果不升级,连接EBS的时候,会出现用户名和密码错误的提示,从而不能登录。

参考:Metalink:Note:365285.1

2007年7月26日星期四

EBS表定时分析

EBS中默认定义了并发程序对数据库对象的进行分析,从而对基于Cost的优化器能够有效的工作。这些并发程序主要通过调用程序包FND_STATS来完成。而实际上,这几个并发程序并不是很方便。例如Gather Schema Statistics算是比较方便的一个,一次可以对数据库中的某个Schema下的对象进行分析。但是如果Oracle中有这么多的Schema,需要提交很多次请求才能完成。实际中,通过自己编写的并发程序来完成批量多个Schema下对象的分析。

Gather Table Statistics
Backup Table Statistics
Restore Table Statistics
Gather Schema Statistics
Gather Column Statistics


步骤:
1. 通过SQL*PLUS程序,SPOOL实际饱含分析语句的fnd_stats_run.sql文件,输出到一个应用的目录下,例如$FND_TOP。在这个文件中,对每一个需要分析的对象,都有如下三行语句组成,例如,对于ABM.ABM_BATCH_CALCS:

EXEC DBMS_STATS.DELETE_TABLE_STATS(ownname => 'ABM', tabname => 'ABM_BATCH_CALCS');
ANALYZE TABLE ABM.ABM_BATCH_CALCS ESTIMATE STATISTICS SAMPLE 1 ROWS;
EXEC FND_STATS.GATHER_TABLE_STATS(ownname=>'ABM',tabname=>'ABM_BATCH_CALCS',percent=>30,degree=>1,granularity=>'DEFAULT');

所以,在这个SQL*PLUS中,可以自己编写逻辑确定哪些Schema下的对象需要分析,根据表的记录数,确定分析的百分比等。

2. 将步骤1种程序定义成并发程序FND STATS PRODUCE。

3. 将步骤1中输出到$FND_TOP目录下的SQL*PLUS程序fnd_stats_run.sql,定义成并发程序FND STATS RUN。

4. 定义请求集,将上述两个请求加入请求集。并定义,只有当FND STATS PRODUCE运行成功之后,才运行FND STATS RUN。

5. 最后,定时运行请求集。

在ITPub上提问调查,到底要不要使用系统自带并发程序,意见还真多,FYI:
http://www.itpub.net/822695.html

2007年7月25日星期三

XML Publisher的Excel输出文件字段前面的所有零不丢失

在Itpub上看到问题,Metalink上正好有人问到这个问题,测试通过。

问题:
请教在Oracle XML Publisher,如何解决Excel输出文件自动使前面的所有零不丢失?现在用Excel输出文件时,如果某一个值,如001,会只显示1,自动使前面的所有零丢失。暂时只能加一个单引号,如‘001,避免此情况,但不是好办法,用户需要做修正工作,量多了挺讨厌的。如加一个不可见字符,XML文件报错。有否一个不可见字符,可以使XML文件不报错,或其它办法,以实现上述目的?

方法:
In the rtf template, use the “Insert -> Symbol” function to insert a very small0xA0 (NO-BREAK SPACE) character (font size 1 or 2pt) in front of the number string field.

另外,尝试用Oracle以及Word自带的formate是否都没有办法,Oracle的formate语法支持数字和日期。

参考:
Metalink:Note:417811.1
http://www.itpub.net/820447.html

2007年7月24日星期二

publish image with xml publisher in ebs

本文通过一个例子,展示怎样在EBS使用XMLP输出报表,并在报表中输出存储在数据库Blob字段中的图片。下面将整个开发的过程简略描述一下, EBS 版本为11.5.10.2。
1) 建立数据表。
2) 载入数据。
3) 编写数据编码的函数。
4) 编写报表。
5) 注册并发请求。
6) 运行并发请求,得到用于开发的临时XML数据文件。
7) 开发模板文件。
8) 注册XMLP的数据和模板文件。
9) 运行检查结果。


例子以及拷屏请参考Itpub帖子:http://www.itpub.net/815723.html

已经在Itpub发布,获得一个精华,高兴!

2007年7月11日星期三

Error:Function not available to this responsibility

新环境克隆出来,用户发现对于所有的客户化Form都不能访问,提示的错误为:
Function not available to this responsibility. Change responsibilities or contact you System Administrator.

按照Responsibility,Menu,Function检查,相关定义都没有更改。对比了另外一个环境,发现,发现应用层的服务器上相关Costumer的TOP目录都没有在环境中设置。通过echo $CUSTOMER_TOP,输出为空。所以,当通过Function去找Form的时候,就会遇到如上的错误。

回头想想,问题本应该这样:
1) Form和Report在不同的tie上,客户化的Report都没有问题,只有客户化的Form有问题。
2) 客户化的Menu指向一个客户化的Function(Function对应客户化Form)有问题,如果指向系统标准的Function(例如:Standard Request Submit)没有问题。

2007年7月8日星期日

XML Publisher

已经在itpub中看到不少的关于xml publisher的文章了,在网上已经找到一个非常好入门例子:
XML Publisher Concurrent Program - XMLP

2007年7月5日星期四

《Expert one on one Oracle》- 表- 笔记-4

嵌套表

类似于父/子表,但是有较大的差别。其中一个就是,在嵌套表中,父表中有多少行,就有多少嵌套表。使用嵌套表的两种方法:PL/SQL以及存储机制。
创建,查询,更新嵌套表的例子:

SQL> create or replace type emp_type
2 as object
3 (empno number(4),
4 ename varchar2(10),
5 job varchar2(9),
6 mgr number(4),
7 hiredate date,
8 sal number(7, 2),
9 comm number(7, 2)
10 );
11 /
Type created.

SQL> create or replace type emp_tab_type
2 as table of emp_type
3 /
Type created.

SQL> create table dept_and_emp
2 (deptno number(2) primary key,
3 dname varchar2(14),
4 loc varchar2(13),
5 emps emp_tab_type
6 )
7 nested table emps store as emps_nt;
Table created.

SQL> alter table emps_nt add constraint emps_empno_unique
2 unique(empno)
3 /
Table altered.

SQL> insert into dept_and_emp--插入嵌套表
2 select dept.*,
3 CAST( multiset( select empno, ename, job, mgr, hiredate, sal, comm
4 from emp
5 where emp.deptno = dept.deptno ) AS emp_tab_type )
6 from dept
7 /
5 rows created.
--multiset告诉Oracle子查询可能返回多行
--CAST告诉Oracle将返回结果作为一个集合


SQL> insert into table--插入嵌套子表
2 ( select emps from dept_and_emp where deptno = 10 )
3 values
4 ( 1234, 'NewEmp', 'CLERK', 7782, sysdate, 1200, null );
1 row created.

SQL> delete from table--删除嵌套子表
2 ( select emps from dept_and_emp where deptno = 20 )
3 where ename = 'SCOTT';
1 row deleted.

SQL> select d.dname, e.empno, ename--查询嵌套子表
2 from dept_and_emp d, table(d.emps) e
3 where d.deptno in ( 20 );

DNAME EMPNO ENAME
-------------- ---------- ----------
RESEARCH 7369 SMITH
RESEARCH 7566 JONES
RESEARCH 7876 ADAMS
RESEARCH 7902 FORD


SQL> update--更新嵌套子表
2 table( select emps
3 from dept_and_emp
4 where deptno = 10
5 )
6 set comm = 100
7 /
3 rows updated.

SQL> update
2 table( select emps
3 from dept_and_emp
4 where deptno = 1
5 )
6 set comm = 100
7 /
update
*
ERROR at line 1:
ORA-22908: reference to NULL table value

通过exp/imp可以查看到嵌套表的创建语句。通过运行如下的语句,可以进一步得到:

SQL> SELECT SQL_TEXT FROM V$SQL WHERE UPPER(SQL_TEXT) LIKE
2 '%EMP%';
……
SELECT /*+NESTED_TABLE_GET_REFS+*/ NESTED_TABLE_ID,SYS_NC_ROWINFO$ FROM "SCOTT"."EMPS_NT"

--执行上述查询出来的SQL语句
SQL> SELECT /*+NESTED_TABLE_GET_REFS+*/ NESTED_TABLE_ID,SYS_NC_ROWINFO$
2 from
3 "SCOTT"."EMPS_NT";

--得到表EMPS_NT中两列的值
NESTED_TABLE_ID
--------------------------------
SYS_NC_ROWINFO$(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM)
--------------------------------------------------------------------------------

A704A65FA4D14709807E86B8741D5ED7
EMP_TYPE(7782, 'CLARK', 'MANAGER', 7839, '09-JUN-81', 2450, 100)

A704A65FA4D14709807E86B8741D5ED7
EMP_TYPE(7839, 'KING', 'PRESIDENT', NULL, '17-NOV-81', 5000, 100)

A704A65FA4D14709807E86B8741D5ED7
EMP_TYPE(7934, 'MILLER', 'CLERK', 7782, '23-JAN-82', 1300, 100)

实际上,这两列NESTED_TABLE_ID,SYS_NC_ROWINFO$被隐藏。NESTED_TABLE_ID列是父表实际的外健,SYS_NC_ROWINFO$列,让ORACLE将一列看作一个对象。通过这种方式,ORACLE通过系统产生的主健和外健实现父子表。可以查看系统为父表创建的主健:

SQL> select name
2 from sys.col$
3 where obj# = ( select object_id
4 from user_objects
5 where object_name = 'DEPT_AND_EMP')
6 /

NAME
------------------------------
DEPTNO
DNAME
LOC
EMPS
SYS_NC0000400005$

系统为父表创建了一列SYS_NC0000400005$,为子表的外健,通过如下查询可以确定:

SQL> select SYS_NC0000400005$ from dept_and_emp WHERE SYS_NC0000400005$ = 'A704A
65FA4D14709807E86B8741D5ED7';

SYS_NC0000400005$
--------------------------------
A704A65FA4D14709807E86B8741D5ED7

从而通过NESTED_TABLE_GET_REFS可以单独查询子表,例如:
SQL> select /*+ nested_table_get_refs */ empno, ename from emps_nt where ename l
ike '%AR%';

EMPNO ENAME
---------- ----------
7782 CLARK
7521 WARD
7654 MARTIN


通过如上查询结果,嵌套表的物理结构为:
如果EXP/IMP嵌套表,那么可以发现嵌套表的定义中有RETURN AS VALUE因子,这表示会将潜套表行全部返回给应用的客户端。可以改写为RETURN AS LOCATOR,那么只是将指针方会给应用的客户端。

同时,从上面的例子可以看到,嵌套子表系统创建的主健实际上是没有索引的,而在访问这个子表的时候,ORACLE总是需要关联这个字段,所以最好为这个字段创建索引。更进一步,最好的方式将嵌套子表建立成索引组指表。

临时表

创建临时表时并不分配存储参数。当运行的时候,一个SESSION第一次将数据存入临时表,一个临时段将会创建。每个SESSION都有自己的临时段。

ORACLE的临时表应该预先创建了,只是通常情况下它们都没有数据,直到SESSION存入数据。有两种类型的临时表,基于SESSION的/基于事务的。

create global temporary table temp_table_session
on commit preserve rows--on commit delete rows
as
select * from scott.emp where 1=0
/

临时表的限制:
a. 不能定义参考完整性约束
b. 不能有VARRAY和NESTED TABLE类型的列
c. 不能是IOT/分区表/索引(HASH)CLUSTER表
d. 不能通过ANALYZE产生统计信息

针对最后一条,如果需要临时表在运行的时候有参考的统计信息,可以采用如下的方式:
a. 创建与临时表一样的普通表(表名,数据量都相同),创建索引
b. 对表和索引进行分析
c. 将统计信息导出

begin
dbms_stats.create_stat_table( ownname => USER,
stattab => 'STATS');

dbms_stats.export_table_stats( ownname => USER,
tabname => 'TEMP_ALL_OBJECTS',
stattab => 'STATS');

dbms_stats.export_index_stats( ownname => USER,
indname => 'TEMP_ALL_OBJECTS_IDX',
stattab => 'STATS');
end;
/

d. 删除普通表,创建临时表
e. 导入步骤c中导出的统计信息

begin
dbms_stats.import_table_stats( ownname => USER,
tabname => 'TEMP_ALL_OBJECTS',
stattab => 'STATS');
dbms_stats.import_index_stats( ownname => USER,
indname => 'TEMP_ALL_OBJECTS_IDX',
stattab => 'STATSʹ');
end;
/

对象表

对象表和嵌入表类似,ORACLE为了维持对象表,在普通表上增加了许多隐藏的东西。其实,其最终还是转换成关系型数据库的行和列。所以,对于物理存储的表而言,倾向于不使用对象表,因为不会知道背后隐藏的机制究竟会产生什么样的副作用。当然在存储过程,程序开发中使用是一个不错的选择。例如,用对象视图来同步对象与数据库数据。

SQL> create table people_tab
2 ( name varchar2(30) primary key,
3 dob date,
4 home_city varchar2(30),
5 home_street varchar2(30),
6 home_state varchar2(2),
7 home_zip number,
8 work_city varchar2(30),
9 work_street varchar2(30),
10 work_state varchar2(2),
11 work_zip number
12 )
13 /
Table created.

SQL> create or replace type address_type
2 as object
3 ( city varchar2(30),
4 street varchar2(30),
5 state varchar2(2),
6 zip number
7 )
8 /
Type created.

SQL> create or replace type person_type
2 as object
3 ( name varchar2(30),
4 dob date,
5 home_address address_type,
6 work_address address_type
7 )
8 /
Type created.

SQL> create view people of person_type
2 with object identifier (name)
3 as
4 select name,dob,
5 address_type(home_city,home_street,home_state,home_zip) home_a
6 address_type(work_city,work_street,work_state,work_zip) work_a
7 from people_tab
8 /
View created.

SQL> insert into people values ( 'Tom','15-mar-1965',
2 address_type( 'Reston','123 Main Street','Va','45678' ),
3 address_type( 'Redwood','1 Oracle Way','Ca','23456' ) );
1 row created.

SQL> select name, p.home_address.city from people p;
NAME HOME_ADDRESS.CITY
------------------------------ ------------------------------
Tom Reston

SQL> select name from people_tab;
NAME
------------------------------
Tom