所有由小潘发布的文章

喜欢分享的小潘.

PLSQL存储过程金额大写的转换

function lcw_get_money(money in number) return varchar2 is
    c_money  VARCHAR2(12);
    b_string VARCHAR2(80);
    m_string VARCHAR2(60) := '分角圆拾佰仟万拾佰仟亿';
    n_string VARCHAR2(40) := '壹贰叁肆伍陆柒捌玖';
    n        CHAR;
    len      NUMBER(10);
    i        NUMBER(10);
    tmp      NUMBER(12);
    is_zj    BOOLEAN;
    z_count  NUMBER(10);
    l_money  NUMBER;
    l_money1 NUMBER;
    l_sign   VARCHAR2(10);
  BEGIN
    l_money1 := to_number(money);
    l_money  := abs(money);
    IF l_money1 < 0 THEN
      l_sign := '负';
    ELSE
      l_sign := '';
    END IF;
    tmp     := round(l_money, 2) * 100;
    c_money := rtrim(ltrim(to_char(tmp, '999999999999')));
    len     := length(c_money);
    is_zj   := TRUE;
    z_count := 0;
    i       := 0;
    WHILE i < len LOOP
      i := i + 1;
      n := substr(c_money, i, 1);
      IF n = '0' THEN
        IF len – i = 6 OR len – i = 2 OR len = i THEN
          IF is_zj THEN
            b_string := substr(b_string, 1, length(b_string) – 1);
            is_zj    := FALSE;
          END IF;
          IF len – i = 6 THEN
            b_string := b_string || '万';
          END IF;
          IF len – i = 2 THEN
            b_string := b_string || '圆';
          END IF;
          IF len = i THEN
            b_string := b_string || '整';
          END IF;
          z_count := 0;
        ELSE
          IF z_count = 0 THEN
            b_string := b_string || '零';
            is_zj    := TRUE;
          END IF;
          z_count := z_count + 1;
        END IF;
      ELSE
        b_string := b_string || substr(n_string, to_number(n), 1) ||
                    substr(m_string, len – i + 1, 1);
        z_count  := 0;
        is_zj    := FALSE;
      END IF;
    END LOOP;
    b_string := l_sign || b_string;
    RETURN b_string;
  EXCEPTION
    WHEN OTHERS THEN
      RETURN(SQLERRM);
  END;

Form开发常用命令点

1. 根据条件,输出错误提示

IF :detail_line.quantity <= 0 THEN
        fnd_message.set_string('数量不能为0或负数!');
        fnd_message.error;
        RAISE form_trigger_failure;
END IF;

2.  完成MOAC的初始化
   CUX_MOAC_PKG.pre_form;   
   app_window.set_window_position('MAIN', 'FIRST_WINDOW');

3. 初始化folder块,可初始化多个folder块
    app_folder.define_folder_block(object_name=>'CUXGSPCHK01',
                                   folder_block_name=>'DETAIL_HEADER',
                                   prompt_block_name=>'DETAIL_HEADER_PROMPT',
                                   folder_canvas_name=>'DETAIL_HEADER_STK',
                                   folder_window_name=>'MAIN',
                                   disabled_functions=>null,
                                   tab_canvas_name=>null,
                                   fixed_canvas_name=>null);
    app_folder.event('INSTANTIATE');

