SQL> select dbms_xdb.gethttpport as "HTTP-Port"
, dbms_xdb.getftpport as "FTP-Port" from dual;
HTTP-Port FTP-Port
---------- ----------
8080 0
- 8月 20 週五 201015:05
OracleXE在udl的設定
- 7月 27 週二 201019:59
OGG for Java開發:PK欄位的Update
- 7月 12 週一 201019:20
OGG for Java開發
extract ext1 # 宣告extract name
userid ogg, password oracle # 連Oracle的ID/PWD
EXTTRAIL ./dirdat/je # OGG放置redo.log路徑,檔名je開頭
table jemmy.FOO; # 允許Schema Jemmy的FOO table
table orcl.BAR; # 允許Schema ocrl的BAR table
userid ogg, password oracle
defsfile ./dirprm/javaue.def # 產出javaue.def檔
table jemmy.*;
table ocrl.*;
Extract javaue
SetEnv (JAVA_HOME = "/usr/java5_64")
SetEnv (LIBPATH = "/usr/java5_64/jre/bin/j9vm:/usr/java5_64/jre/bin:/oracle10/lib:/ogg/ogg_sync")
SetEnv (GGS_USEREXIT_CONF = "dirprm/cuserexit.properties" ) # OGG for Oracle的設定
SetEnv (GGS_JAVAUSEREXIT_CONF = "dirprm/javaue.properties") # OGG for Java的核心設定
CUserExit Java5_UserExit.so CUSEREXIT PassThru IncludeUpdateBefores # CUserExit是OGG for Oracle核心程式
GetUpdateBefores
NoCompressDeletes
NoCompressUpdates
Table jemmy.*;
Table orcl.*;
#gg.handlerlist=sample_test # sample_test是ggjava提供的用Velocity讀取redo.log的處理程式
#gg.handlerlist=test_jms,sample_test
gg.handlerlist=sample_test,ogg_adapter
# OGG Adapter
gg.handler.ogg_adapter.type=com.mycompany.OggHandler
gg.classpath=/ogg/ogg_tprs33a/ggjava/resources/lib/NCSO.jar,/ogg/ogg_tprs33a/ggjava/resources/lib/Notes.jar
- gg.handlerlist:後面接的是處理程式代名,可以多個,用逗號分隔。和log4j指定appender方法一樣。
- gg.handlerlist.程式代名.type:是指這程式代名實際對應的類別,需要在/dirprm/com/mycompany下找到OggHandler這個類別。該類別實作容後再敍。
- gg.classpath:import額外的jar檔,用逗號分隔。
- gg.handlerlist.程式代名.自訂屬性:ggjava好像進步到可以該程式代名需要的屬性。
package com.mycompany;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.goldengate.atg.datasource.AbstractHandler;
import com.goldengate.atg.datasource.DsConfiguration;
import com.goldengate.atg.datasource.DsEvent;
import com.goldengate.atg.datasource.DsOperation;
import com.goldengate.atg.datasource.DsTransaction;
import com.goldengate.atg.datasource.GGDataSource.Status;
import com.goldengate.atg.datasource.meta.DsMetaData;
public class OggHandler extends AbstractHandler { // 繼承它
private static Logger logger = LoggerFactory.getLogger(OggHandler.class);
private List<DsOperation> rows = new ArrayList<DsOperation>(); // DsOperation表示一筆增改刪動作
@Override
public void init(DsConfiguration arg0, DsMetaData arg1) {
super.init(arg0, arg1);
logger.debug("[1]init");
}
@Override
public Status operationAdded(DsEvent e, DsTransaction tx, DsOperation op) {
logger.debug("[4]operationAdded");
this.rows.add(op); // 增加一筆record至list
return Status.OK;
}
@Override
public Status transactionBegin(DsEvent e, DsTransaction tx) {
logger.debug("[3]transactionBegin");
return Status.OK;
}
@Override
public Status transactionCommit(DsEvent e, DsTransaction tx) {
logger.info("[5]transactionCommit size={}", this.rows.size());
OggThread poster = new OggThread();
poster.setOps(this.rows); // 傳該transaction所有record過去(即一個List)
poster.setDsMetaData(this.getMetaData()); // 傳該DataSource的中介資訊
Thread t = new Thread(poster);
t.start();
this.rows = null;
this.rows = new ArrayList<DsOperation>();
return Status.OK;
}
@Override
public void destroy() {
logger.debug("[7]destory");
}
@Override
public Status metaDataChanged(DsEvent e, DsMetaData meta) {
logger.debug("[2]metaDataChanged");
return Status.OK;
}
@Override
public String reportStatus() {
logger.debug("destory[6]");
return "status report...";
}
}
for (DsOperation op : this.ops) { // 取得每筆record
TableName tableName = op.getTableName(); // 該record所屬table
TableMetaData tableMetaData = this.dsMetaData.getTableMetaData(tableName); // 取得該table中介資訊
List<ColumnMetaData> keyList = tableMetaData.getKeyColumns(); // 取得該table的primary key欄位
DsOperation.OpType opType = op.getOperationType(); // 取得該record的操作(增|刪|改)
for(DsColumn dsCol: op.getColumns()) { // 取得該record每個欄位
ColumnMetaData cMeta = tableMetaData.getColumnMetaData(colNum); // 取得該欄位中介資訊
String colName = cMeta.getColumnName(); // 取得欄位名稱
String afterValue = dsCol.getAfterValue(); // 取得欄位修改後值
String beforeValue = dsCol.getBeforeValue(); // 取得欄位修改前值
// ...
}
}
- 5月 15 週六 201018:35
ORA-08002
- 5月 08 週六 201021:39
Oracle的Array型態定義與存取
import javax.sql.DataSource;
import oracle.sql.ARRAY;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.systex.rdf4.util.AnnotationConfigContextLoader;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class,
value = "com.foo.bar.DSConfig")
public class TestVArray {
private static Logger logger = LoggerFactory.getLogger(TestVArray.class);
private SimpleJdbcTemplate simpleJdbcTemplate;
@Autowired
public void init(DataSource datasource) {
this.simpleJdbcTemplate = new SimpleJdbcTemplate(datasource);
}
@Test
public void testVArray() {
String sql = "insert into employee values (?, ?, varray_phone(?, ?, ?))";
this.simpleJdbcTemplate.update(sql, 2, "Tom", "12345", "67890", "09876");
sql = "select * from employee";
List<Map<String, Object>> rsList = this.simpleJdbcTemplate.queryForList(sql);
for (int i=0, n=rsList.size(); i<n; i++) {
System.out.println("====== Line #" + i + " ======");
Map<String, Object> map = rsList.get(i);
System.out.println(map.get("NAME"));
ARRAY array = (ARRAY) map.get("PHONE");
try {
String[] values = (String[]) array.getArray();
if (values != null) {
for (String phone : values) {
System.out.println(phone + ", ");
}
} else {
System.out.print("phone is null");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
- 9月 23 週三 200914:58
How to change OracleXE HTTP Port on Windows
- 9月 22 週二 200915:41
PL/SQL的Exit與Return
- 8月 27 週四 200918:22
Oracle的Stored Procedure執行truncate table
- 8月 26 週三 200923:21
oracle export script及Tool
set feedback off
set linesize 9999
set pagesize 0
set sqlprompt ''
set trimspool on
spool log.csv select log_id||','||
log_date||','||
log_memo
from log_tablewhere order by sp_id; spool off 如此,在VPN連上遠端的Terminate後,su - oracle切換到oracle帳號,將該script傳到其home目錄下, 下達:sqlpulse [id]/[pwd]@[sid] @exp.sql,就會根據exp.sql的指定寫到log.csv檔了。 上述是目前進行專案遇到stored procedure的效能瓶頸,所以在procedure加insert到log的指令查看是瓶頸所在,所以匯出log.csv後,該怎麼分析呢?我還是比較擅長使用Perl,微軟轉投資的ActiveState的Komodo IDE是Windows下最好的script IDE,可惜要錢,現在也跟上免費的潮流,出了免費的Komodo Edit,試用了一下,需要像UltraEdit一樣事先config命令,不然沒有像Komodo IDE一樣有個play的按鍵,也難怪叫Edit啦,試用結果還不是很順手,使用EditPlus run Perl較多。 分析的話,在Perl裡面怎麼寫,我通常把log.csv純文字內容貼在__DATA__之後,再用while (<DATA>) {…}逐筆取出,使用split以逗號分隔進行解析。 while (<DATA>) { chomp; @comma = split/,/; … } 甚至組成一行行的insert sql寫進MySQL做查詢,比如我可多出一個欄位計算這筆記錄和上筆記錄時間差,若沒有運算的需要,其實直接在exp.sql組成insert sql就OK了。 做系統開發到現在,我從不奢求之前寫code或現在合作的對象,程式能力有多好,但就是有人常常寄厚望某個萬能工具能為自己做解析、改善。其實是有這個萬能工具,如IBM的Rational Rose,除了要價不斐,更需要去學它的方法論以及貫徹執行才有它的value;當然也可以用於重構,可是重構層次也是到程式技巧,和部份的Design Pattern重構,遇到架構層次的議題,目前應該還做不到。 就像蔡學鏞曾列出一條Anti-Pattern,想做產品一勞永逸的賣,但實際卻必須接專案維持財務運作。一樣的道理,就有同事很天真想買一套EA(Enterprise Architecture)就從此靠它了,這遇到新案或可有作為,遇舊案需要後續維護,誰願接手。這也是我老用Perl寫些臨時小工具的緣故,快又即時,也因此不必去想把Perl寫成Super Tool。
- 8月 20 週四 200911:36
Oracle的Sequence用法
1、Create Sequence
你首先要有CREATE SEQUENCE或者CREATE ANY SEQUENCE權限,
CREATE SEQUENCE emp_sequence
INCREMENT BY 1 -- 每次加幾個
START WITH 1 -- 從1開始計數
NOMAXVALUE -- 不設置最大值
NOCYCLE -- 一直累加,不循環
CACHE 10;
一旦定義了emp_sequence,你就可以用CURRVAL,NEXTVAL
CURRVAL=返回 sequence的當前值
NEXTVAL=增加sequence的值,然返回 sequence 值
比如:
emp_sequence.CURRVAL
emp_sequence.NEXTVAL
可以使用sequence的地方:
- 不包含子查詢、snapshot、VIEW的 SELECT 語句
- INSERT語句的子查詢中
- NSERT語句的VALUES中
- UPDATE 的 SET中
可以看如下例子:
INSERT INTO emp VALUES
(empseq.nextval, 'LEWIS', 'CLERK',7902, SYSDATE, 1200, NULL, 20);
SELECT empseq.currval FROM DUAL;
但是要注意的是:
- 第一次NEXTVAL返回的是初始值;隨的NEXTVAL會自動增加你定義的INCREMENT BY值,然返回增加的值。CURRVAL 總是返回當前SEQUENCE的值,但是在第一次NEXTVAL初始化之才能使用CURRVAL,否則會出錯。一次NEXTVAL會增加一次SEQUENCE的值,所以如果你在同一個語句裡面使用多個NEXTVAL,其值就是不一樣的。明白?
- 如果指定CACHE值,ORACLE就可以預先在內存裡面放置一些sequence,這樣存取的快些。cache裡面的取完,oracle自動再取一組到cache。 使用cache或許會跳號, 比如數據庫突然不正常down掉(shutdown abort),cache中的sequence就會丟失. 所以可以在create sequence的時候用nocache防止這種情況。
2、Alter Sequence
你或者是該sequence的owner,或者有ALTER ANY SEQUENCE 權限才能改動sequence. 可以alter除start至以外的所有sequence參數.如果想要改變start值,必須 drop sequence 再 re-create .
Alter sequence 的例子
ALTER SEQUENCE emp_sequence
INCREMENT BY 10
MAXVALUE 10000
CYCLE -- 到10000從頭開始
NOCACHE ;
影響Sequence的初始化參數:
SEQUENCE_CACHE_ENTRIES =設置能同時被cache的sequence數目。
可以很簡單的Drop Sequence
DROP SEQUENCE order_seq;
好吧,就到這裡。
