取得EBS帳號用戶密碼

EBS 11i有個方法可以破解EBS帳號的密碼,網路上已有許多的文章都有提到,今天依據這些方法測試一下,
果然可以順利取得EBS帳號用戶的密碼。

EBS使用的加解密JAVA函數:

    加密函數:第一個參數是「金鑰」;第二個參數是「密碼明文」,傳回加密後字串
    oracle.apps.fnd.security.WebSessionManagerProc.encrypt(java.lang.String,java.lang.String) return java.lang.String

    解密函數:第一個參數是「金鑰」;第二個參數是「加密後字串」,傳回密碼明文
    oracle.apps.fnd.security.WebSessionManagerProc.decrypt(java.lang.String,java.lang.String) return java.lang.String

撰寫加解密的Package
    CREATE OR REPLACE package APPS.pk_password_use authid current_user as
        --加密函數
        function encrypt(v_key in Varchar2, value in Varchar2) return Varchar2;
        --解密函數
        function decrypt(v_key in Varchar2, value in Varchar2) return Varchar2;
    end;
    /

    CREATE OR REPLACE package body APPS.pk_password_use as
        function encrypt(key in Varchar2, value in Varchar2) return Varchar2 as
              language java name 'oracle.apps.fnd.security.WebSessionManagerProc.encrypt(java.lang.String,java.lang.String) return java.lang.String';
        function decrypt(key in Varchar2, value in Varchar2) return Varchar2 as
              language java name 'oracle.apps.fnd.security.WebSessionManagerProc.decrypt(java.lang.String,java.lang.String) return java.lang.String';
    end;
     /

取得APPS的密碼(任一個User/Password都可以取得)。

    --測試的結果的確可以取得APPS的密碼。
     --不用管fnd_user_view取出來的加密字串是什麼,只要USER/Password正確就可以了
    select APPS.pk_password_use.decrypt('GUEST/ORACLE',
        (select encrypted_foundation_password
                from apps.fnd_user_view
                where user_name='GUEST')) pwd
    from dual;


取得DB帳號PO的密碼。

    --前提是要有APPS密碼,假設密碼是APPS123。
    select APPS.pk_password_use.decrypt('APPS',
        (select encrypted_oracle_password
            from fnd_oracle_userid
            where oracle_username = 'PO';)) pwd
    from dual;
   
取得APP帳號GUEST的密碼。

    --前提是要有APPS密碼,假設密碼是APPS123。
    select APPS.pk_password_use.decrypt('APPS',
        (select encrypted_oracle_password
            from fnd_user
            where oracle_username = 'GUEST';)) pwd
    from dual;
      

用FND_USER_PKG修改EBS帳號密碼

EBS俢改帳號密碼,通常是在System Administrator --> Security --> User --> Define 更改,如下圖:


也可以用PL/SQL來更改密碼,如下面Script:

DECLARE
    v_check boolean;
BEGIN
    v_check := FND_USER_PKG.ChangePassword('OPERATIONS','welcome123');
        IF v_check THEN
            DBMS_OUTPUT.PUT_LINE('Password Changed');
         ELSE
            DBMS_OUTPUT.PUT_LINE('Changed Error');
         END IF;
END;

修改Oracle EBS的密碼

修改Oracle EBS的密碼

環境:
    DataBase:9.2.0.7
    Applications:11.5.10.2

修改前可以先備份FND_USER、FND_ORACLE_USERID兩個表格的資料


一、自行修改模組密碼:必須修改DB及EBS兩邊的密碼

1、登入SQL*Plus,更改DB的密碼,例如更改PO模組的密碼

   SQL> grant connect to po identified by po999;

2、登入EBS,System Administrator --> ORACLE --> Register


3、找出po並更改密碼,儲存時會出現注意視窗,主要告訴你DB的部份也要改,還有更改apps密碼注意事項



二、利用FNDCPASS來修改密碼:會自動更新DB、APP兩邊的密碼

1、FNDCPASS是一個專門用來更改密碼的指令,可以更改Oracle帳號(模組帳號)及EBS帳號密碼

2、FNDCPASS指令的位置放在 $FND_TOP/bin,必須登入主機(如:linux、solaris)才能使用

3、可以另外開一個新的目錄,進入目錄後再執行FNDCPASS,就可以把產生的Log都放在該目錄內

4、更改Oracle帳號的密碼,例如更改PO模組的密碼(表格: fnd_oracle_userid)

   語法:FNDCPASS apps/[APPS密碼] 0 Y system/[SYSTEM密碼] ORACLE [模組帳號] [新密碼]

   rp7410: FNDCPASS apps/apps123 0 Y system/system123 ORACLE po po999

5、更改EBS帳號的密碼,例如更改使用者帳號UA015的密碼(表格:fnd_user)

   語法:FNDCPASS apps/[APPS密碼] 0 Y system/[SYSTEM密碼] USER [EBS帳號] [新密碼]

   rp7410: FNDCPASS apps/apps123 0 Y system/system123 USER ua015 123456