4. 功能:当进入FORM时,执行pre_form程序完成MOAC的初始化
   procedure pre_form
   is
      l_default_org_id  number;
      l_default_ou_name varchar2(240);
      l_ou_count         number;
   begin
        MO_GLOBAL.init('CUX');
       
        mo_utils.get_default_ou(l_default_org_id, l_default_ou_name, l_ou_count);
     
        copy(l_default_org_id,'PARAMETER.mo_default_org_id'); 
        copy(l_default_ou_name,'PARAMETER.mo_default_ou_name');
        copy(l_ou_count,'PARAMETER.mo_ou_count'); 
       
        –fnd_message.debug('l_default_org_id = ' || l_default_org_id);
        –fnd_message.debug('l_default_ou_name = ' || l_default_ou_name);
        –fnd_message.debug('l_ou_count = ' || l_ou_count);
       
        –判断是否找到了OU,如果没有找到,则报错
        if nvl(l_ou_count,0) <= 0 then
            fnd_message.set_name('CUX', '没有找到相应的OU,请联系系统管理员或开发人员!');
            fnd_message.error;
            raise form_trigger_failure;
        end if;           
   end pre_form;

 5. 帮助》历史记录灰掉问题

问题:在一个FORM中发现历史记录菜单灰掉

解决:这个跟块查询灰掉一样,块查询是把块级触发器WHEN-NEW-RECORD-INSTANCE触发器层级修改为BEFORE,

这个问题需要将WHEN-NEW-BLOCK-INSTANCE触发器层级修改为BEFORE,因为这两个的可用与否,是FORM级触发器判断的,如果覆盖,就不可用了。

PS:使用历史记录时报“历史记录不可用”,是由于在该块中没有5个数据库WHO字段的原因,添加上就行。

6. 设置ITEM属性

set_item_instance_property('DETAIL_LINE.LOT_NUMBER',
                                   current_record,
                                   update_allowed,
                                   property_false);

 set_item_property('QUERY_FIND.VENDOR_CUST_NAME'
                       ,insert_allowed
                       ,property_false);

7.Form客户化设置消息例子,参考系统用户创建form,用户创建触发器

FND_USER_PKG_WRP

FND_USER_PKG

8.问题描述: 手电筒功能查询一次后变灰色,不可用

原因:QUERY_FIND查询块中的Query_Allowed属性为NO

方法:把该属性设置为YES即可。

原因:这是主数据块(被查询的数据块)上When-new-record-instance触发器的执行层次问题

方法:改一下主data block的触发器WHEN-NEW-RECORD-INSTANCE ,把属性execution hierarchy改为after。

EBS并发程序相关SQL

–所有客户化并发程序
SELECT FC.USER_CONCURRENT_PROGRAM_NAME,
       FC.DESCRIPTION,
       FC.CONCURRENT_PROGRAM_NAME,
       UPPER(FE.EXECUTION_FILE_NAME)
  FROM FND_CONCURRENT_PROGRAMS_VL FC,
       FND_EXECUTABLES_FORM_V     FE,
       FND_APPLICATION            FA
 WHERE 1 = 1
   AND FA.APPLICATION_ID = FC.APPLICATION_ID
   AND FA.APPLICATION_SHORT_NAME = 'CUX'
   AND FC.CONCURRENT_PROGRAM_NAME = FE.EXECUTABLE_NAME
   AND FC.ENABLED_FLAG = 'Y'
 ORDER BY FC.CREATION_DATE DESC;

