2010年4月14日星期三

ORACLE的幾個常見小問題的詳細解答 (轉)


 ORACLE的幾個常見小問題的詳細解答
 
第一部分、SQL&PL/SQL
 [Q]怎麼樣查詢特殊字符,如通配符%與_
 [A]select * from table where name like 'A\_%' escape '\'


 [Q]如何插入單引號到數據庫表中[A]可以用ASCII碼處理,其它特殊字符如&也一樣,如insert into t values('i'||chr(39)||'m'); -- chr(39)代表字符'
 或者用兩個單引號表示一個or insert into t values('I''m');--兩個''可以表示一個'


 [Q]怎樣設置事務一致性[A]set transaction [isolation level] read committed;默認語句級一致性set transaction [isolation level] serializable;
 read only;事務級一致性[Q]怎麼樣利用游標更新數據[A]cursor c1 is
 select * from tablename
 where name is null for update [of column]
……
 update tablename set column = ……
 where current of c1;


 [Q]怎樣自定義異常[A] pragma_exception_init(exception_name,error_number);
 如果立即拋出異常raise_application_error(error_number,error_msg,true|false);
 其中number從-20000到-20999,錯誤信息最大2048B
 異常變量SQLCODE錯誤代碼SQLERRM錯誤信息[Q]十進制與十六進制的轉換[A]8i以上版本:
to_char(100,'XX')
to_number('4D','XX')
 8i以下的進制之間的轉換參考如下腳本create or replace function to_base( p_dec in number, p_base in number )
 return varchar2
is
 l_str varchar2(255) default NULL;
 l_num number default p_dec;
 l_hex varchar2(16) default '0123456789ABCDEF';