6、欲更改APPS的密碼,可以用下列的方法:
  
   語法:FNDCPASS apps/[APPS密碼] 0 Y system/[SYSTEM密碼] SYSTEM applsys [新密碼]

   rp7410: FNDCPASS apps/apps123 0 Y system/system123 SYSTEM applsys 123456
 
   大寫SYSTEM是識別字,不是指帳號system;修改applsys的密碼,會一併修改apps。

   接著修改$IAS_ORACLE_HOME/Apache/modplsql/cfg底下wdbsvr.app內的apps密碼
 
   rp7410: cd $IAS_ORACLE_HOME/Apache/modplsql/cfg
   rp7410: vi wdbsvr.app

   找到下列的內容,並將password由舊密碼改為新密碼

   [DAD_CLONE]
   connect_string  = CLONE
   password        = 123456  <--改為新密碼
   username        = APPS

利用PowerShell刪除Process

例如要殺掉開啟的記事本:get-process notepad | foreach-object {$_.kill()}

在foreach-object中,$_ 表示是目前的物件,kill() 表示刪除的函數
因為使用foreach-object,所以無論同時開啟多少個記事本(notepad),都可以全部殺掉。

Windows PowerShell如何執行、簡單說明

Windows PowerShell是微軟公司為Windows環境所開發的殼程式(shell)及腳本語言技術,
這項全新的技術提供了豐富的控制與自動化的系統管理能力。
PowerShell可以使用部份的UNIX指令,例如:ps、kill、ls,但是參數用法並不一樣。
(UNIX指令的部份,應該是用別名的方式,例如ps,實際的是get-process)

PowerShell Scripts 檔案,附檔名為 .ps1。(數字的1)
PowerShell與一般直譯式語言一樣,直接以文字檔編輯,也不用編譯。

如果想要執行.ps1 的檔案,必須在PowerShell的介面下或直接以powershell指令執行
1、在PowerShell介面下
   在CMD底下或「開始」-->「執行」,輸入powershell,會出現下列的提示(前面會有PS的識別字)
   PS C:\>
   再將Script檔案以./執行,如
   PS C:\> ./test.ps1
   或是以完整路徑+Script檔案來執行,如
   PS C:\> d:\test.ps1
 
2、以powershell指令來執行
   在CMD底下或「開始」-->「執行」,輸入powershell + script檔案,例如:
   C:\> powershell "D:\test.ps1"  或是 C:\> powershell -command "D:\test.ps1"
   註:如果資料夾名稱有「空白字元」,則必須以「單引號」來區別。例如:D:\'test ps'\test01.ps1
 
如何查詢所有指令:
PS C:\> get-command

如何查詢指令用法,例如要查詢get-process:
PS C:\> get-help get-process  或是 PS C:\> help get-process 或是 PS C:\> get-process -?
(說明的文件是中文的,而且也有範例可以查詢)

線上查詢所有的 Windows PowerShell 指令和說明文件,可使用「*」萬用字元或是「?」單一字元。例如:
get-help *:列出所有的主題,包括指令和概念。
get-help * | more:列出所有的主題,包括指令和概念,more表示當資料已顯示整個視窗就暫停。
get-help about*:列出所有的概念主題。
get-help about_???:列出所有about_後面最多三個字元的概念主題,如about_do、about_for
get-help get*:列出所有 get 開頭的主題。
get-help {<指令名稱或主題名稱>}:列出指定的指令或主題的說明,例如 get-help dir  

教學網址:
http://www.pstips.net/
http://technet.microsoft.com/zh-tw/scriptcenter/dd742419.aspx

Windows Powershell XXXX.ps1 檔案無法載入

Powershell XXXX.ps1 檔案無法載入,因為這個系統上已停用指令碼執行。
如需詳細資訊,請參閱 "get-help about_singing";

原來是系統預設是不允語任何指令碼執行,所以第一次使用要去更改安全性的設定值。

1、先開啟PowerShell

   C:\> powershell
  
   PS C:\>
  
2、執行Set-ExecutionPolicy RemoteSigned,出現訊息之後,因為預設值為"Y",直接按下Enter即可。
  
   PS C:\> Set-ExecutionPolicy RemoteSigned
   執行原則變更
   執行原則有助於防範您不信任的指令碼。如果變更執行原則,可能會使您接觸到 about_Execution_Policies
   說明主題中所述的安全性風險。您要變更執行原則嗎?
   [Y] 是(Y)  [N] 否(N)  [S] 暫停(S)  [?] 說明 (預設值為 "Y"):