–并发程序对应参数
SELECT FV.COLUMN_SEQ_NUM                序号,
       FV.END_USER_COLUMN_NAME          参数,
       FV.DESCRIPTIVE_FLEXFIELD_NAME    可执行程序,
       FV.ENABLED_FLAG                  是否启用,
       FV.DISPLAY_FLAG                  显示,
       FFVS.FLEX_VALUE_SET_NAME         值集名称,
       FV.DEFAULT_TYPE                  默认类型,
       FV.DEFAULT_VALUE                 默认值,
       FV.REQUIRED_FLAG                 必需,
       FV.SECURITY_ENABLED_FLAG         启用安全性,
       FV.RANGE_CODE                    范围,
       FV.DISPLAY_SIZE                  显示大小,
       FV.MAXIMUM_DESCRIPTION_LEN       说明大小,
       FV.CONCATENATION_DESCRIPTION_LEN 级联说明大小,
       FV.FORM_ABOVE_PROMPT             提示,
       FV.SRW_PARAM                     变量
  FROM FND_DESCR_FLEX_COL_USAGE_VL FV, FND_FLEX_VALUE_SETS FFVS
 WHERE FV.FLEX_VALUE_SET_ID = FFVS.FLEX_VALUE_SET_ID
   AND SUBSTR(FV.DESCRIPTIVE_FLEXFIELD_NAME, 7) IN
       (SELECT FC.CONCURRENT_PROGRAM_NAME
          FROM FND_CONCURRENT_PROGRAMS_VL FC,
               FND_EXECUTABLES_FORM_V     FE,
               FND_APPLICATION            FA
         WHERE 1 = 1
           AND FA.APPLICATION_ID = FC.APPLICATION_ID
           AND FA.APPLICATION_SHORT_NAME = 'CUX'
           AND FC.CONCURRENT_PROGRAM_NAME = FE.EXECUTABLE_NAME
           AND FC.ENABLED_FLAG = 'Y')
 ORDER BY FV.DESCRIPTIVE_FLEXFIELD_NAME, FV.COLUMN_SEQ_NUM;

Oracle ORA-01555快照过旧的错误(转载)

转载地址:http://blog.csdn.net/liaoyuanzi/article/details/7712682

关于Oracle ORA-01555快照过旧的错误


首先了解Oracle在什么情况下会产生ORA-01555错误: 


假设有一张6000万行数据的testdb表,预计testdb全表扫描1次需要2个小时,参考过程如下: 


1、在1点钟,用户A发出了select * from testdb;此时不管将来testdb怎么变化,正确的结果应该是用户A会看到在1点钟这个时刻的内容。


2、在1点30分,用户B执行了update命令,更新了testdb表中的第4100万行的这条记录,这时,用户A的全表扫描还没有到达第4100万条。毫无疑问,这个时候,第4100万行的这条记录是被写入了回滚段,假设是回滚段UNDOTS1,如果用户A的全表扫描到达了第4100万行,是应该会正确的从回滚段UNDOTS1中读取出1点钟时刻的内容的。 


3、这时,用户B将他刚才做的操作提交了,但是这时,系统仍然可以给用户A提供正确的数据,为那第4100万行记录的内容仍然还在回滚段UNDOTS1里,系统可以根据SCN到回滚段里找到正确的数据,但要注意到,这时记录在UNDOTS1里的第4100万行记录已经发生了重大的改变:就是第4100万行在回滚段UNDOTS1里的数据有可能随时被覆盖掉,为这条记录已经被提交了! 


4、由于用户A的查询时间漫长,而业务在一直不断的进行,UNDOTS1回滚段在被多个不同的transaction使用着,这个回滚段里的extent循环到了第4100万行数据所在的extent,由于这条记录已经被标记提交了,所以这个extent是可以被其他transaction覆盖掉的! 


5、到了1点45分,用户A的查询终于到了第4100万行,而这时已经出现了第4条说的情况,需要到回滚段UNDOTS1去找数据,但是已经被覆盖掉了,这时就出现了ORA-01555错误。 以上此段非本人原创 


 


分析:"报表"程序执行时间漫长,在程序查询的过程中其他用户对"报表"进行了更新,被更新的数据写入了回滚段,当程序到回滚段找数据时,发现数据已经被覆盖掉,于是就出现了ORA-01555错误。另外"报表"程序执行效率不高也会造成ORA-01555错误。
解决办法:
1、扩大回滚段,为回滚段是循环使用的,如果回滚段足够大,那么那些被提交的数据就能保存足够长的时间,使那些大事务完成一致性读取。之前EBS系统UNDO表空间为9GB,目前为10GB。见下图:



2、增加undo_retention时间,为UNDO回滚段是循环使用,里面的数据可能随时被循环覆盖掉,如果设置undo_retention时间更长,那么在retention规定的时间内,任何其他事务都不能覆盖这些数据。目前EBS系统undo_retention为10800秒(3个小时)。见下图:
 


