2012年10月25日

比對二個 Table 的資料, 並進行資料更新

系統做資料同步,新的資料就用 Insert ,原本的資料就用 Update 指令,
當然也可以全部資料 delete 掉再全部重新 Insert 進去,
從 Oracle 10g 的版本開始就提供了一個 Marge 的指令,可以解決很多資料比對上的問題。
Merge 指令的缺點就是,只能二個 Table 進行資料異動。
優點是使用 Update 更新時要注意找不到資料會更新為 Null 的情況,用 Merge 可以避免。

例如:TableA 要依據 TableB 的欄位更新過來,一般都會寫:
            update TableA set (ColumnA2,ColumnA3) =
             (select ColumnB2,ColumnB3 from TableB where ColumnB1 = ColumnA1)
            但是如果要再增加判斷 TableB 的 ColumnB2 不是空的才更新,這樣要改成:
            update TableA set (ColumnA2,ColumnA3) =
             (select nvl(ColumnB2,ColumnA1),ColumnB3 from TableB where ColumnB1 = ColumnA1)

有了 Merge 的指令就可以比較有直覺的 SQL 語法了。
merge into TableA a  a using TableB b  on (a.ColumnA1= b.ColumnB1)
when matched then
   update set a.ColumnA2= b.ColumnB2, a.ColumnA3 = b.ColumnB3 where b.ColumnB2 is not null
when not matched then
   insert (ColumnA1,ColumnA2,ColumnA3) values (ColumnB1,ColumnB2,ColumnB3)

Marge 指令要如何變化不彷就研究試試看吧~~

2012年10月8日

將 CONSTRUCT 所輸入的欄位拆開來

通常報表要判斷多個欄位的時候,
都是用 CONSTRUCT BY NAME tm.wc ON 欄位1,欄位2,欄位3…
有時候欄位1要另外判斷,欄位2又要另外判斷的時候怎麼辦,
這樣 tm.wc 已經組好 SQL 的語法,總不能用字串去拆吧,可能會有錯誤的情況。
當然你也可以分寫開三次 CONSTRUCT ,只是使用者要按三次確定才行。

山不轉路轉,就變化一下吧~~
這時候 GET_FLDBUF 的指令就可以派上用場了。
只是抓出來的卻是使用者輸入查詢的字串,SQL 根本不能拿來用。

只在原本的 CONSTRUCT 加上:
  AFTER CONSTRUCT
          LET tm.wc1 = GET_FLDBUF(imd01)
          LET tm.wc2 = GET_FLDBUF(sfa01)
          LET tm.wc3 = GET_FLDBUF(sfa03)

再來就是增加三個 CONSTRUCT,這樣就分別對應到 tm.wc1, tm.wc2, tm.wc3 。
之後的 SQL 就只要抓 wc1,wc2,wc3 的值就好了。

      CONSTRUCT BY NAME tm.wc1 ON imd01
         BEFORE CONSTRUCT
            DISPLAY tm.wc1 TO FORMONLY.imd01
            EXIT CONSTRUCT
      END CONSTRUCT
     
      CONSTRUCT BY NAME tm.wc2 ON sfa01
         BEFORE CONSTRUCT
            DISPLAY tm.wc2 TO FORMONLY.sfa01
            EXIT CONSTRUCT
      END CONSTRUCT

      CONSTRUCT BY NAME tm.wc3 ON sfa03
         BEFORE CONSTRUCT
            DISPLAY tm.wc3 TO FORMONLY.sfa03
            EXIT CONSTRUCT
      END CONSTRUCT

雖然是很白痴的用法,不過至少也是可以解決不少特殊報表的需求。

2012年9月17日

使用 COM 方式實現 Excel 資料匯入匯出的功能

對使用者來說,在 Excel 整理大量的資料還是比較方便又快速的,
傳統 TIPTOP 的匯入 Excel 資料的方式都是需要先轉為文字檔,
利用分隔符號來區分資料的欄位,但是這樣已是古代的作業方式了。

通常應用程式開發工具可以使用 COM 的方式是跟 Excel Application 進行通訊,
GDC 是 Clinet 端的軟體,所以可以使用 COM 的方式來讀取 Excel 的資料,
參考 4js 提供的 Genero 使用說明,找到 ui,interface.frontcall() 的使用方式。