Set-ExecutionPolicy參數值說明:
  • Restricted:預設值,不允許執行 ( 安全性最高 )。
  • RemoteSigned :在本機電腦所撰寫的腳本檔,不需要簽署就可執行;從網際網路下載的腳本檔必須經受信任發行者的簽署才能執行 ( 有限的安全性 )。
  • AllSigned :只允許受信任發行者簽署過的指令檔 ( 較安全,建議使用 )。
  • Unrestricted :任何腳本檔皆可被執行,但是網際網路下載的腳本,會先出現警告的提示視窗 ( 不安全 )。

在Windows下,利用tasklist與taskkill來刪除Process

Windows7 / Windows8 kill process

Linux下要刪除某個程序通常會使用 ps 配合 kill 來刪除程序。
例如:ps -ef |grep [PROCESS NAME]
      kill -9 [PID]

在Windows下,通常是開啟工作管理員來強制結束應用程式,但是如果要寫成Script,就必須改為命令式。

TASKLIST [/S system [/U username [/P [password]]]]
         [/M [module] | /SVC | /V] [/FI filter] [/FO format] [/NH]
         
TASKKILL [/S system [/U username [/P [password]]]]
         { [/FI filter] [/PID processid | /IM imagename] } [/T] [/F]
         
(Tasklist:查詢Process ; Taskkill:刪除Process)

         
例如要刪除已開啟的記事本(notepad):

1、查詢記事本的Process訊息
    C:\> tasklist |find /i "notepad.exe"
    notepad.exe      6092 Console     1     5,832 K

2、由上得知記事本的PID為6092
    C:\> taskkill /f /PID 6092
    成功:處理程序 PID 6092 已經終止了。

    taskkill使用的參數
    /f:指定此參數可強制終止處理程序
    /PID:指定要終止之處理程序的 PID
    
3、也可以直接以程式名稱刪除
    C:\ taskkill /f /im notepad.exe
    成功:處理程序 "notepad.exe" <PID 6092> 已經終止了
    

下面是我自己測試的Script,可以刪除多個相同的程式,例如同時開啟了三個記事本:
@echo off

for /f "tokens=2 delims= " %%c in ('tasklist /FI "imagename eq notepad.exe" /FO table /NH') do (
    echo %%c
     taskkill /F /PID %%c
)

其中for後面的/f,表示要將傳來的字串進行解析。
'tasklist /FI "imagename eq notepad.exe" /FO table /NH'是指篩選出程序名稱為notepad.exe的資料,
並且指定以table的格式來顯示在螢幕上,而/NH是指不要列印出欄位名稱(必須撘配/FO的格式為table或csv)

"tokens=2 delims= "指的是以空白(delims=[空白])來分割整個字串,並取得第2個欄位(PID)的值,
篩選出來值被會放入虛擬變數%%C中,再以taskkill來刪除%%c中的PID值,就完成了。

/FI 後面接著是篩選的條件,"imagename eq notepad.exe" 是指IMAGENAME等於notepad.exe

更多用法可參考:
tasklist /?
taskkill /?

REP-1216 : xxx has an illegal print condition

開發Report時,測試時出現錯誤 REP-1216 : xxx has an illegal print condition

包圍的框架拉大一
選擇正確的群組,然後確認Base Print On 是選擇 Anchoring Object



1坪的大小

1坪大約等於兩塊榻榻米
一塊榻榻米=3台尺x6台尺(約90x180公分)
1台尺=10台寸,1台寸=3.03公分,1台尺=30.3公分
所以一坪=3.305 平方公尺 或 1平方公尺=0.3025坪