begin
 if ( p_dec is null or p_base is null ) then
 return null;
 end if;
 if ( trunc(p_dec) p_dec OR p_dec 20;


 [Q]怎麼樣抽取重複記錄[A]select * from table t1 where where t1.rowed !=
 (select max(rowed) from table t2
 where t1.id=t2.id and t1.name=t2.name)
 或者select count(*), t.col_a,t.col_b from table t
 group by col_a,col_b
 having count(*)>1
 如果想刪除重複記錄,可以把第一個語句的select替換為delete


 [Q]怎麼樣設置自治事務[A]8i以上版本,不影響主事務pragma autonomous_transaction;
……
commit|rollback;


 [Q]怎麼樣在過程中暫停指定時間[A]DBMS_LOCK包的sleep過程如:dbms_lock.sleep(5);表示暫停5秒。


 [Q]怎麼樣快速計算事務的時間與日誌量[A]可以採用類似如下的腳本DECLARE
 start_time NUMBER;
 end_time NUMBER;
 start_redo_size NUMBER;
 end_redo_size NUMBER;
BEGIN
 start_time := dbms_utility.get_time;
 SELECT VALUE INTO start_redo_size FROM v$mystat m,v$statname s
xyz資訊工坊  WHERE m.STATISTIC#=s.STATISTIC#
 AND s.NAME='redo size';
 --transaction start
 INSERT INTO t1
 SELECT * FROM All_Objects;
 --other dml statement
COMMIT;
 end_time := dbms_utility.get_time;
 SELECT VALUE INTO end_redo_size FROM v$mystat m,v$statname s
 WHERE m.STATISTIC#=s.STATISTIC#
 AND s.NAME='redo size';
 dbms_output.put_line('Escape Time:'||to_char(end_time-start_time)||' centiseconds');
 dbms_output.put_line('Redo Size:'||to_char(end_redo_size-start_redo_size)||' bytes');
END;


 [Q]怎樣創建臨時表[A]8i以上版本create global temporary tablename(column list)
 on commit preserve rows;--提交保留數據會話臨時表on commit delete rows;--提交刪除數據事務臨時表臨時表是相對於會話的,別的會話看不到該會話的數據。


 [Q]怎麼樣在PL/SQL中執行DDL語句[A]1、8i以下版本dbms_sql包2、8i以上版本還可以用execute immediate sql;
dbms_utility.exec_ddl_statement('sql');
[Q]怎麼樣獲取IP地址[A]服務器(817以上):utl_inaddr.get_host_address
 客戶端:sys_context('userenv','ip_address')


 [Q]怎麼樣加密存儲過程[A]用wrap命令,如(假定你的存儲過程保存為a.sql)
 wrap iname=a.sql
 PL/SQL Wrapper: Release 8.1.7.0.0 - Production on Tue Nov 27 22:26:48 2001
 Copyright (c) Oracle Corporation 1993, 2000.All Rights Reserved.
 Processing a.sql to a.plb
 提示a.sql轉換為a.plb,這就是加密了的腳本,執行a.plb即可生成加密了的存儲過程[Q]怎麼樣在ORACLE中定時運行存儲過程[A]可以利用dbms_job包來定時運行作業,如執行存儲過程,一個簡單的例子,提交一個作業:
 VARIABLE jobno number;
BEGIN
 DBMS_JOB.SUBMIT(:jobno, 'ur_procedure;',SYSDATE,'SYSDATE + 1');
commit;
END;
 之後,就可以用以下語句查詢已經提交的作業select * from user_jobs;


 [Q]怎麼樣從數據庫中獲得毫秒[A]9i以上版本,有一個timestamp類型獲得毫秒,如SQL>select to_char(systimestamp,'yyyy-mm-dd hh24:mi:ssxff') time1,
xyz資訊工坊  to_char(current_timestamp) time2 from dual;


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


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


 [Q]如果存在就更新,不存在就插入可以用一個語句實現嗎[A]9i已經支持了,是Merge,但是只支持select子查詢,
 如果是單條數據記錄,可以寫作select …… from dual的子查詢。
 語法為:
 MERGE INTO table
 USING data_source
 ON (condition)
 WHEN MATCHED THEN update_clause
 WHEN NOT MATCHED THEN insert_clause;
 如MERGE INTO course c
 USING (SELECT course_name, period,
course_hours
 FROM course_updates) cu
 ON (c.course_name = cu.course_name
 AND c.period = cu.period)
 WHEN MATCHED THEN
UPDATE
 SET c.course_hours = cu.course_hours
 WHEN NOT MATCHED THEN
 INSERT (c.course_name, c.period,
c.course_hours)
 VALUES (cu.course_name, cu.period,
cu.course_hours);


 [Q]怎麼實現左聯,右聯與外聯[A]在9i以前可以這麼寫:
 左聯:
 select a.id,a.name,b.address from a,b
 where a.id=b.id(+)
 右聯:
 select a.id,a.name,b.address from a,b
 where a.id(+)=b.id
 外聯SELECT a.id,a.name,b.address
 FROM a,b
 WHERE a.id = b.id(+)
UNION
 SELECT b.id,'' name,b.address
 FROM b
 WHERE NOT EXISTS (
 SELECT * FROM a
 WHERE a.id = b.id);
 在9i以上,已經開始支持SQL99標準,所以,以上語句可以寫成:
 默認內部聯結:
 select a.id,a.name,b.address,c.subject
 from (a inner join b on a.id=b.id)
 inner join c on b.name = c.name
 where other_clause
 左聯select a.id,a.name,b.address
 from a left outer join b on a.id=b.id
 where other_clause
 右聯select a.id,a.name,b.address
 from a right outer join b on a.id=b.id
 where other_clause
 外聯select a.id,a.name,b.address
 from a full outer join b on a.id=b.id
 where other_clause
or
 select a.id,a.name,b.address
 from a full outer join b using (id)
 where other_clause


 [Q]怎麼實現一條記錄根據條件多表插入[A]9i以上可以通過Insert all語句完成,僅僅是一個語句,如:
 INSERT ALL
 WHEN (id=1) THEN
 INTO table_1 (id, name)
values(id,name)
 WHEN (id=2) THEN
 INTO table_2 (id, name)
values(id,name)
ELSE
 INTO table_other (id, name)
 values(id, name)
 SELECT id,name
 FROM a;
 如果沒有條件的話,則完成每個表的插入,如INSERT ALL
 INTO table_1 (id, name)
values(id,name)
 INTO table_2 (id, name)
values(id,name)
 INTO table_other (id, name)
 values(id, name)
 SELECT id,name
 FROM a;


 [Q]如何實現行列轉換[A]1、固定列數的行列轉換如studentsubject grade
---------------------------
 student1語文80
 student1數學70
 student1英語60
 student2語文90
 student2數學80
 student2英語100
……
 轉換為語文數學英語student1 8070 60
 student2 9080 100
……
 語句如下:
 select student,sum(decode(subject,'語文', grade,null)) "語文",
 sum(decode(subject,'數學', grade,null)) "數學",
xyz軟體補給站  sum(decode(subject,'英語', grade,null)) "英語"
 from table
 group by student


 2、不定列行列轉換如c1 c2
--------------
 1我1是1誰2知2道3不……
 轉換為1我是誰2知道3不這一類型的轉換必須藉助於PL/SQL來完成,這裡給一個例子CREATE OR REPLACE FUNCTION get_c2(tmp_c1 NUMBER)
 RETURN VARCHAR2
IS
 Col_c2 VARCHAR2(4000);
BEGIN
 FOR cur IN (SELECT c2 FROM t WHERE c1=tmp_c1) LOOP
 Col_c2 := Col_c2||cur.c2;
 END LOOP;
 Col_c2 := rtrim(Col_c2,1);
 RETURN Col_c2;
END;
/
 SQL> select distinct c1 ,get_c2(c1) cc2 from table;即可[Q]怎麼樣實現分組取前N條記錄[A]8i以上版本,利用分析函數如獲取每個部門薪水前三名的員工或每個班成績前三名的學生。
 Select * from
 (select depno,ename,sal,row_number() over (partition by depno
 order by sal desc) rn
 from emp)
 where rnset heading off
 set feedback off
 spool temp.txt
 select * from tab;
dbms_output.put_line(‘test’);
 spool off
exit
EOF


 [Q]如何在SQL*PLUS環境中執行OS命令?
 [A]比如進入了SQLPLUS,啟動了數據庫,忽然想起監聽還沒有啟動,此時不用退出SQLPLUS,也不用另外起一個命令行窗口,直接輸入:
 SQL> host lsntctl start
 或者unix/linux平台下SQL>!
 windows平台下SQL>$
 總結:HOST可以直接執行OS命令。
 備註:cd命令無法正確執行。


 [Q]怎麼設置存儲過程的調用者權限[A]普通存儲過程都是所有者權限,如果想設置調用者權限,請參考如下語句create or replace
 procedure ……()
 AUTHID CURRENT_USER
As
begin
……
end;


ORACLE PL/SQL 常用轉換函數(轉)



to_char(d[,fmt[,'nlsparams']])
–◎ 轉換日期欄位資料成自定格式文字
–◎ 當沒有輸入fmt時,將使用預定的日期格式轉換
–◎ ‘nlsparams’是用來決定月份與日期的縮寫格式,語法為’NLS_DATE_LANGUAGE = language’


ex1.
select sysdate, to_char(sysdate,’Month DD,YYYY HH:MI:SS’) aa from dual;


SYSDATE AA
———- ————————–
27-SEP-07 September 27,2007 11:40:07


–◎ 轉換數字欄位資料成自定格式文字串
–◎ ‘nlsparams’可用來定義下列數字格式
xyz — 1. 小數點(.)
— 2. 每三位為一單位的區隔符號(,)
— 3. 區域性的幣值符號(NT)
— 4. 國際發行的幣值符號($)
— 設定方式;
— ‘NLS_NUMBERIC_CHARACTERS = “dg”
— NLS_CURRENCY = “text”
— NLS_ISO_CURRENCY = territory’


ex2.
select to_char(-10000,’L99G999D99MI’) aa from dual;


AA
—————
NT$10,000.00-


select to_char(-10000,’L99G999D99MI’,
‘NLS_NUMERIC_CHARACTERS=., NLS_CURRENCY=AUD’) aa from dual;


–◎ L99:Currency
–◎ G999:Group
–◎ D99:小數點
–◎ MI:負號


to_date(char[,fmt])
— 根據fmt的格式將char或varchar2的資料型態轉成date的資料型態


ex.
select sysdate, to_date(’20070808′,’YYYYMMDD’) aa from dual;


SYSDATE AA
———- ———-
21-SEP-07 08-AUG-07


to_number(char,[,fmt[,'nlsparams']])
–將數字格式的文字,轉換成數字


ex.
select to_number(’NT$10,000.00′,’L99G999D99′) aa from dual;
AA
———-
10000


select to_number(’1000′)+10 aa from dual;
AA
———-
1010


 


xyz軟體補給站 Oracle資料庫Date資料型態的使用


如果只要存入日期,可以利用內建函數
TRUNC(date)
來消去,時、分、秒的資料。


關於料號的SQL取值



1.取料號.單位及版本

  SELECT msi.inventory_item_id, msi.primary_uom_code,MAX(mir.revision) max_revision
           INTO v_inv_id, v_item_unit,v_revision
           FROM mtl_system_items_b msi,mtl_item_revisions_b mir
          WHERE msi.organization_id = 127
          AND msi.segment1 = temp_rec.items
xyz資訊工坊           AND msi.inventory_item_id=mir.inventory_item_id
          AND mir.organization_id = 127
           GROUP BY  msi.inventory_item_id, msi.primary_uom_code;

2.找ON_HAND
 SELECT LOT_NUMBER ,TRANSACTION_QUANTITY
      INTO V_LOT_NUMBER,V_TRANSACTION_QUANTITY
      FROM MTL_ONHAND_QUANTITIES 
    WHERE INVENTORY_ITEM_ID=V_INV_ID
    AND ORGANIZATION_ID=127
xyz軟體補給站     AND SUBINVENTORY_CODE=V_SUB_CODE
    AND LOT_NUMBER=V_LOT
   -- AND TRANSACTION_QUANTITY=V_QTY
    AND LOCATOR_ID=V_INVENTORY_LOCATION_ID_GET;
       EXCEPTION
       WHEN NO_DATA_FOUND THEN
             MESSAGE('找不到LOT名稱['|| V_LOT ||'],匯入動作已取消,請檢查!');
             RAISE EX_LOT_NUMBER;
    WHEN OTHERS THEN
      NULL;
      END; 

  3.
 SELECT LOT_NUMBER ,TRANSACTION_QUANTITY,CREATE_TRANSACTION_ID
         INTO V_LOT_NUMBER,V_TRANSACTION_QUANTITY,V_CREATE_TRANSACTION_ID
         FROM MTL_ONHAND_QUANTITIES 
       WHERE INVENTORY_ITEM_ID=V_INV_ID
       AND ORGANIZATION_ID=127
       AND SUBINVENTORY_CODE=V_SUB_CODE
       AND LOT_NUMBER=V_LOT;   


查詢FORM中F11,F12按鈕功能的小探討


查詢FORMF11F12按鈕功能的小探討


     在咱們ERP系統中,F11F12按鈕是大家經常使用的,它們給查詢工作帶來了很多方便。但是在開發的查詢FORM中若不做任何設置,F11F12按鈕的作用就沒有完全體現出來了。


如當你輸入了查詢條件點擊“FIND”按鈕後得到了你想要的一些記錄,然後針對這些記錄我們想繼續進行相關條件的查詢(F11按鈕功能)或者想查詢記錄的數目(F12按鈕功能)。但如果未做任何設置,F11F12功能將在查詢結果塊所在資料源的範圍內查詢而不是你輸入查詢條件查到的結果內查詢,這顯然沒有實現我們想要的功能。


     一般情況下,我們開發的查詢FORM均是在資料塊QUERY_FIND按鈕項FINDWHEN-BUTTON-PRESSED觸發器中寫入(例如查詢結果塊名為“RESULT”)


     :parameter.G_query_find := 'TRUE';


app_find.find('RESULT');


:parameter.G_query_find := 'FALSE';


然後我們在查詢結果塊(RESULT)的block級觸發器PRE-QUERY中寫入:


IF :parameter.G_query_find = 'TRUE' THEN


: RESULT.ID := :QUERY_FIND.ID; --查詢條件之ID


app_find.query_range(:QUERY_FIND.date_from,


                       :QUERY_FIND.date_to,


                       RESULT.DATE'); --查詢條件之DATE範圍


xyz資訊工坊 COPY (:QUERY_FIND.status,'RESULT.STATUS'); --xyz 查詢條件之STATUS


:parameter.G_query_find := 'FALSE';


END IF;


我們可以看出parameter.G_query_find的作用是標記查詢來源,若:parameter.G_query_find = 'TRUE'則意味著查詢來源於查詢資料塊QUERY_FIND點擊“FIND”按鈕後。顯然查詢來源是F11F12按鈕查詢的情況沒有在這個範圍內,所以只要將此來源考慮進來就可以了。


針對本例情況,查詢來源除了查詢塊QUERY_FIND就只有F11F12的查詢了,所以可以將F11F12查詢動作控制放在查詢結果塊(RESULT)的block級觸發器PRE-QUERYIF語句的ELSE情況中就可以了。


其實很多情況下例如本例中兩種查詢來源的查詢動作控制是一致的,所以本例我們可以用這種方法來解決:


1、資料塊QUERY_FIND按鈕項FINDWHEN-BUTTON-PRESSED觸發器中改為:


xyz資訊工坊 app_find.find('RESULT');


2、查詢結果塊(RESULT)的block級觸發器PRE-QUERY中改為:


lv_where_string VARCHAR2(32767);


begin


lv_where_string :=’(:QUERY_FIND.ID is null or ID = :QUERY_FIND.ID)


and (date >= :QUERY_FIND.date_from or :QUERY_FIND.date_from is null )


and (date <= :QUERY_FIND.date_to or :QUERY_FIND.date_to is null)


and (:QUERY_FIND.status is null or status = :QUERY_FIND.status)’;


SET_BLOCK_PROPERTY('RESULT',DEFAULT_WHERE,lv_where_string);


exception when others then


                               fnd_message.debug(SQLCODE||'is'||SQLERRM);xyz軟體補給站


end;


這種解決方法是取消了查詢來源標記,將兩種查詢動作合二為一了(其實算是偷懶了)。


我這種方法應該不太規範,現在向大家請教一下規範的方法,望不吝賜教。


 


提交處理事務處理介面請求


--- 提交處理事務處理介面請求
l_request_id := FND_REQUEST.SUBMIT_REQUEST(
APPLICATION => 'INV',
xyz資訊工坊 PROGRAM => 'INCTCM'
);
IF ( l_request_id = 0 ) THEN
RAISE E_SUBMIT_FAILED;
RETURN;
ELSE
COMMIT;
L_REQUEST_FLAG := FND_CONCURRENT.WAIT_FOR_REQUEST(
REQUEST_ID => L_REQUEST_ID,
INTERVAL => 5,
MAX_WAIT => 0,
PHASE => L_PHASE,
STATUS => L_STATUS,
DEV_PHASE => L_DEV_PHASE,
xyz DEV_STATUS => L_DEV_STATUS,
MESSAGE => L_MESSAGE
);
END IF;
COMMIT;
xyz軟體補給站 EXCEPTION
WHEN E_SUBMIT_FAILED THEN
ERRCODE := '1';
ERRMSG := '提交處理事務處理介面請求失敗!'||SUBSTR(SQLERRM,1,100);
FND_FILE.PUT_LINE(FND_FILE.LOG,ERRMSG);
ROLLBACK;
RETURN;
END;
今天關注到這個問題,將找到的資料收集在這裏:
1、關於fnd_request.submit_request的用法
fnd_request.submit_request的用法:
FND_REQUEST.SUBMIT_REQUEST 函數是用來提交一個請求的,它返回一個NUMBER值.具體調用如下
:result := fnd_request.submit_request(application CHAR, --AP模快
program CHAR, --應用程式
description CHAR, --請求說明(可選)
start_time CHAR, --RUN 時間(可選)
sub_request BOOLEAN, --立刻提交請求
argument1 CHAR, --參數1
argument2 CHAR, --參數2
argument3 CHAR, --參數3
argument4 CHAR, --參數4
argument5 CHAR, --參數5.......
argument100 CHAR);
英文說明(zt oracle) :
Parameters are as follows:
application - Short name of the application associated with the concurrent
request to be submitted.
program - Short name of the concurrent program (not the executable) for which
xyz軟體補給站 the request should be submitted.
description - Description of the request that is displayed in the Concurrent
Requests form (Optional.)
start_time - Time at which the request should start running, formatted as HH24:
MI or HH24:MI:SS (Optional.)
sub_request - Set to TRUE if the request is submitted from another request and
should be treated as a sub-request.
argument1...100 - Arguments for the concurrent request; up to 100
arguments are permitted. If submitted from Oracle Forms, you must specify all
100 arguments.
補充說明:
在用fnd_request.submit_request的時候,第五個參數用false,不要被參數名稱誤導;
這個函數有105個參數,前面五個定義請求本身,後面100個是傳遞給請求的具體參數,都是Char類型,
我們需要轉換,預設值是chr(0),代表這個參數不用傳遞給調用的請求;
在Package裏面調用只需要傳遞需要的參數個數,因為它有預設值指示結束;
在form裏面則不行,要寫滿105個,而且我們參數結束之後要用一個chr(0)來表示結束

fnd_request.submit_request('AR',
'SVAINEX_P',
'',
'',
FALSE,
:parameter.invoice_store,
chr(0),
'','','',
'','','','','','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','','','','','','',
'','','','','','','','','','','','','','','');
2、Oracle Erp等待報表運行機制
主要是用到了Fnd_concurrent.wait_for_ruqest這個function.
Fnd_concurrent.wait_for_request返回Boolean值,主要參數如下:
function FND_CONCURRENT.WAIT_FOR_REQUEST
(request_id IN number default NULL, --請求ID
interval IN number default 60, --檢查時間間隔
max_wait IN number default 0, --最大等待時間
phase OUT varchar2,
status OUT varchar2,
dev_phase OUT varchar2, --請求運行階段
dev_status OUT varchar2, --各個階段狀態
message OUT varchar2 --運行完成後輸出資訊)
return boolean;
dev_phase有Pending,Running,Complete,Inactive等幾種,每種對應不同的Dev-Status,比如Complete階段後就有Normal,Error,Warning,Cancelled,Terminated等幾種狀態。
例如: l_request_status := Fnd_Concurrent.Wait_For_Request(l_request_id,
5,
0,
l_phase,
l_status,
l_dev_phase,
l_dev_status,
l_message);
IF l_request_status THEN
IF l_dev_status = 'NORMAL' THEN
NULL;
ELSE
Fnd_Message.Debug('請求運行不成功:'||l_dev_status);
RETURN;
END IF;
ELSE
Fnd_Message.Debug('請求未完成,無法查看報表內容!');
RETURN;
END IF;
Editor_Pkg.Report(l_request_id,'Y');
總結:FND_REQUEST.SUBMIT_REQUEST是一種通過後臺方式提交請教的方法,可以在pkg和form中使用,在form中使用要將參數寫全。 FND_CONCURRENT.WAIT_FOR_REQUEST是一個等待當前請求運行完畢的程式,可以利用這個等待當前的請求程式運行完畢再運行下面的程式。


 


2010年4月13日星期二

如何判斷 execute_query 查詢結果是否有記錄?

如何判斷 execute_query 查詢結果是否有記錄? 
IF :SYSTEM.BLOCK_STATUS = 'NEW' THEN
xyz資訊工坊   message('沒有查詢到所要的記錄!!!'); 
END IF;

基礎篇

文本項 TEXT_ITEM

顯示項 DISPLAY_ITEM

列表項 LIST

復選框 CHECKBOX

單選組 RADIO_GROUP

按鈕項 BUTTON

畫布 CANVAS

窗口 WINDOW

塊 BLOCK

彈性域 TEXT_ITEM_DESC_FLEX

當前記錄開始項 CURRENT_RECORD_INDICATOR

只顯示文本項 TEXT_ITEM_DISPLAY_ONLY

時間文本項 TEXT_ITEM_DATE

在text檔裡,判斷多少筆數.


xyz軟體補給站 在text檔裡,判斷多少筆數.


                                11111
                                22222
                                33333
                                44444


begin  
       text_io.get_line(v_in_file,v_linebuf);   
       exit when v_linebuf is null;  
       exception  
       when no_data_found then  
        text_io.fclose(v_in_file);  
           
      exit;         
    end;  
     v_total_count := v_total_count+1;  
  end loop;  

xyz軟體補給站 xyz軟體補給站xyz

在server run 修改D2K程式的步驟


 在server run 修改D2K程式的步驟 :


1.先將檔案上傳至ORACLE SERVER上
  例 : /oracle/testmgr1/cherpdv1appl/au/11.5.0/forms/US
   ps: 必須是fmb的檔案


2.在開始WINDOWS→執行→輸入CMD→畫面將打開DOS
  2.1 輸入Telnet 10.12.25.23
      ps: 10.12.25.23 為oracle主機檔案存放的ip位置,在此為例
  2.2 輸入登入的帳號及密碼
      ps: 登入oracle主機伺服器的帳密
xyz軟體補給站 xyz資訊工坊   2.3 輸入檔案路徑
      cd $AU_TOP/forms/US
  2.4 輸入要compiler的檔名
      例 : tinvcom 檔名
      ps : tinvcom模組名稱


tinvcom script file內容,把tinvom製成script file上傳至server,副檔名為sql
#clear
echo 'now compiler Form $1.fmb....'
date
rm $INV_TOP/forms/US/$1.fmx
ls -l $1.fmb
$ORACLE_HOME/bin/f60gen module=$AU_TOP/forms/US/$1.fmb userid=APPS/APPS output_file=$INV_TOP/forms/US/$1.fmx module_type=form batch=YES compile_all=special
ls -l $1.err
ls -l $INV_TOP/forms/US/$1.fmx


  2.5 當compiler完成後,會出現三行
      fmb
      err
      fmx
      當系統產生fmx就表示compiler成功


3.當檔案上傳成功後,就可以至oracle erp裡看客製的form是否有修改成功.


SET_BLOCK_PROPERTY - DEFAULT_WHERE應用


假設我們現在要查xyz資訊工坊 員工編號在 1000~2000 之間,且姓王的員工

<
查詢畫面>
Block Name : B_QUERY_FIND
Item Name : emp_name "
員工姓名" , emp_no_beg "員工編號起" , emp_no_end "員工編號迄"

<
主畫面>
Block Name : B_MAIN
Item Name : emp_name "
員工姓名" , emp_no "員工編號"

xyz 因為兩個 Block 的員工姓名資料是可以 maping 的,
B_MAIN block level trigger : PRE-QUERY 中加上
copy( :B_QUERY_FIND.EMP_NAME , 'B_MAIN.EMP_NAME' );

如此不管在 :B_QUERY_FIND.EMP_NAME 打完整名稱,或以 % 來查詢都可以

因為員工編號的查詢條件是以區間來查詢,所以在  FIND Button 中處理
declare
   ls_where         varchar2(1000);
   ls_this_where    varchar2(1000);
begin
   if     :b_query_find.emp_no_beg is null
      and :b_query_find.emp_no_end is null
   then
      :parameter.g_query_find := 'FALSE';
      Fnd_Message.Set_Name('FND','You Must Enter Employee Number !!');
      Fnd_Message.Error;
   else
      ls_where := GET_BLOCK_PROPERTY('B_MAIN',DEFAULT_WHERE);
      if  ls_where is null
      then
         ls_this_where := '1=1 ';
      else
         ls_this_where := ls_where;
      end if;
      if    :b_query_find.emp_no_beg is not null
      then
         ls_this_where := ls_this_where||' and emp_no >= :b_query_find.emp_no_beg';
      end if;
      if    :b_query_find.emp_no_end is not null
xyz資訊工坊       then
         ls_this_where := ls_this_where||' and emp_no <= :b_query_find.emp_no_end';
      end if;
      SET_BLOCK_PROPERTY(''B_MAIN',DEFAULT_WHERE,LS_THIS_WHERE);
      app_find.find('B_MAIN');
      SET_BLOCK_PROPERTY('B_MAIN',DEFAULT_WHERE,LS_WHERE);
   end if;
end;
:parameter.g_query_find := 'FALSE';

以此例而言 :
:B_QUERY_FIND.EMP_NAME := '
%'
:B_QUERY_FIND.EMP_NO_BEG := '1000'
:B_QUERY_FIND.EMP_NO_END := '2000'


Oracle Form (使用注意事項-轉)


 一、處理錯誤
 
1.當錯誤出現在Oracle Form PL/SQL中時,處理的方法如下: 
 IF (err_condition) THEN  
    Fnd_message.set_name(appl_short_name,message_name); 
    Fnd_message.error;  
 RAISE form_trigger_failure; 
 END IF; 
 
2.當錯誤出現在Stored Procedure中時,處理的方法如下: 
 IF (err_condition) THEN 
     Fnd_message.set_name(appl_short_name,message_name); 
     App_exception.raise_exception; 
 END IF;
 
 
3.當我們在測試FORM_SUCCESS,FORM_FAILURE和FORM_FATAL的時候,
  可能觸發了目地的子程序而導至它們的值發生改變,例如下面這個例子:
 
  GO_ITEM(‘emp.empno’);
 
 IF FROM_FAILURE THEN 
 RAISE FORM_TRIGGER_FAILURE;  
xyz資訊工坊  END IF; 
 
 GO_ITEM引起其它的觸發器觸發,比如WHEN-NEW-ITEM-INSTANCE,儘管GO_ITEM可能執行失敗,
 但是後面的Trigger有可能執行成功,這就意味著FROM_FAILURE是失效的,
 為了避免這種情況發生,可以改為下面這樣:
 
 GO_ITEM(‘emp.empno’); 
 IF :SYSTEM.CURSOR_ITEM != ‘EMP.EMPNO’ THEN  
    RAISE FORM_TRIGGER_FAILURE;  
 END IF;
 
 4.避免使用RAISE_APPLICATION_ERROR,因為它與我們使用的進程服務的設置有衝突 
 
 5.不要使用CALL_FORM,你可以使用FND_FUNCTION.EXECUTE來代替CALL_FORM或是OPEN_FORM
 
 
 二、在Oracle Application中使用PL/SQL中需要注意的地方
 
 1.使用select … from dual來代替select … from sys.dual ;
 
 2.只返回一條行的Select查詢要處理NO_DATA_FOUND例外, INSERT 、 UPDATE 、 DELETE
   不會產生這個例外,要使用SQL%NOTFOUND來檢查是否有數據  
 
 三、 Triggers in Forms 
 1.所有的BLOCK或是FIELD的TRIGGER的執行類型都是Override或是Before,一般情況下,
   使用的是Before類型,因為通常相同的Trigger在FORM層級同樣也會觸發.
   這個例外是如果彈性域調用了From層次的POST-QUERY ,但是你在BLOCK的POST-QUERY中重置了
   這個塊的查詢狀態,像這種情況, BLOCK層的POST-QUERY必須將執行類型設置為After 
 
 四、使用APPCORE來代替Oracle Forms Built-In, APPCORE包含了一些等同於Oracle Forms built-ins的功能
 
 EXIT_FORM不要直接使用EXIT_FROM,應該始終使用do_key(‘EXIT_FORM’),
xyz軟體補給站  如果需要退出整個Oracle applications suite,應該首先調用copy(‘Y’,’GLOBAL.APPCORE_EXIT_FLAG’);
 然後再調用Do_key(‘EXIT_FORM’); 
 
 SET_ITEM_PROPERTY使用APP_ITEM_PROPERTY.SET_PROPERTY和APP_ITEM_PROPERTY.SET_VISUAL_ATTRIBUTE來代替 
 GET_ITEM_PROPERTY使用APP_ITEM_PROPERTY.GET_PROPERTY來代替 
 OPEN_FORM使用FND_FUNCTION.EXECUTE來代替 
 CLEAR_FORM使用do_key(‘CLEAR_FORM’)來代替
 
 COMMIT使用do_key(‘COMMIT_FORM’)來代替
 
 EDIT_FIELD使用do_key(‘EDIT_FIELD’)來代替,這個程序噹噹前的ITEM是DATE的時彈出Calendar
 
 VALIDATE使用APP_STANDARD.APP_VALIDATE來代替 
 
 五、 Coding Table handlers (參考Oracle Application Developer ’ s Guide)
 
 
 六、設置物件的屬性 
 1. Canvas的大小最大隻能設置到高5 inch 、寬7.8 inch ,目的是為了更好的適應客戶端的環境 
 2.使用APP_CUSTOM.OPEN_WINDOW和APP_CUSTOM.CLOSE_WINDOW來打開和關閉window,
   不過使用go_block也可以達到打開window的功能
 
 3. APP_SPECIAL用來控制菜單項是否可用 
 
 七、設置ITEM的一些屬性
 
1.Text Items
 
 一般情況下,大多數的Text items使用TEXT_ITEM這個屬性類,而需顯示多行的使用TEXT_ITEM_MULTILINE屬性類,
 如果是field是date類型使用TEXT_ITEM_DATE 
 設置它的查詢長度為255個字符
 
 
 2.Date Fields 
 可以使用$$DBDATE$$或是$$DBDATETIME$$來設置作為它的預設日期
 
 
 3.使LOV在ENTER-QUERY模式下應用於一個ITEM ,創建一個ITEM層級的KEY-LISTVAL觸發器,如下: 
 IF (:SYSTEM.MODE != ‘ENTER-QUERY’) THEN 
    LIST_VALUES;  
 ELSE
   SHOW_LOV(‘query lov’); 
xyz END IF;
 
 
4. Flexfields  
   鍵彈性域使用的是’ENABLE_LIST_LAMP’這個LOV ,並且將驗證設為No ,描述性彈性域不會使用到LOV
 
 
 八、控制Window 、 BLOCK
 
1. 控制運行時期的window
 
 例如在採購訂單窗口包含了一個標籤叫做’Lines’的按鈕,點擊它去到另一個窗口LINES這個塊,需要的步驟如下:
 
 
 第一步:修改以下的Trigger
 
 Trigger : PRE-FORM 
 App_window.set_window_position(‘HEADER’,’FIRST_WINDOW’);
 
 
 Trigger: WHEN-BUTTION-PRESSED 
 app_custom.open_window(‘LINES’); 
 第二步:修改APP_CUSTOM.OPEN_WINDOW
 
 If wnd = ‘LINES’ then 
    App_window.set_window_position(‘LINES’,’CASCADE’,’HEADER’);  
 Go_block(‘lines’); 
 End if;
 
 可用的類型有以下幾種: 
 ◆ CASCADE此類型當子窗口打開的時候,會顯示在父窗口的上面並距離父窗口的右邊0.3,通常使用於明細窗口  
 ◆ RIGHT, BELOW略 
 ◆ OVERLAP略 
 ◆ CENTER略  
 ◆ FIRST_WINDOW通常用於主窗口
 
 
 2.關閉窗口 
 一個FORM具有三個窗口分別是’Header’,’Lines’和’Shipments’,Shipments是Lines的明細窗口,
 而Lines是Header的明細窗口,從邏輯上講關閉窗口如下: 
 Procedure close_window(wnd varchar20 is
 
 If wnd = ‘HEADER’ then
 
App_window.close_first_window;
 
 Elsif wnd = ‘lines’ then
 
App_custom.close_window(‘shipments’);
 
 If (wnd = get_view_property(get_item_property(:system.cursor_item,item_canvas), 
 window_name) then
 
 go_block(‘header’); 
 end if; 
 elsif wnd = ‘shipments’ then
 
 If (wnd = get_view_property(get_item_property(:system.cursor_item,item_canvas),
 
 window_name) then
 
 go_block(‘lines’); 
 end if; 
 end if; 
hide_window(wnd);
 
end;
 
 
3.在執行過程中使用查詢 
 如果你想在打開FORM之前調用一個ROW-LOV或是查詢窗口,在WHEN-NEW-FORM-INSTANCE後面加上:
 
 EXECUTE_TRIGGER(‘QUERY_FIND’); 


 

Oracle ERP系統工具欄上ZOOM按鈕的開發


 在 ERP 標準 custom.pll 文件中,填寫下麵類似代碼:
FUNCTION zoom_available RETURN BOOLEAN IS
form_name  varchar2 ( 30 ) := name_in( 'system.current_form' );
 block_name varchar2 ( 30 ) := name_in( 'system.cursor_block' );
BEGIN
 if (form_name = 'WIPDJMDF' ) then
return TRUE ;
 elsif (form_name = 'POXSCASL' and block_name = 'ASL_SUPPLIERS' ) then
return TRUE ;
else
return FALSE ;
end if ;
 END zoom_available; 上段代碼表示我們在 form_name 為:“ WIPDJMDF ”,“ POXSCASL ”的時候 ZOOM 按鈕可用 ;
 然後在自己定義的 pll 文件中響應 ZOOM 按鈕:
procedure event(event_name varchar2 ) is
xyz軟體補給站 Form_Name  Varchar2 ( 30 ) := Name_In( 'system.current_form' );
Block_Name  Varchar2 ( 30 ) := Name_In( 'system.current_block' );
Item_Name  Varchar2 ( 30 ) := Name_In( 'system.current_item' );
Form_Status  Varchar2 ( 30 ) := Name_In( 'system.form_status' );
 l_Record_Status Varchar2 ( 30 ) := Name_In( 'system.record_status' );
v_Stage Varchar2 ( 1000 );
v_item_id number ;
V_vendor_name varchar2 ( 300 );
 Begin /*when form. instance*/
DEFAULT_VALUE( null , 'GLOBAL.XXUTS_MFG_REVISION_MPN' );  /* 全局參數 */
 if (event_name = 'ZOOM' and form_name = 'POXSCASL' ) then
v_item_id:=Name_In( 'ASL_ITEMS.ITEM_ID' );
 FND_FUNCTION. EXECUTE ( /* 調用另一 Form*/
function_name=> 'XXUTS_MFG_ITEM_REVISION' ,
 other_params => 'INVENTORY_ITEM_ID =' ||v_item_id);
End if ;
 If (form_name = 'POXSCASL' )  and (event_name = 'WHEN-NEW-ITEM-INSTANCE' ) THEN
xyz資訊工坊 if NAME_IN( 'GLOBAL.XXUTS_MFG_REVISION_MPN' ) is not null then
copy(name_in( 'global.XXUTS_MFG_REVISION_MPN' ), 'ASL_SUPPLIERS.PRIMARY_VENDOR_ITEM' );
COPY( null , 'global.XXUTS_MFG_REVISION_MPN' );
end if ;
xyz軟體補給站 end if ;
end event;

xyz

LOV在欄位上的應用


1.透過PL-SQL直接叫系統已設的LOV用法 :
 DECLARE
a_value_chosen BOOLEAN;
BEGIN
go_block('sis_registration');
enter_query(no_validate);
a_value_chosen := Show_Lov('lovreg');
IF NOT a_value_chosen THEN
Message('You have not selected a value.');
RAISE Form_Trigger_Failure;
else
execute_query;
END IF;
END;


 


2.


取消LOV: 
 set_item_property('attendance_detail.employee_id',lov_name,'');  


不能使用: 
xyzset_item_property('attendance_detail.employee_id',lov_name,null);  
  
分配LOV: 
set_item_property('attendance_detail.employee_id',lov_name,'employee_lov');xyz軟體補給站  


FORM 簡易開發流程(轉)


製作登入、資料登錄畫面,按鈕觸發:      
      When-Button-Pressed  
        要實現下面幾個功能。        1。保存功能     輸入資料以後,按此按鈕保存到對應變數裏。  
        2。消除功能     消除所有輸入,恢復到原始狀態  
        3。輸出功能     將此表輸出到C:\aaa  
        4。翻頁功能     pageup   翻到上個畫面,pagedown下個畫面。  
        5。數據登入     順序排列,比如輸入   D,B,C,A   登陸時候按照A,B,C,D   排列  
        6。條件判斷     比如A項必須填寫,否則彈出錯誤對話方塊;如果填寫B項,但是資料庫裏面沒有B,也彈出對話方塊。  
        7。可能出現的錯誤、問題和bug  



   第一步   當然是建表了  
  example   :   --   create   table    
  drop   table   t_tname;  
  create   table   t_tname(xh     number(2),                  --   序號  
           xm      varchar2(10),                            --   姓名  
           csrq     date,                                       --   xyz資訊工坊 出生日期  
           bz       varchar2(100),                           --   備註  
          constraint   pk_t_tname   primary   key(xh));  



  下面以表格   t_tname   為例  
   
  第二步   就是實現功能了  
  打開form   builder   前期準備工作  
  首先要有一個畫布、視窗(假如將其名字名為cc_main,w_main)兩者必須對應,然後就是添加資料塊(就是選擇你建立的表格)佈局畫面,按照提示一步一步完成了,最後將你需要實現什麼功能添加功能按鈕,放在另外一個非資料庫塊  
   
  然後就是代碼編寫了。  
  1.WHEN-NEW-FORM-INSTANCE(進入FROM時執行)   所要做的就是初始化視窗和一些自己需要的查詢  
      1.1   將初始化視窗寫成一個過程  
   
  PROCEDURE   Prc_Init_Windows   IS  
   
  BEGIN  
      Set_Window_Property(Forms_Mdi_Window,TITLE,'WINDOW_NAME');             --設置多文檔視窗標題  
      Set_Window_Property(Forms_Mdi_Window,WINDOW_STATE,maximize);           --設置多文檔視窗最大化  
      Set_Window_Property('W_Main',WINDOW_STATE,maximize);                        --設置主視窗最大化  
      :System.Message_Level:='15';                                                             --設置資訊提示級別  
  END;  
  然後直接調用過程在WHEN-NEW-FORM-INSTANCE觸發器裏  
  --   code    
  Prc_Init_Windows;  
  GO_BLOCK('t_tname');  
  SET_BLOCK_PROPERTY('t_tname',INSERT_ALLOWED,PROPERTY_false);  
  SET_BLOCK_PROPERTY('t_tname',UPDATE_ALLOWED,PROPERTY_false);  
  execute_query;     --   內置副程式執行查詢(查詢所有記錄)  
   
  2.添加   (所要做的就是保證序號不能為空,關鍵字)  
  兩種操作方法一種直接在介面上輸入,二種彈出另外一個視窗進行操作  
  就講第一種吧,定義一個form參數p_xh   (在物件導航器裏面定義)  
  declare  
      nXH NUMBER(2);  
  BEGIN  
   
      GO_BLOCK('t_tname');  
      SET_BLOCK_PROPERTY('t_tname',INSERT_ALLOWED,PROPERTY_TRUE);  
      SET_BLOCK_PROPERTY('t_tname',UPDATE_ALLOWED,PROPERTY_false);  
      last_record;  
      create_record;  
      select   max(xh)   into   nXH   from   t_tname;  
      :parameter.p_xh   :=   nXH;  
      :t_tname.xh   :=   :parameter.p_xh;  
   
  END;  
   
  t_tname資料塊中添加WHEN-NEW-RECORD-INSTANCE觸發器  
      if   get_block_property('t_tname',insert_allowed)   =   'true'   then  
          if   :t_tname.xh   is   null   then  
              :parameter.p_xh   :=   :parameter.p_xh   +   1;  
              :t_tname.xh   :=   :parameter.p_xh;  
          end   if;  
      end   if;  
   
  3.修改  
      GO_BLOCK('t_tname');  
      IF   :t_tname.XH   IS   NOT   NULL   THEN  
          SET_BLOCK_PROPERTY('t_tname',INSERT_ALLOWED,PROPERTY_FALSE);  
          SET_BLOCK_PROPERTY('t_tname',UPDATE_ALLOWED,PROPERTY_TRUE);  
      END   IF;  
   
  4.刪除  
       
      GO_BLOCK('t_tname');  
      IF   :t_tname.XH   IS   NOT   NULL   THEN  
          SET_BLOCK_PROPERTY('t_tname',delete_ALLOWED,PROPERTY_true);  
          delete_record;  
          commit;  
          SET_BLOCK_PROPERTY('t_tname',delete_ALLOWED,PROPERTY_false);  
      END   IF;  
    xyz
  5.保存  
      GO_BLOCK('t_tname');  
      COMMIT;  
      SET_BLOCK_PROPERTY('t_tname',delete_ALLOWED,PROPERTY_FALSE);  
      SET_BLOCK_PROPERTY('t_tname',INSERT_ALLOWED,PROPERTY_FALSE);  
      SET_BLOCK_PROPERTY('t_tname',UPDATE_ALLOWED,PROPERTY_FALSE);  
   
  6.撤銷  
  DECLARE  
      P_WHERE       VARCHAR2(200);  
  BEGIN  
      GO_BLOCK('t_tname');        
      CLEAR_BLOCK(NO_COMMIT);  
      P_WHERE   :=   GET_BLOCK_PROPERTY('t_tname',DEFAULT_WHERE);  
      SET_BLOCK_PROPERTY('t_tname',DEFAULT_WHERE,P_WHERE);  
      EXECUTE_QUERY;  
  END;  
   
  7.查詢  
   
  以姓名和出生日期為欄位進行查詢,從新添加一個視窗和畫布,一個查詢非資料塊(例如塊名為BLK_QUERY)  
   
  DECLPARE  
      P_WHERE       VARCAHR2(200)   :=   '1=1';  
  BEGIN  
      IF   :BLK_QUERY.XM   IS   NOT   NULL   THEN  
          P_WHERE   :=   P_WHERE||'   AND   XM   =   '||CHR(39)||:BLK_QUERY.XM||CHR(39);  
      END   IF;  
      IF   :BLK_QUERY.CSRY   IS   NOT   NULL   THEN  
          P_WHERE   :=   P_WHERE||'   AND   TO_CHAR(CSRY,''YYYYMMDD'')   =           '||CHR(39)||TO_CHAR(:BLK_QUERY.CSRY,'YYYYMMDD')||CHR(39);  
      END   IF;  
   
      GO_BLOCK('t_tname');  
      CLEAR_BLOCK(NO_VALIDATE);  
      SET_BLOCK_PROPERTY('t_tname',DEFAULT_WHERE,P_WHERE);  
      EXECUTE_QUERY;  
  END;  


較新的文章 較舊的文章 首頁