3、最重要的一点就是优化程序相关查询语句,减少查询语句的一致性读,降低读取不到回滚段数据的风险。所有的出错信息都会纪录到数据库日志alert_PROD.log文件中,下图红线部分是一条SQL查询词句,ORA-01555很有可能是这条语句造成,把这条语句提供给开发人员来分析和优化程序代码。


————————————————————————————————————————–

ORA-01555 原与解决:

前面提到了ORA-01555错误,那么现在来看一下ORA-01555错误是怎样产生的。由于回滚段是循环使用的,当事务提交以后,该事务占用的回滚段事务会被标记为非活动,回滚段空间可以被覆盖重用。那么一个问题就出现了,如果一个查询需要使用被覆盖的回滚段构造前镜像实现一致性读,那么此时就会出现Oracle著名的ORA-01555错误。

ORA-01555错误的另外一个原为延迟块清除(Delayed Block Cleanout)。当一个查询触发延迟块清除时,Oracle需要去查询回滚段获得该事务的提交SCN,如果事务的前镜像信息已经被覆盖,并且查询SCN也小于回滚段中记录的最小提交SCN,那么Oracle将无从判断查询SCN和事务提交SCN的大小,此时出现延迟块清除导致的ORA-01555错误。

另外一种导致ORA-01555错误的情况出现在使用sqlldr直接方式加载(direct=true)数据时。当通过sqlldr direct=true 方式加载数据时,由于不产生重做和回滚信息,Oracle直接指定Cached Commit SCN 给加载数据,在访问这些数据时,有时会产生ORA-01555错误。

看下图的描述:假定在时间T用户A发出一条更新语句,更新SCOTT用户的SAL;用户B在Ty时间发出查询语句,查询SCOTT用户的SAL;用户A的更新在Tx时间提交,提交可能为快速提交块清除,也可能是延迟块清除;用户B的查询在Tz时间输出。

来看一下数据库在不同情况下的内部处理:

如果 Ty < T < Tz < Tx ,那么查询需要构造一致性读,由于事务尚未提交,可以通过回滚段构造前镜像,完成一致性读取。
·如果 Ty < T < Tx < Tz ,由于Ty查询时间小于T事务更新时间,那么数据库需要构造一致性读取,而Tz查询完成时间大于Tx提交时间,那么前镜像就有可能被覆盖,不可获取。

如果Tx的提交方式为Fast Block Cleanout,那么回滚段信息不可用时就会出现一致性读ORA-01555错误。

如果Tx的提交方式为Delayed Block Cleanout,那么回滚段信息不可用时Oracle将无法判断Ty和Tx的时间先后关系。如果 Ty > Tx ,那么Oracle可以正常进行块清除,并将块清除后的数据返回给用户B;如果 Ty < T ,那么Oracle需要继续构造一致性读返回给用户B;Oracle无法判断这两种情况,就会出现延迟块清除ORA-01555错误。

ORA-01555的直观解释是“snapshot too old”,也就是快照太旧,其根本含义就是查询需要的前镜像过于“久远”,已经无法找到了。可以想象,如果一个历时数个小时或十几个小时的查询,如果最后遭遇ORA-01555错误而失败,会是多么令人沮丧的一件事。一直以来,ORA-01555都是ORACLE最为头痛的问题之一。

在Oracle 9i的文档中这样描述ORA-01555错误:

01555, 00000, "snapshot too old: rollback segment number %s with name \"%s\" too small"
// *Cause: rollback records needed by a reader for consistent read are
//         overwritten by other writers
// *Action: If in Automatic Undo Management mode, increase undo_retention
//          setting. Otherwise, use larger rollback segments