像我家地板是用拋光石英磚,所以也可以用磚塊數來「粗估」。
1才=1台尺x1台尺,而1台尺約30公分,所以石英磚換算如下:
60x60公分磚:約有4才(60x60)/(30x30)=4才
80x80公分磚:約有7.1才(80x80/(30x30)=7.1才
1坪大約是9塊60x60石英磚;5塊80x80石英磚

其他土地單位換算:
1公頃 = 10000平方公尺 = 3025坪 = 1.03102甲
1甲 = 10分 = 2934坪 = 0.96992公頃
1平方公里 = 100公頃

MK808B Driver(更新到Win8)

我家沒有裝設第四台,今年初買了MK808B用HDMI連接電視,再下載PPS、風行網等來觀看。
再加上目前還不用月租費的MOD(基本台數),一個月少花好幾百元。
不過最近遇到MK808B無法開機,重開好幾次情況未能改善,上網查詢得知也許是ROM有問題。
於是開始找ROM來刷機,網上分享了不少很棒的刷機文章,步驟也很簡單,最後自己也刷機成功。
但是因為筆電是Win8 x64,為了Driver費了不少的時間,所以把自己抓到的Driver分享。

MK808B Driver支援的作業系統如下:
x86:WinXP、Win2000、Vista、Win7、Win8
x64:Vista、Win7、Win8

按此下載    或複製下列的網址:
https://mega.co.nz/#!oRcFRbpD!GQKJjw69tekezuwuGQgir14hxcdB1QiGRJkEZkE3afA


刷機教學,我自己是參考這篇:
http://www.mobile01.com/topicdetail.php?f=586&t=3557442

我自己是到這裡下載ROM,不過網路上還有分享其他的ROM,有時間再測試。
http://www.freaktab.com/showthread.php?3857-NEW-MK808-quot-all-models-quot-Finless-1-7

最近把Win8更新到Win8.1,沒想到Driver就裝不上去了,試了幾種方法也無效,看來只能再等等了。

正展BOM

--Bom API會將結果放進BOM_SMALL_EXPL_TEMP,料號就找component_item_id,用量就找component_quantity
--上一階(父階)就找 assembly_item_id

declare 
    cursor cur1 is 
        select inventory_item_id,segment1 from mtl_system_items_b where segment1 =<ITEM>
            and inventory_item_status_code='Active'
            and item_type=<ITEM_TYPE>
and organization_id= <ORGANIZATION_ID> ;
        
    r1 cur1%rowtype;
    
    v_Group_Id number;
    v_Error_Message varchar2(1000);
    v_Error_Code varchar2(1000);

begin  
     delete from BOM_SMALL_EXPL_TEMP;

  open cur1;
  LOOP
    FETCH cur1 INTO r1;
    EXIT WHEN cur1%NOTFOUND;
        BEGIN        
            --取下一個Group_id
            Select Bom_Explosion_Temp_S.NextVal into v_Group_Id From dual;

            Bompxinq.Exploder_Userexit(
                Verify_Flag => 0,
                Org_Id => <ORGANIZATION_ID>,
                Order_By => 1,
                Grp_Id => v_Group_Id,
                Session_Id => 0,
                Levels_To_Explode => 15,
                Bom_Or_Eng => 1, --Bom_Or_Eng
                Impl_Flag => 1,
                Plan_Factor_Flag => 2,
                Explode_Option => 3, -- :B_Bill_Of_Matls.Bom_Inquiry_Display_Type
                Module => 2, --:B_Bill_Of_Matls.Costs,
                Cst_Type_Id => 0, --:B_Bill_Of_Matls.Cost_Type_Id,
                Std_Comp_Flag => 2,
                Expl_Qty => 1, --:B_Bill_Of_Matls.Explosion_Quantity,
                Item_Id => r1.inventory_item_id, -- :B_Bill_Of_Matls.Assembly_Item_Id,
                Alt_Desg => null, --:B_Bill_Of_Matls.Alternate_Bom_Designator,
                Comp_Code => null,
                Unit_Number_From => null, --NVL(:B_Bill_Of_Matls.Unit_Number_From, :CONTEXT.UNIT_NUMBER_FROM),
                Unit_Number_To => null, --NVL(:B_Bill_Of_Matls.Unit_Number_To, :CONTEXT.UNIT_NUMBER_TO), 
                Rev_Date => sysdate, -- :B_Bill_Of_Matls.Disp_Date,
                Show_Rev => 1,  -- yes
                Material_Ctrl => 2, -- :B_Bill_Of_Matls.Material_Control,
                Lead_Time => 2, --:B_Bill_Of_Matls.Lead_Time,
                Err_Msg => v_Error_Message,
                Error_Code => v_Error_Code);
        END;        
      END LOOP;
  CLOSE cur1;

逆展BOM

以下是修改過的逆展,只抓最頂層的料號,會將結果寫入tmp_ccc
Declare

   v_comp number:= 0;

   cursor cur_1 is
       select inventory_item_id
           from mtl_system_items_b
           where organization_id = <ORGANIZATION_ID>
           and segment1 = <ITEM>

    r1 cur_1%rowtype;

   Procedure Get_top_item (component_item_id number ) is

      Cursor Cur_bom is
          select bom.ASSEMBLY_ITEM_ID ,
                 msib.segment1 item_number
              from bom_components_b bcb,
                   bom_bill_of_materials bom,
                   mtl_system_items_b msib
              where bcb.bill_sequence_id = bom .BILL_SEQUENCE_ID
                 and bom.ORGANIZATION_ID = <ORGANIZATION_ID>
                 and bcb.component_item_id = component_item_id
                 and bcb.disable_date is null
                 and bom.ORGANIZATION_ID = msib .organization_id
                 and bom.ASSEMBLY_ITEM_ID = msib .inventory_item_id
                 and bcb.component_quantity > 0 ;

   Begin

      For c_bom in Cur_bom Loop
          select count(* ) into v_comp
     from bom_components_b bcb,
                   bom_bill_of_materials bom
              where bcb.bill_sequence_id = bom .BILL_SEQUENCE_ID
                   and bom.ORGANIZATION_ID = <ORGANIZATION_ID>
                   and bcb.disable_date is null
                   and bcb.component_quantity > 0
                   and bcb.component_item_id = c_bom .ASSEMBLY_ITEM_ID ;

            If v_comp > 0 then
                Get_top_item (c_bom. ASSEMBLY_ITEM_ID);
            else
                 --dbms_output.put_line('Top Item:' ||c_bom .item_number);              
                 insert into tmp_ccc (a) values ( c_bom.item_number ) ;
            end if;

      End Loop;

   End;
 
Begin
    for r1 in cur_1 loop
       Get_top_item (r1.inventory_item_id );--Component Item Id
    end loop;
End;


-----------------------------------------------------------------------------------------------------------

--逆展BOM,可以自訂階層。

declare
      IN_ORGANIZATION_ID     NUMBER ;
      IN_ITEM_ID                    NUMBER ;
      ln_SEQUENCE_ID   number;
      char_date      varchar2(30);
      err_msg   varchar2(200);
      err_code varchar2(200);
   
   begin
 
       in_organization_id:=84;
       select inventory_item_id into in_item_id
               from mtl_system_items_b where organization_id=84 and segment1= <ITEM> ;

       delete BOM_SMALL_IMPL_TEMP;  --刪除TEMP資料

       select bom_implosion_temp_s.nextval -- 取 SEQUENCE
           into ln_SEQUENCE_ID
       from dual;

      -- 執行日期
      SELECT to_char(sysdate, 'YYYY/MM/DD HH24:MI')
        INTO char_date
        FROM dual;

      -- 逆展API
      BOMPIINQ.IMPLODER_USEREXIT (
                  sequence_id => ln_SEQUENCE_ID,
                  eng_mfg_flag => 1,              -- BOM
                  org_id => IN_ORGANIZATION_ID,
                  impl_flag => 1,                 --IMPLEMENTED_ONLY,
                  display_option => 1,            --All
                  levels_to_implode => 1,         --Level
                  item_id => IN_ITEM_ID,
                  impl_date => X_char_date,
                  unit_number_from => null,
                  unit_number_to => null,
                  err_msg => err_msg,
                  err_code => err_code,
                  organization_option => 1,
                  organization_hierarchy => null,
                  serial_number_from => null,
                  serial_number_to => null
                  );
   end;

--執行OK就可以應用BOM_SMALL_IMPL_TEMP的資料了。上一階ITEM抓parent_item_id,目前的ITEM抓CURRENT_ITEM_ID

Concurrent Request無法取消執行

當Cancel Request時,出現下列的錯誤訊息:
Request xxxxxx can no longer be cancelled. The Concurrent Manager Process that was running this request has exited abnormally. The ICM will mark this request as completed with error.


在網路上找到解決的方式如下:
Manually cancel the request out of the queue with the following SQL against the offending
request id(s). This can be safely done while managers are up and running

UPDATE fnd_concurrent_requests
        SET phase_code = 'C', status_code = 'X'
         WHERE request_id = 10975869;

回到EBS,可以發現它已經Cancel了

將EBS的DB改以SPFILE啟動

我們的ERP DB是以pfile來啟動,顧問建議可以改為spfile來啟動,
因為DB的Script是addbctl.sh,所以查詢內容找到了更改的地方:

路徑:
$ORACLE_HOME/appsutil/scripts/<sid>_<hostname>/adstrtdb.sql

例如:
cd $ORACLE_HOME/appsutil/scripts/TEST_rp7410
cp adstrtdb.sql adstrtdb.sql.bk
vi adstrtdb.sql

內容只要找到starup這個關鍵字,把startup之後的字串刪除,DB時就會以spfile啟動

(略)…
REM connect / as sysdba;
spool /erptest/clonedb/9.2.0/appsutil/log/test_rp7410/addbctl_CLONE.txt
define USER="&1"
connect &USER;

startup pfile=/erptest/testdb/9.2.0/dbs/initTEST.ora

exit
(略)…

用DBMS_METADATA.GET_DDL取得表格的DDL

雖然我都是用Toad、SQL Developer等工具來取得DDL,但是可能偶而會遇到沒有工具的時候。
所以找了一下不用工具而取得DDL的方法。

語法如下,會傳回Clob型態的值
DBMS_METADATA.GET_DDL (
object_type     IN VARCHAR2,
name            IN VARCHAR2,
schema          IN VARCHAR2 DEFAULT NULL,
version         IN VARCHAR2 DEFAULT 'COMPATIBLE',
model           IN VARCHAR2 DEFAULT 'ORACLE',
transform       IN VARCHAR2 DEFAULT 'DDL')
RETURN CLOB;

範例如下:

單一Table的DDL
set heading off;
set echo off;
Set pages 999;
set long 90000;
spool c:\ddl.txt
select dbms_metadata.get_ddl('TABLE','TMP_CCC','TEST_USER') from dual;
spool off;

取出當前使用者的整個Schmea的Table DDL
set pagesize 0
set long 90000
set feedback off
set echo off 
spool c:\schema.sql
SELECT DBMS_METADATA.GET_DDL('TABLE',u.table_name)
      FROM USER_TABLES u;
spool off;

取出所有的Tablespace的DDL
SELECT DBMS_METADATA.GET_DDL('TABLESPACE', TS.tablespace_name)
        FROM DBA_TABLESPACES TS;

用指令find查詢時排除特定目錄(資料夾)

只排除一個目錄:
find /dir1  -path "/dir1/aa"  -prune -o  -name "test*" -print

排除多個目錄:
find /dir1  -path "/dir1/aa" -prune -o -path "/dir1/bb" -prune -o  -name "test*" -print

如果是要排除目錄時,目錄名稱後面不能加上「/」;但是如果是排除檔案時,就沒有關係。
例如:-path "/dir1/aa/"  -prune -o  -->因為aa是一個目錄,所以會無法排除


-o 表示OR,所以必須在每個表達式之間加入,與程式語言的OR觀念一樣,說明如下:
expression -o expression:Logical OR operator.  True if either or both of the expressions are true.

EBS 11i 依不同的使用者設定不同背景顏色

同事問我EBS 11i是否可以依不同的使用者設定不同背景顏色,測試的結果是可行的,
但是這樣的做法可是會引起爭議,所以最後當然是不淮啦!

System Administrator --> Profile --> System
User輸入使用者帳號,Profile輸入「Java Color Scheme」,如下圖:


可針對不同的使用者來設定主題顏色


以帳號sysadmin登入,使用的是系統設定值「red」


以剛剛設定的帳號ORACLE登入,可以發現使用的是「blue」



Linux把檔案名稱改為大寫的Script

剛好因為把Windows的某些檔案上傳到Linux,但是Linux是有區分大小寫,
所以寫了一個簡單的Scripts來將目錄tmpfile內檔案一徑改為大寫。

#!/bin/bash
for oldname in `ls`
do
  for newname in `ls $oldname|tr '[a-z]' '[A-Z]'`
  do
    mv $oldname $newname
  done
done

如果要改為小寫,則改為 tr '[A-Z]' '[a-z]'
如果只想把檔案名稱有a、c的改為大寫,則改為tr '[a,c]' '[A,C]'
如果想把檔案名稱有a改為T,c改為H,則改為 tr '[a,c]' '[T,H]'

自動備份alert.log及刪除dump file的scripts

因為DB alert.log資料太多,以致閱讀及查詢上較為不便,顧問也建議如此做法,
所以設計了一個Script,可以設定排程來定時備份alert.log,且清空alert.log的內容,
這樣每次查詢時就不會有那麼多的資料。順便也將14天前DB Dump出來Trace file也一併清除。
系統是HP-UX,程式如下:

#!/bin/sh
v_date=`date '+%Y%m%d'`
v_filename="_alert_prod.log"
cp  /erp/erpdb/9.2.0/admin/prod_rp7420/bdump/alert_PROD.log /erp/erpdb/9.2.0/admin/prod_rp7420/bdump/$v_date$v_filename
find /erp/erpdb/9.2.0/admin/prod_rp7420/bdump -mtime +7 -name "prod_*.trc" -exec rm {} \;
find /erp/erpdb/9.2.0/admin/prod_rp7420/udump -mtime +7 -name "prod_*.trc" -exec rm {} \;
cat /dev/null > /erp/erpdb/9.2.0/admin/prod_rp7420/bdump/alert_prod.log

EBS Concurrent Request列印時產生的檔案

原因:$COMMON_TOP的剩餘空間越來越少,已經定期刪除Concurrent Request產生的log、output file
原來Request在有指定印表機列印的情形下,會產生列印的檔案。



由「View Log...」可以知道路徑及產生的檔案名稱,而且因為有字集的轉換,所以會有兩個檔案。
 

從$COMMON_TOP/temp來找,果然有這樣的檔案,而且不會自動刪除(不知道有沒有自動刪除的設定)

所以在HP-UX下寫一個Scripts來定期刪除這些檔案。

#!/bin/sh
find $COMMON_TOP/temp  -mtime +14 -name "OF*.t" -exec rm {} \;
find $COMMON_TOP/temp  -mtime +14 -name "OF*.t.zht" -exec rm {} \;

不過最後我是用絕對路徑,而不是變數$COMMON_TOP。
因為上次有一個Scripts也是利用$APPLCSF/$APPLLOG來找到路徑,
但是不小心登入到root帳號,而root並沒有該變數,以致於變數為空值,
加上有一個「/」,所以就變成根目錄,幸好刪除時有指定副檔名,
才有機會從測試機複製相同的檔案,所以要使用變數時,一定要對該變數進行判斷。



dba_jobs_running查詢速度很慢

網路找的答案是Oracle 9i的Bug,可以用hint來試著解決:
select /*+ rule */ * from dba_jobs_running;

<Bug:2624130> 
QUERY AGAINST DBA_JOBS_RUNNING IS USING CBO EVEN WHEN NO STATISITICS.

刪除一個執行很久的JOB

先以下列的SQL找出正在running的job,並確認要刪除的job及sid。
select /*+ rule */ * from dba_jobs_running;

假設找到的 job=1640,sid=32

查job的內容
select * from dba_jobs where job=1640;

將job的broken改為Y
exec dbms_job.broken(1640,true);

找出執行job session的sid、serial#、OS process id
select vs.sid,vs.serial#,vp.spid,vs.*,vp.* from v$session vs,v$process vp
    where vp.addr=vs.paddr and vs.sid=32 ;
    
假設找到的是 serial#=7,spid=9642

刪除session
alter system kill session '31,7';

如果 kill 的時間很久,也可以直接由OS刪除,如我的系統是UNIX:
kill -9 9642


將job的broken恢復成N
exec dbms_job.broken(1640,false);

HTML特殊字符

因為某些字會與HTML語法相衝突,所以必須以特別的方式來區分兩者之間的差異,
例如大於與小於符號,在HTML語法中為Tag的識別符號。

符號 說明 字符
  半形的空白 &ensp;
  全形的空白 &emsp;
  空白(不斷行) &nbsp;
< 小於 &lt;
> 大於 &gt;
&   &amp;
" 雙引號 &quot;
© 版權符號 &copy;
® 注冊商標符號 &reg;
× 相乘 &times;
÷ 相除 &divide;

取消Google Blogger自動識別HTML語法

有時候文意內容會提到HTML標籤的用法,但是google blogger會自動轉為HTML語法,
以致文章內容產生錯誤。一直以來都是直接用「&lt;」及「&gt;」的特殊字符來解決,
沒想到google早已替我們想好,只要更改設定值就可以了。

例如有一個內容是「網頁是以<html>開始,結束</html>」,發佈之後如下:

點選右方的「選項」-->「按照字面顯示HTML」

不用特殊字符就可以完整顯示



Android--XML的讀取,使用XmlPullParser

=================================
test.xml
=================================

<? xml version= "1.0" encoding= "utf-8" ?>
    <channel >
        <title >旅遊 </title >
        <description >(...略) </description >
        <language >zh-Hant-TW </language >
        <pubDate >Sun, 06 Jan 2013 </pubDate >
        <ttl >5 </ttl >
        <item >
            <title >台南美食吃不完 </title >
               <pubDate >Sun, 06 Jan 2013 </pubDate >
                <description >(...略) </description >
        </item >
    </channel >



====================================
activity_main.xml
====================================
< RelativeLayout xmlns:android ="http://schemas.android.com/apk/res/android"
    xmlns:tools= "http://schemas.android.com/tools"
    android:id= "@+id/RelativeLayout1"
    android:layout_width= "match_parent"
    android:layout_height= "match_parent"
    android:paddingBottom= "@dimen/activity_vertical_margin"
    android:paddingLeft= "@dimen/activity_horizontal_margin"
    android:paddingRight= "@dimen/activity_horizontal_margin"
    android:paddingTop= "@dimen/activity_vertical_margin"
    tools:context= ".MainActivity" >

    <FrameLayout
        android:id= "@+id/frameLayout1"
        android:layout_width= "wrap_content"
        android:layout_height= "wrap_content"
        android:layout_alignParentLeft ="true"
        android:layout_alignParentTop ="true" >

        <TextView
            android:id= "@+id/textView1"
            android:layout_width= "wrap_content"
            android:layout_height= "wrap_content"
            android:text ="TextView1" />

    </FrameLayout >

    <FrameLayout
        android:layout_width= "wrap_content"
        android:layout_height= "wrap_content"
        android:layout_alignParentRight ="true"
        android:layout_alignTop= "@+id/frameLayout1"
        android:layout_marginRight= "123dp" >

        <TextView
            android:id= "@+id/textView2"
            android:layout_width= "wrap_content"
            android:layout_height= "wrap_content"
            android:text ="TextView2" />

    </FrameLayout >

</ RelativeLayout>



===================================
MainActivity.java
===================================
package com.example.test_app06;

import java.io.IOException;
import java.io.InputStream;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.os.Bundle;
import android.app.Activity;
import android.content.res.AssetManager;
import android.util.Xml;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          TextView tv01 = (TextView)findViewById(R.id.textView1);
          TextView tv02 = (TextView)findViewById(R.id.textView2);
          int i= 0;
          XmlPullParser pullParser = Xml.newPullParser();
          //因為將test.xml放在/assets之下,所以必須以讀取檔案的方式來處理
          AssetManager assetManager = getAssets();
          InputStream is;
          try
          {
              is = assetManager.open("test.xml"); //讀取檔案
              pullParser.setInput(is , "utf-8");  //設定語系
              //利用eventType來判斷目前分析到XML是哪一個部份
              int eventType = pullParser.getEventType();
              //XmlPullParser.END_DOCUMENT表示已經完成分析XML
              while(eventType != XmlPullParser.END_DOCUMENT)
              {
                  i++;
                  //XmlPullParser.START_TAG表示目前分析到的是XML的Tag,如<title>
                  if (eventType == XmlPullParser.START_TAG) {
                    String name = pullParser.getName();
                    tv01.setText(tv01.getText() + ", " + name);
                  }
                  //XmlPullParser.TEXT表示目前分析到的是XML Tag的值,如:台南美食吃不完
                  if (eventType==XmlPullParser.TEXT) {
                       String value = pullParser.getText();
                      tv02.setText(tv02.getText() + ", " + value);
                  }
                  //分析下一個XML Tag
                  eventType = pullParser.next();
              }
          } catch (IOException e) {
               tv02.setText(e.toString());
          } catch (XmlPullParserException e) {
               tv02.setText(e.toString());
          }
     }

     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
          // Inflate the menu; this adds items to the action bar if it is present.
          getMenuInflater().inflate(R.menu.main, menu);
          return true;
     }

}