建立 COM
1:CALL ui.interface.frontcall("WinCOM","CreateInstance",[program],[handle]
  A. program - 系統中註冊的 COM 名稱
  B. handle - 回傳狀態 -1 表示有錯誤,此值在 API 可以使用

使用指定的方法
2:CALL ui.interface.frontcall("WinCOM","CallMethod",[handle,method,arg1,...],[result])
  A.handle - 使用宣告的 handle 值。
  B. method - 函數的名稱。
  C. arg1 - 傳送給方法用的參數
  D. result - 回傳狀態 -1 表示有錯誤,0 表示沒有錯誤

讀取屬性值
3.CALL ui.interface.frontcall("WinCOM","GetProperty",[Handle,member],[result]
  A. handle - 使用宣告的 handle 值
  B. member - 取得屬性的
  C. result - 回傳狀態 -1 表示有錯誤,0 表示沒有錯誤

設定屬性值
4.CALL ui.interface.frontcall("WinCOM","SetProperty",[handle,member,value],[result]
  A. handle - 使用宣告的 handle 值
  B. member - 設定屬性的名稱
  C. value - 屬性的值。
  D. result - 回傳狀態 -1 表示有錯誤,0 表示沒有錯誤

錯誤訊息內容
5.CALL ui.interface.frontcall("WinCOM","GetError",[],[result]
  A. result - 錯誤的說明,如果沒有錯誤就為 Null

關閉 COM
6.CALL ui.interface.frontcall("WinCOM","ReleaseInstance",[handle],[result])
  A. handle - 使用宣告的 handle 值
  B. result - 回傳狀態 -1 表示有錯誤,0 表示沒有錯誤

以下就為 4GL 程式 Excel 資料匯入的範例:
DEFINE l_excelapp INTEGER,
               l_excelwb INTEGER,
               l_result INTEGER,
               l_str STRING,
               l_filename STRING,
               l_target STRING,
               l_range STRING

DEFINE l_i LIKE type_file.num5,
               l_j LIKE type_file.num5,
               l_column LIKE type_file.chr10
LET l_excelapp = -1
LET l_excelwb = -1

# 選擇檔案的位置和檔案名稱
LET l_filename = cl_browse_file()
# 建立 Excel Application 的 COM
CALL ui.interface.frontcall("WinCOM","CreateInstance",["Excel.Application"],[l_excelapp])
# 開啟所選擇的 Excel 檔案
CALL ui.interface.frontcall("WinCOM","CallMethod",[l_excelapp,"WorkBooks.Open",l_filename],[l_excelwb])
# 設定 Excel 要顯示
CALL ui.interface.frontcall("WinCOM","SetProperty",[l_excelapp,"Visible",true],[l_result])
# 讀取 Excel 的行數
CALL ui.interface.frontcall("WinCOM","GetProperty",[l_excelwb,'activesheet.UsedRange.Rows.Count'],[l_result])

FOR l_i=1 TO l_result
   LET l_column = l_i
   # 所要讀取的欄位,A 列第 n 行
   LET l_range = 'activesheet.Range("A',l_column,'").Value'
   # 讀取欄位的值
   CALL ui.interface.frontcall("WinCOM","GetProperty",[l_excelwb,l_range],[l_str])
   LET g_bmd[l_i].bmd01 = l_str
   # 所要讀取的欄位,B 列第 n 行
   LET l_range = 'activesheet.Range("B',l_column,'").Value'
   # 讀取欄位的值
   CALL ui.interface.frontcall("WinCOM","GetProperty",[l_excelwb,l_range],[l_str])
   LET g_bmd[l_i].bmd02 = l_str
END FOR

# 關閉 Excel 的 檔案和 COM
CALL ui.interface.frontcall("WinCOM","CallMethod",[l_excelapp,"WorkBooks.Close"],[l_excelwb])
CALL ui.interface.frontcall("WinCOM","ReleaseInstance",[l_excelapp],[l_result])

2012年8月21日

在畫面加上資料清單,從此不必再下一筆查了

用過 TIPTOP 的剛開始最不習慣的就是查詢資料都要下一筆、下一筆的查詢,
不但查詢耗時,而且要匯出 Excel 需要跑報表才可以列出清單,
讓使用者感覺操作不是那麼的流暢和便利。

可以在程式上面加上資料清單囉~~
而且調整的程式的部份不會很多,大約半小時就可以完成一支程式。

以動態料件數量明細查詢 aimq102 為例:


當在主畫面的時候匯出 Excel 可以匯出庫存明細,
在資料清單匯出 Excel 則匯出資料清單資料,且 Double Click 就會跳到主畫面。
在資料清單選擇料件時,下面的庫存明細也會跟著更新。

這樣是不是就方便許多,也不需要另外在做報表程式做明細資料的匯出。

修改程式步驟:
1. 修改畫面檔,增加新的頁籤,並指定 action ,記得 Main 也要加上 action。

2. 再來就是修改程式了,需要增加二個 Function。
    q102_list_fill() 在顯示資料清單用的。
    q102_bp1(p_ud) 在跳到資料清單時等待操作用的,才能停留畫面在資料清單。                                           
                          如果需要能夠在資料清單做過帳、確認的動作,也是加在此 Function。

3. 最後就是一些小調整,讓功能更完整啦,
   可以在主畫面查詢到第幾筆,資料清單也可以移動到那一筆。
   還有匯出 Excel 依畫面在主畫面還是資料清單來匯出到 Excel。
   需要修改 q102_menu()、q102_bp(p_ud)、q102_cs()、全域變數。

2012年4月10日

不用登出重新載入 .profile, 隨意切換正式或測試環境

常常會遇到一種情況,TIPTOP 要切換到測試環境或是正式環境時,
一般都是離開再重新登入;或是使用 su 再登入一次。
不過還是會有使用上的混亂和麻煩。

其實可以重新 load user profile 讓設定重新載入一次。
以下是範例畫面說明。

1. 如果登入時輸入 1,進入 topprod 的環境。

2. 重新載入 .profile 的檔案,使用 「點」「空格」「.profile 的位置」 就可以了,下圖為範例。

3. 出現為 toptest 代表已經切換成功囉~~ 直接執行 .profile 或是 sh .profile 都是沒有用的,因為子 shell  對當前的 shell 是沒有作用的。

2012年3月14日

SQL進行全文搜索,找出所有Table相關字的欄位出來

應該有很多人感到非常的不便就是找尋資料庫的所有 Table ,可能是在某個欄位的資料。
TIPTOP 標準不含 synonym 的話也有 3千多個 Table ,總不能一個一個去 SELECT 吧~
另外 5.X 版就開始有所謂的營運中心,也就是 Table 欄位會多了 PLANT、LEGAL 欄位,
也有許多非 PLANT、LEGAL 的欄位記錄著營運中心的資料。
所以複製到測試資料庫時,當測試資料進行"還原"時,會有可能造成還原到正式的資料庫。
EX:測試資料庫在 AP刪除時,會還原正式資料庫的 rvv20 欄位,變成未匹配。

遇到此狀況時測試資料庫就需要好好的"檢視"一番..........

以下是將資料庫進行全文的檢索 SQL 語法。

create table xxxx as select imk01,imk02,imk09 from imk_file where rownum = 0;   --先建一個暫存 xxx 的 Table 存放搜尋出來的值

declare
    str varchar2(1000);
    num number;
    begin
    for i in(select column_name,table_name from user_tab_cols where data_type in('CHAR','VARCHAR','VARCHAR2'))       -- 列出此 OWNER 的所有欄位出來
    loop
      str:='insert into xxxx select '''||i.table_name||''','''||i.column_name||''',count(*) from '||i.table_name||' where '||i.column_name||'='||'''DS1''';              -- 將查詢有DS1的欄位筆數寫入暫存 xxx Table
      execute immediate str ;                                   -- 轉換並執行
      commit;
   end loop;
   end;

接下來只要執行以下的查詢 SQL 指令,就可以知道有多少筆資料存在那些 Table 裡面了。
再進行整批的資料更新,將營運中心改為測試資料庫的營運中心。

select 'update '||imk01||' set '||imk02||'= ''DS1'';',imk09 from xxxx
where imk09 <> 0
order by imk09

隨著資料庫越來越大,當然要把資料量大的 Table 獨立出來更新,不然會造成資料庫 IO 滿載,系統會變很慢,以下是用迴圈的方式更新資料,減少資料大批量更新。

declare nums number;
begin
for i in(select distinct tlf01 from TLF_FILE)
loop
   update TLF_FILE set TLF20 = 'DS1' where TLF01 = i.tlf01;
commit;
end loop;
end;

這樣完全不會影響到正式資料庫的測試資料就完成囉~

2011年10月13日

讓 TIPTOP Web-GDC 也可以修改字型大小

有些人會認為 TIPTOP 的字怎麼這麼小(預設是9 pt),是可以讓 GDC 預設字型大小改為更大一點,只要在 gdc.exe 後面加上參數 –a即可,不過如果是 Web ActiveX GDC呢,就不能用參數去改了。
 
有找到如何可以改 GDC 參數的功能。
/u1/genero/gas/tpl/fglgdcdefault.html 檔,有以下的參數提供修改。

    function configureGDC() {
      //uncomment following line to enable Admin Mode
      gdc.setAdmin(true);          // 開啟 Option 功能 

      //uncomment following line to enable Debug Mode
      //gdc.setDebug(true);         // 開啟 Debug功能

      //uncomment and modify the following line if you want to change the ping timeout (120 sec by default)
      //gdc.setPingTimeOut(120);   // 開啟 ping time out 功能

       //uncomment and modify the following line if you want to change the proxy (using system settings by default)
      //gdc.setProxy("proxy:3128")  // 開啟 proxy 功能

      // this is to ensure that any popup window will appear in front of the browser
      gdc.setFocus();             // 設為視窗動作中
    }


存檔後重新開啟。
就可以修改文字大小囉~~

讓 Oracle 也可以連結 SQL Server 讀取資料

要如何讓Oracle也可以整合 MS SQL Server ? Oracle有提供一套工具,10g版本稱之為 Oracle Transparent Gateway,到了11g之後改名為 Oracle Database Gateway,如果有購買Oracle DB的話,官方是可以免費提供使用的,不需額外購買,主要是讓Oracle可以做 DB-Link 。提供了許多異質資料庫的整合,詳細可查閱 Oracle Database Gateway 文件說明檔。

Oracle 官方網站下載,然後安裝 Oracle Database Gateway,選擇你所需要連結的資料庫類型。

再來就是預設會幫你建立一個連結設定

然後直接安裝就可以了,要一段時間

再來就是修改二個重要的檔案,首先是在 oracle\product\11.2.0\ts_1\dg4msql\admin,會有一個initdg4msql.ora檔。
修改為
HS_FDS_CONNECT_INFO=127.0.0.1//ERP
HS_FDS_TRACE_LEVEL=OFF
HS_FDS_RECOVERY_ACCOUNT=RECOVER
HS_FDS_RECOVERY_PWD=RECOVER
然後再修改檔案名稱initdg4msql.ora改為自已喜歡的 initerp.ora
第二個檔案就是修改 oracle\product\11.2.0\tg_1\NETWORK\ADMIN\ 裡面的listener.ora檔。
直接在最下面加上
SID_LIST_LISTENER=
  (SID_LIST=
      (SID_DESC=
         (SID_NAME=erp)
         (ORACLE_HOME=D:\Oracle\product\11.2.0\tg_1)
         (PROGRAM=dg4msql)
      )
  )
 之後再重新啟動 LISTENER

lsnrctl stop (停止)
lsnrctl start (啟動)
這樣就完成了 Oracle Database Gateway 的安裝和設定了。
再來就是第二部份,Oracle主機的部份。
首先就是要先建立連線服務的名稱,修改Oracle主機 oracle\product\11.2.0\dbhome_1\network\admin tnsnames.ora檔。
在最底下增加
ERP  =
  (DESCRIPTION=
    (ADDRESS=(PROTOCOL=tcp)(HOST=127.0.0.1)(PORT=1521))
    (CONNECT_DATA=(SID=erp))
    (HS=OK)
  )
 最後就是建立DB-Link,在SQL PLUS下指令,我試sa帳號好像不能使用,不過還是建議建立一個帳號比較好。
CREATE PUBLIC DATABASE LINK ERP CONNECT TO user IDENTIFIED BY password USING 'erp';
測試看看吧~~
select * from table_name@erp;
有結果啦~~

需要注意 Oracle 的所有 Object 英文是不區分大小寫的,但是 SQL Server 是有大小寫之分,
當執行 SQL 指令時, Oracle 會自動轉換為大寫的方式來執行,
必需要加上雙引號 " 的方式才能夠找到正確的 Table 名稱。
select * from "table_name"@erp;

2011年5月17日

fglWrt - 查詢 Tiptop 線上使用人數和狀況

要如何查詢目前有誰在 TIPTOP 系統線上呢?
還有目前總共有多少人在用,
當上線人數已滿的話,要如何把沒有在使用的 User 踢掉呢?

我想這個是 Tiptop 系統維護人員有時會很頭大吧!

fglWrt 指令可以做到以上這幾個問題喔~~
以下是 fglWrt 的所有參數:

Usage  : fglWrt [options]
 -l [license]: Installs a license.
 -v|-V       : Shows version information.
 -u          : Checks active users.
 -k key      : Installation key for license validation.
 -d          : Deletes current license.
 -i          : Clears the list of registered user sessions.
 -a opt      : Check or view options, possible options are:
               ps           : Shows processes on this machine.
               env          : Shows current environment.
               cpu          : Shows number of CPU in the computer.
               hostname     : Shows name of this machine.
               info license : Shows license information.
               info stat    : Shows statitics of license server.
               info users   : Shows all registered active users.
               info up      : Shows if license server is up.

查詢目前的線上人數和使用者:
fglWrt -a info users

要踢掉沒有在使用的 User :
fglWrt -i  

注意:我是直接使用這個指令,把 session 全部清除,正在 key 單的人會跳開,
所以執行前需看有沒有人 lock table 才能執行。
只是清除 server 上 genero 的 session 數而已,
所以不會影響已登入的 User (不會斷線或關閉程式),
這時就通知比較好的 User 快搶 session 吧~~~

2011年5月11日

重新建立 TIPTOP 測試區的環境

相信小地方修改,或是日積月累的修改程式,或是變更 Database Schema 時,
正式區和測試區的 4GL 程式和 Database Schema 會有不一樣的情況,
這時要如何快速的把正式區完全的蓋到測試區呢?

首先,把正式區的程式整個目錄 copy 到測試區的目錄,
記得不能全部複製喔~~ 只能複被各模組、共用程式、副程式。

1. \cp -r /u1/topprod/tiptop/a* /u1/toptest/tiptop  (先前一定要加 \ 喔,不然會一直問要不要覆蓋)
2. \cp -r /u1/topprod/tiptop/lib /u1/toptest/tiptop
3. \cp -r /u1/topprod/tiptop/sub /u1/toptest/tiptop
4. \cp -r /u1/topprod/tiptop/qry /u1/toptest/tiptop
5. \cp -r /u1/topprod/tiptop/g* /u1/toptest/tiptop

再來就是把全部客製程式都 copy 過去。

6. \cp -r /u1/topprod/topcust/c* /u1/toptest/topcust

程式的部份,這樣就不需要再重新 rebuild 囉~~整個動作應該是不會超過 5 分鐘。

接下來就是資料庫的部份:

首先把所有的測試資料庫都刪除吧~~ (包含 ds)
在 sqlplus 下執行 drop user ds cascade

還原正式區的 ds 資料庫到測試區的 ds 資料庫。
1. 建立空的 ds 資料庫: createdb ds 1
2. 匯入正式區 ds 備份檔到測試區的 ds DB:
       imp system/manager@toptest fromuser=ds touser=ds ignore = y file=ds.dmp log=ds.log
3. 匯入公司的資料到測試區,步驟同 1~2 。
4. 要記得修改 /u1/genero.run/etc/fglprofile.test 喔~~
    通常 createdb 參數是 1 的話,fglprofile.xxxx 檔是不會修改的。
dbi.database.aaa.source= "toptest"
dbi.database.aaa.username= "aaa"
dbi.database.aaa.password= "aaa"
dbi.database.aaa.schema= "aaa"
dbi.database.aaa.ora.prefetch.rows = 1
5. 完成,記得重新登入 udm7 試試看吧~

如果不行的話,要修改 zx_file 的 zx08 欄位,看預設的營運中心是否和測試資料庫一致。

資料庫要看資料的大小而定,不過應該是1個小時內可以搞定吧~~~

TIPTOP 程式/ Oracle 資料庫備份-集中備份篇

還記得之前有一篇文章:TIPTOP 主機定期備份 Oracle 資料 & TIPTOP 程式, 備份篇 嗎?
相信應該足夠使用了吧,
但還是有不足的部份,需要將 TIPTOP 主機設定 cron job ,然後再 cr 主機再設定排程工作,
實在是不符合統一集中備份的方式。

其實只要安裝 Oracle Client ,就可以將 Oracle 資料 export 到遠端的電腦,
這樣就可以一個指令,就可以完整的將全部的資料都在遠端的電腦上執行囉~~

以下是備份 Oracle 資料的批次檔,先轉換 Database 的字集,會有警告訊息,但還是可以正常匯出資料。

set NLS_LANG=TRADITIONAL CHINESE.AL32UTF8
exp system/sys_dsc@topprod owner=%1 log=d:\backup\tiptop\exp\%1.log file=d:\backup\tiptop\exp\%1.dmp

再來就是用 ftp 軟體去抓取 Tiptop 主機的程式檔案到本機電腦。

最後就是執行 RAR 的批次指令囉,
就可以在專屬的備份主機,主動的抓取 TITPOP 程式和 Oracle 資料庫來備份啦~

2011年3月23日

Oracle 如何還原已刪除的 Table / 清除回收筒

從 Oracle 10g 開始, 就開始提供有 recyclebin 的功能 (資源回收筒) ,
所以一旦不小心 drop table 刪錯了, 而且已經 commit ,
由於在 Oracle 10g 裡面的運作, 只是把原本的 Table 名稱換成 BIN$1234567890==$0 ,
沒關係, 只要把 recyclebin 裡面的物件還原就好啦~~
總是會有不小心的時候嘛~~
也由於沒有釋放 Tablespace 的空間, 也因此查詢 tablespace 佔用大小時就會越來越慢 ,
所以建議還是固定時間去清理一下 ,

以下就是整個還原會用到的相關指令 :

1. 查看目前有那些 Table
select * from tab

2. 查看資源回收有那些物件
select * from recyclebin;

select * from dba_recyclebin
或 SQLPLUS 的
SQL> show recyclebin

3. 再來就是還原指令
FLASHBACK TABLE [被刪除的 Table Name] TO BEFORE DROP;

如果是刪除 Table  不要放到 recyclebin 呢?
drop table recycletest purge;

當然囉, 也可以指定那些物件確定要清除 recyclebin
purge table recycletest;

要清空資源回收筒:
purge recyclebin;

purge dba_recyclebin;

要注意喔~ 建議用 BIN$1234567890==$0 當作 Table 名稱的方式來還原,
因為有可能建立重複的 Table 名稱, 到時候還原的方式是以後刪除的先還原,
BIN$1234567890==$0 數字越大表示越晚刪除的物件.

遇到重複 Table 的情況時, 可以還原的時候變更 Table 的名稱,
flashback table [刪除的 Table 名稱] to before drop rename to [要還原的 Table 名稱];

當然也可以打開或關閉資源回收筒的功能:
alter session set recyclebin = off;
alter system set recyclebin = off;

因 TIPTOP 執行批次作業或是報表的時候,都會產生暫存 Table 的,
像是 TT 開頭+一串數字+_文字 的 Table 就是暫存時產生的資料,以後也不會再用到了。
有時候也不會 DROP 掉一直存留著,或是就算 DROP 也會一直留在回收筒,
只要在 Oracle 建立排程,定時把這些垃圾都清一清吧~
declare
    str varchar2(1000);
    num number;
    begin
   --刪除 TEMP TABLE
    for i in(select table_name from user_tables ,user_objects where table_name like 'TT%' and created <= sysdate - 3 and table_name = object_name and object_type = 'TABLE' and tablespace_name = 'TEMPTABS')
    loop
    str:='drop table '||i.table_name||' purge ';
    execute immediate str ;
    commit;
   end loop;
   --清空回收筒
    for i in(select object_name,droptime from user_recyclebin where droptime < to_char(sysdate-3,'YYYY-MM-DD hh:mm:ss') and type= 'TABLE' order by droptime)
    loop
    str:='purge table "'||i.object_name||'" ';
    execute immediate str ;
    commit;
   end loop;
   end;

2011年3月16日

TIPTOP 和其他系統整合的架構

說到系統整合, 大家應該是惟恐不及吧~~
變成盡量讓其他的系統廠商去思考如何和 ERP 系統來整合,
但越來越多系統的話, 不就有越來越多的整合方式, 在管理上或問題釐清就變的複雜了.

在整合外部多種系統後發現, 比較容易和確實的就屬中介 Table 是最好的方式,
可以避免外部的系統直接寫入 ERP 的資料庫, 可以建立存取權限.
也讓系統整合能夠有足夠資料去稽核正確性.

再來就是系統整合的架構囉~

建立外部系統的 Oracle user account , 並在此 DB 帳號建立要讀取 ERP 的 readonly view ,
之後要取得 ERP 系統的資料, 就可以直接連到資料庫去 Select .
如果是要存入或異動資料到 ERP Database, 需要透過中介 Table 方式進行,
外部系統先寫入到中介 DB 的 Table (需先跟廠商溝通好整合的資料 Schema) ,
然後再由 ERP 用 cron job 或是手動的方式執行程式去建立或異動資料,
確認資料異動正確或錯誤, 回寫狀態碼給中介 DB 的 Table,
外部程式再去 Check 整合資料是否完整和正確.

整合系統讓權責能夠區分清楚, 避免以後維護和責任確認可以比較清楚和容易.

以 APS 的範例如下:
1. 和 APS 系統整合, 所以建立在 Oracle 建立 aps 的帳號名稱.
    使用 sys 帳號和 sysdba 方式登入
    conn sys/sys_dsc as sysdba;
    --create user
   CREATE USER aps
     IDENTIFIED BY aps
     DEFAULT TABLESPACE DBS1
     TEMPORARY TABLESPACE TEMP
     PROFILE TIPTOPGP
     ACCOUNT UNLOCK;
     -- 2 Roles for aps
     GRANT RESOURCE TO aps;
     GRANT TIPTOPGP TO aps;
     ALTER USER aps DEFAULT ROLE ALL;
     -- 5 System Privileges for aps
     GRANT UNLIMITED TABLESPACE TO aps;
     GRANT CREATE VIEW TO aps;
     GRANT CREATE TABLE TO aps;
     GRANT CREATE SYNONYM TO aps;
     GRANT CREATE SESSION TO aps;
     -- 1 Object Privilege for aps
     GRANT SELECT ON SYS.V_$SESSION TO aps;

2. 建立 aps 所要讀取 ERP 的 Table 資料 readonly view .
    我假設是全部 DS 裡面的 table 都可以讀取.
    select 'CREATE OR replace view aps.' || table_name || ' as
               select * from ds.' || table_name || ' with read only;'
      from  dba_tables
    where owner = 'DS'
    order by 1
   
    再把 SQL 執行後的資料, 全部複製再執行.
    或一個一個 table 加上去
    CREATE OR replace view aps.XXX_FILE as select * from ds.XXX_FILE with read only;

3. 在 aps Database 中建立中介 Table 的 Schema . 
    APS 會回寫工單和請購單, 所以我就叫 aps_sfb_file 和 aps_pml_file .

4. 使用者完成外部 APS 系統後, 回寫工單和請購單的資料到 ERP 系統,
    新增 APS 接口的程式, 去讀取中介 Table 和產生 ERP 的單號 .
    完成後回寫狀態到中介 Table .

2011年3月9日

TIPTOP Genero 呼叫本機的程式來執行

TIPTOP 導入之後, 再來就是一連串的外部程式整合囉~~
能夠提供公司全資訊化的服務, 才是 IT 價值所在.

最近想辦法整合條碼的設計軟體,
讓 TIPTOP 能夠抓取資料, 呼叫外部條碼軟體並丟參數值, 由條碼軟體列印出來.
這樣可以讓設計條碼的人就不是 IT 囉~~(這才是我的目的~~)
也簡化了作業的流程, 和日後的維護工作.

不過要如何做呢??
可以參考 cl_client_app.4gl 的程式,
就可以發現 GDC 是可以呼叫 Genero 稱之為"前端"的程式段, ( ui.Interface.frontCall )
只要在要呼叫外部軟體的程式上,加上 cl_open_prog("Shell的程式名稱","參數") ,
如果是多參數的話用 | (pipe) 來分隔.

以範例來說, 我是呼叫"記事本" (notepad) ,
然後檔案的位置在本機的 C:\TIPTOP\xxxxx.TXT ,
加上:

LET status = cl_open_prog("notepad","C:\\TIPTOP\\xxxxx.TXT")

這樣就完成啦~~~試試看吧~~~

2011年2月28日

多角貿易拋轉多倉儲批出貨收貨入庫單的問題

應該都知道出貨單可以多倉儲批出貨吧~
但收貨和入庫單是否可以多倉儲批呢?
當然是不行啦~ 只有出貨才能多筆倉儲批的數量合併成出貨單的同一項次.
所以拋轉到收貨單時變成了倉儲批的欄位是空白的. (那多角貿易就不能確保批號一致了)

問題來了, 這樣多角貿易不就不能用多倉儲批出貨了嗎?
難道要在出貨單一筆一筆 key 要出貨的資訊 ?
如果是鼎新的標準程式, 這是必然的, 必須出貨單產生多項才能避免此問題發生.
因為出貨單的項次和拋轉後的收貨入庫單項次是鎖死的. 必須要一致.
唉~

不過我們可以做以下的修改, 修改 saxmp900.4gl 的程式,
多抓 ogc_file ,並項次能夠是依 ogc_file 排序來自動編號, 這樣不就好了嗎?

1. 首先需要增加抓取 ogc_file 的資訊, 並只在中斷點的時候才做拆多倉儲批控管.

 2. 再來就是自動編號和產生多倉儲批的資訊囉~

3. 試拋看看吧. 看似很難其實很簡單吧.

要注意喔~ 修改確認段時, 就要注意取消確認段, 當然拋轉的程式也要注意拋轉還原囉~
所以記得也要改拋轉還原的程式啦~ 不然標準程式可是會拋轉還原失敗的.

2011年2月22日

請採購部門費用預算管控機制

相信每一家公司都是以營利為目的是吧?
不止要開源-增加訂單和出貨量,節流-控制部門的花費也是必要的管理手段.

如何讓 TIPTOP 實現公司部門費用的預算管理機制呢?
其實只是把功能打開就可以用囉~~
不過最重要的還是: 請購人員需要知道購買何種商品或是服務,
需要入到那一個費用的"會計科目",
入錯費用或是隨意輸入的話,當然就沒有管控的意義啦~

再來就是預算是以"年"為單位,
所以跨年度的預算的請購單, 當然最好是重 key 囉~ (有寫入年度的欄位就不能再續用了.)

如何開啟預算的呢?

1. 先匯入部門預算的資料. (相信應該原本就有在維護了吧~)

2. 會計科目開啟部門預算的控管.

3. 再來就是針對單別來做預算的功能開啟.

4. 之後就是各單位請購單, 記得在單身要維護部門的預算資料囉~~

PS : 部門費用預算的管制, 流程上會有一些程序上的問題,
       盡量能夠保有管控的機制才有意義.

2011年2月21日

如何查詢 TIPTOP 系統的所有欄位的內容和定義

我們在維護 TIPTOP 程式的時候, 會發現 SQL 指令要查詢那一個欄位.
用 p_zta 實在是不方便, 工作效率也不佳.

TIPTOP 在資料庫有紀錄欄位定義的 Table ,
以後只要查詢這一個 Table 就好啦~ 就可以快速查到你要的欄位定義和內容了.

範例參考 :
select * from ds.gaq_file
where gaq02 = '0'   --語言別
and gaq01 like '%ima%'   --Table 的代號
order by 1

是不是就方便許多了呢?

依不同國家的使用者設定不同時區

因 TIPTOP 系統是屬於 Clinet-Server 的架構, 如圖所示 :

也就是說, 所有的使用者端都是連線到伺服端裡面來執行程式,
伺服端執行完成後, 再把執行的結果的畫面傳回到使用者端,
所以 TIPTOP 登入的時間也就不是使用者本機的設定了,
而是 TIPTOP 主機 User profile 的設定.

要如何針對使用者讓顯示的時間是正確的呢?
很簡單, 只要針對 user 在 .profile 檔裡,
加入一行 export TZ=GST+8 就可以了 (以美國西岸為例) ,
再看時區為何來調整要加減多少.

但要注意喔~ .profile 檔不能是 link 的 file , 不然就所有使用者全部跟著改啦~
所以 .profile 檔要先移除 ln 再重新建立.

2011年2月17日

TIPTOP 主機定期備份 Oracle 資料 & TIPTOP 程式, 備份篇

相信 TIPTOP 主機的備份, 大多還是都存在 /u1/backup 目錄裡面,
而且只放一週的資料而已吧~~備份資料還有包含在正式區的測試資料庫...等。
再加上 TIPTOP GP 5.x 開始, 報表轉為 Crysal Report ,
需另外新增一台 IIS Web Service 的 CR 報表伺服器,
備份資料變的分散無法集中,再加上 Linux 沒有開啟 Samba 的服務,  (也比較安全一點)
備份上更是難以管理和紀錄.

好加在還有 FTP 的功能,提供資料上傳和下載的工具將資料移轉到另一台主機.
方便的做法當然是利用 CR 主機的 IIS 服務, 另外再加掛 ftp server 的功能囉~~
這樣備份就變的輕鬆而完整啦~~

TIPTOPGP 主機 --------經由 ftp-------->  CR 主機 ----------> 磁帶或遠端儲存媒體.
 (tar 程式 + exp Oracle DB)              (cr 報表檔)          (可以利用 rar 進行壓縮)

隨著時代不斷的進步,硬碟容量也比以前大很多囉,所以備份到硬碟也是可行的方法之一.
以下就是我的備份方式.皆用排程的方式來自動執行.省時又省力.

1. 上傳 ftp 的指令

2. 自動備份 Oracle 的匯出指令,首先要載入環境變數,讓排程會自動執行

3. 備份資料,可以排除一些 patch 和比較沒有用的資料檔, 節省備份時間和空間

4. 再來就是設定工作排程囉~~用 root 帳號登入後, 執行 crontab -e 來設定排程作業,
    範例說明是設定為早上 7 點自動執行.

5. 再補充一個 rar 的指令,讓資料能夠壓縮起來,資料庫的檔案大小可是差異很大的喔~~~
    可以壓縮大概 80% 的容量...100 MB 壓縮起來剩 20 MB 的磁碟空間大小.

當然囉~~市面上也有很多備份工具可以提供完整的 solution, 不過經濟又實惠的作法也是值得參考的.


2011年2月1日

如何用一個 SQL 來查 BOM -- 遞迴查詢

常常在設計連結資料庫程式的時候, 階層式架構的 Table 大致上都是母子在同一行的樣式來設計,                

資料庫 Table 是容易設計,不過呢? 要把所有的階層展開時,程式就不容易寫,且執行效能也低落,
其實 SQL 是可以做遞迴查詢的,不但不用寫程式一直 WHILE 跑迴圈 , 而且執行效率更快.

以下是 TIPTOP 5.x 的多階 BOM 的 Oracle 範例:

select level,bmb02,bmb01,bmb03,bmb04,bmb05 from bmb_file,bma_file,ima_file
where (bmb05 > sysdate or bmb05 is null)
  and (bmb04 < sysdate or bmb04 is null)
  and bma01 = bmb01 and bmaacti = 'Y'
  and bma01 = ima01
connect by  bmb01 = prior bmb03 and (bmb05 > sysdate or bmb05 is null) and (bmb04 < sysdate or bmb04 is null) and bmaacti = 'Y'
start with ima01 = '料件編號' and (bmb05 > sysdate or bmb05 is null) and (bmb04 < sysdate or bmb04 is null) and bmaacti = 'Y'

抓取最新的 BOM , 有生失效日的判斷 , 重點是還有階層數喔~~
可以試試看.

再提供一些相關的指令:
LEVEL:階數
SYS_CONNECT_BY_PATH(欄位,符號):可以列出整個路徑出來,符號用 -> 會比較清楚
CONNECT_BY_ISLEAF:可以判斷是不是最底層
CONNECT_BY_ROOT(欄位):顯示最上層的資料欄位
CONNECT_BY_ISCYCLE:判斷是否有迴圈
NOCYCLE:加在 CONNECT BY 後面有迴圈的就不繼續往下,可配合 CONNECT_BY_ISCYCLE 使用