可以看到,在Oracle 9i自动管理UNDO表空间模式下,UNDO_RETENTION参数的引入正是为了减少ORA-01555错误的出现。这个参数设置当事务提交之后(回滚段变得非活跃),回滚段中的前镜像数据在被覆盖前保留的时间,该参数以秒为单位,9iR1初始值为900秒,在Oracle 9iR2增加为10800秒。

显然该参数设置的越高就越能减少ORA-01555错误的出现,但是保留时间和存储空间是紧密相关的,如果UNDO表空间的存储空间有限,那么Oracle就会选择回收已提交事务占用的空间,置UNDO_RETENTION参数于不顾。

在Oracle 9i的AUM模式下,UNDO_RETENTION实际上是一个非担保(NO Guaranteed)限制。也就是说,如果有其他事务需要回滚空间,而空间出现不足时,这些信息仍然会被覆盖;从Oracle 10g开始,Oracle对于UNDO增加了Guarantee控制,也就是说,可以指定UNDO表空间必须满足UNDO_RETENTION的限制。当UNDO表空间设置为Guarantee,那么提交事务的回滚空间必须被保留足够的时间,如果UNDO表空间的空间不足,那么新的事务会空间不足而失败,而不是选择之前的覆盖。

从各个不同版本回滚段的管理变迁,我们可以看出Oracle一直在进步。

Oracle提供了一个内部事件(10203事件)可以用来跟踪数据库的块清除操作,10203事件可以通过以下命令设置,设置后需要重新启动数据库该参数方能生效:


 

alter system set event="10203 trace name context forever" scope=spfile;


 

需要注意的是,可能存在另外一种情况,就是当执行延迟块清除时,回滚段或原回滚表空间已经被删除,此时Oracle仍然可以通过字典表UNDO$来获得SCN信息,执行块清除。

关于Oracle的提交处理及块清除机制是一个极其复杂的过程,本文对这部分内容进行了适当简化说明,旨在使大家能够对Oracle的回滚机制、块清除机制有所了解。

– The End –

oracle ebs 解锁命令

以下是ebs解锁及相关辅助信息:

select (select ppf.full_name
          from per_people_f ppf, per_assignments_f paf, fnd_user fu
         where 1 = 1
           and ppf.person_id = paf.person_id
           and fu.employee_id = ppf.person_id
           and fu.user_name = vss.client_identifier
           and sysdate between ppf.effective_start_date and
               ppf.effective_end_date
           and sysdate between paf.effective_start_date and
               paf.effective_end_date
           and (fu.end_date is null or fu.end_date > sysdate)) user_name,
       (select fr.responsibility_name
          from fnd_responsibility_vl fr
         where fr.responsibility_key =
               (select substr(vss.action, instr(vss.action, '/') + 1)
                  from dual)) resp_name,
       (select fa.application_name
          from fnd_application_vl fa
         where fa.application_short_name =
               (select substr(vss.action, 1, instr(vss.action, '/')-1)
                  from dual)) prod_name,
       (select ff.user_form_name
          from fnd_form_vl ff
         where ff.form_name =
               (select substr(vss.module, instr(vss.module, ':', 1, 3) + 1)
                  from dual)) form_name,
       (select ff.description
          from fnd_form_vl ff
         where ff.form_name =
               (select substr(vss.module, instr(vss.module, ':', 1, 3) + 1)
                  from dual)) form_desc,
       dob.object_name table_name,
       vss.action action,
       vss.client_identifier user_code,
       vss.module,
       vss.machine,
       'alter system kill session ' || '''' || lo.session_id || ',' ||
       vss.serial# || ''';' kill_command,
       vss.osuser osuser,
       vss.process ap_pid,
       vps.spid db_pid,
       lo.locked_mode,
       lo.session_id,
       vss.serial#,
       vps.spid
  from v$locked_object lo, dba_objects dob, v$session vss, v$process vps
 where lo.object_id = dob.object_id
   and lo.session_id = vss.sid
   and vss.paddr = vps.addr
 order by resp_name asc, dob.object_name;