Temporary Tablespace的實際用量與OEM顯示不同

在Oracle Enterprise Manager中顯示Temporary Tablespace已經滿了,
的確在前一段日子,因為一支客製SQL的緣故而導致Temporary使用率100%,
ERP的作業也就受到了影響,alter log也記錄了ora的錯誤。
但是當時強制將SQL停掉後,ERP也就恢復了正常,但是100%卻再也沒有下降過。
之前的作法先加大Temporary的空間,然後在星期日停機的時候重建Temporary,
但是這次我用下列的SQL執行的結果實際使用率只有10%,並未達到100%。
過一段時間,alter log也未記錄到ora的錯誤,使用上也沒有出現異常。
而詢問顧問的結果是因為Oracle 9i在HP-UX上可能存有bug,以致如此。
所以我現在都是以下列的SQL直接觀察。

select a.tablespace,"實際用量(MB)","總空間(MB)",("實際用量(MB)"/"總空間(MB)"*100) "實際使用率"
    from (SELECT TABLESPACE,SUM(BLOCKS)*8/1024 "實際用量(MB)" FROM V$TEMPSEG_USAGE group by tablespace) a,
            (SELECT   tablespace_name,
                           (SUM (bytes_used)+SUM (bytes_free))/1024/1024 "總空間(MB)"                                      
                FROM v$temp_space_header
                GROUP BY tablespace_name) b
    where a.tablespace=b.tablespace_name ;


查某個Item有無在BOM結構中

select msi.segment1 "Item",msi.description "Description" ,decode(count(1) ,0,'N','Y')
from BOM_BILL_OF_MATERIALS bom,
          BOM_INVENTORY_COMPONENTS bic,
          mtl_system_items_b msi
where bom.ASSEMBLY_ITEM_ID = msi.inventory_item_id
  and msi.organization_id=85
  and msi.segment1= 'T01-035'
  and bom.ALTERNATE_BOM_DESIGNATOR is null
  and bom.BILL_SEQUENCE_ID = bic.BILL_SEQUENCE_ID
  and bom.ORGANIZATION_ID = 85
  and bic.DISABLE_DATE is null
  and bic.IMPLEMENTATION_DATE is not null
group by msi.segment1,msi.description;

Excel 2010 XML對應、編輯、使用

Excel 2007之後支援XML的編輯,剛好同事有需求要讓使用者用Excel編輯,
但是要轉出XML,讓其他的程式可以直接以XML匯入資料。

XML的格式希望如下,先儲存為dept.xml:

開啟Excel,點選「開發人員」-->「來源」

如沒有看到「開發人員」,則先選擇「檔案」-->「選項」,
將「開發人員」的欄位打勾,就會顯示在工具列上了。如下圖:

活頁簿的右邊就會出現「XML來源」,選擇「XML對應」會彈出視窗,再選擇「新增」,選擇dept.xml


「XML來源」會自動對應XML每個TAG,如下圖(dept.xml)的範例,
對應成功後,將TAG拉到活頁簿的儲存格,我把「header1」拉到儲存格B2;
把整個「user」群組拉到儲存格A1,Excel會自動把「user」群組底下的欄位自動填上。

這裡有一點要注意的是「header1」,由dept.xml可以知道,「header1」是一個單獨的部門名稱,
不在「user」群組裡面,所以不能直接將「dept」群組直接拉到活頁簿,如下圖。
這樣的格式會導致在另存為XML時,因為與原始的XML格式違背,也就是「header1」會有重複的情形。


因為英文的欄位名稱不易辨識,所以將欄位名稱改為中文,因為儲存格的XML對應不是以名稱來辨別,
所以更改名稱不會影響本身的對應,轉出XML也會以XML TAG來儲存。
接著將它存成副檔名.xlsx,再交使用者編輯即可。


資料輸入完成後,要轉出XML檔案,只要在另存新檔時,選擇「.xml」格式儲存就可以了。