Steps
1. create a shared (standalone) train region
2. create your train pages (the individual steps)
3. create the links in the shared region
- configure the Destination URI to point on the individual pages
- also configure the Text parameter (this will be the one shown above the pages)
4. In your page's layout region, add a location
- configure the Extends property to point to the shared train region you created in the first step
*make sure you have Application Modules configured on your pages (in contrast to pages, this attribute follows the java package syntax)
5. create a page for your Navigation Bar
6. well, finally create the Navigation Bar region
- configure the First Step and Last Step attributes. Normally you would like to configure First Step to 1 and Last Step to the number of the last page (in this case, 2)
7. create links inside that region
- configure the Destination URI in this format OA.jsp?page=/xxx/xxx/xxx/xxxPG
- configure the text visual property
8. create a pageButtonBar region for each individual step pages (you may create the first then copy paste to the rest)
*make sure the Nav Bar links text and the Train links text are identical
programming is an art, a form of expression only the logic side of our brain could appreciate
Sunday, November 28, 2010
Thursday, November 25, 2010
Adding Time Units to SYSDATE
SELECT SYSDATE + INTERVAL '30' MINUTE
FROM SYS.DUAL
simply nice ^^ <3
l_performance_rating_year1 VARCHAR2(10) := TO_CHAR(SYSDATE - INTERVAL '3' YEAR, 'YYYY');
l_performance_rating_year2 VARCHAR2(10) := TO_CHAR(SYSDATE - INTERVAL '2' YEAR, 'YYYY');
l_performance_rating_year3 VARCHAR2(10) := TO_CHAR(SYSDATE - INTERVAL '1' YEAR, 'YYYY');
FROM SYS.DUAL
simply nice ^^ <3
l_performance_rating_year1 VARCHAR2(10) := TO_CHAR(SYSDATE - INTERVAL '3' YEAR, 'YYYY');
l_performance_rating_year2 VARCHAR2(10) := TO_CHAR(SYSDATE - INTERVAL '2' YEAR, 'YYYY');
l_performance_rating_year3 VARCHAR2(10) := TO_CHAR(SYSDATE - INTERVAL '1' YEAR, 'YYYY');
SYS.DUAL
First time seeing it XD
SELECT WF_NOTIFICATIONS_S.NEXTVAL
INTO nid
FROM SYS.DUAL;
got used to the plain DUAL, I didn't noticed it's from SYS schema XD? just something trivial
SELECT WF_NOTIFICATIONS_S.NEXTVAL
INTO nid
FROM SYS.DUAL;
got used to the plain DUAL, I didn't noticed it's from SYS schema XD? just something trivial
(String) Object vs Object.toString()
well, just a thought - I searched around and it seems casting is preferred over the toString() method call XD It's slightly "faster" .. but prolly this info would only be useful if you're dealing with tons of Objects to convert into Strings ^^;;
Oracle DECODE
Well I've used this a dozen of times .. just noting myself :D
SELECT DECODE(XXHLS_STAFF_PKG.GET_CATEGORY_FN(SYSDATE,PERSON_ID), 'PS', 'LIBOR Interest Rate', 'SS', 'Interest Rate') AS TYPE
FROM XXHLS.XXHLS_LOAN_APPLICATION
=A=
SELECT DECODE(XXHLS_STAFF_PKG.GET_CATEGORY_FN(SYSDATE,PERSON_ID), 'PS', 'LIBOR Interest Rate', 'SS', 'Interest Rate') AS TYPE
FROM XXHLS.XXHLS_LOAN_APPLICATION
=A=
Wednesday, November 24, 2010
Commit in DML Procedure
PROCEDURE armageddon
IS
BEGIN
purge_usr_loan_data_fn(113814);
commit;
END armageddon;
Well just a note to myself. If you want your DML changes reflected in the database, issue the command commit =A=
The procedure above calls on another procedure programmed to delete all data I persisted in the database ^^ Having tons of test data could be annoying most of the time, so I need to clean them up once in a while.
IS
BEGIN
purge_usr_loan_data_fn(113814);
commit;
END armageddon;
Well just a note to myself. If you want your DML changes reflected in the database, issue the command commit =A=
The procedure above calls on another procedure programmed to delete all data I persisted in the database ^^ Having tons of test data could be annoying most of the time, so I need to clean them up once in a while.
Monday, November 22, 2010
Dynamic Messages Using Tokens
First you must create a message in Oracle Apps and tag the dynamic part of the message with an ampersand "&". By convention these tags must be in uppercase. - &LOAN_ENTRIES
MessageToken[] tokens = {new MessageToken("LOAN_ENTRIES", getInstructionLoanEntries(loanTypeCode,am)) };
oaRawTextBean.setText(pageContext.getMessage("XXHLS", "XXHLS_SIMULATE_PS_INST", tokens));
Import MessageToken class and create an array of it with elements containing the tags you used in the message. Take note of the application short name and the message name - parameters that will be used for the getMessage method.
Random Rant =w=
JDeveloper's intellisense is buggy - when there is an error in the code, the reflector cannot properly detect the methods in the class anymore .. wtf TwT and so as the refactor function .. rawr
Tuesday, November 16, 2010
Date Manipulation in Java
java.util.Date doesn't have explicit methods for adding days, months, years, etc. However you can indirectly accomplish these operations through the java.util.Calendar class:
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.YEAR, 3);
Date applicationDate = calendar.getTime();
This example gets the current date (aka SYSDATE) then adds 3 years to it; then assigns it to applicationDate variable.
If you already have an existing Date object, just get a Calendar instance then call:
setTime(Date date)
function =A=
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.YEAR, 3);
Date applicationDate = calendar.getTime();
This example gets the current date (aka SYSDATE) then adds 3 years to it; then assigns it to applicationDate variable.
If you already have an existing Date object, just get a Calendar instance then call:
setTime(Date date)
function =A=
Sunday, November 14, 2010
DBMS_OUTPUT Function Using SQL*PLUS
you must first enable message output through this panel:
then issue a command like:
SQL> EXEC DBMS_OUTPUT.PUT_LINE('Pogi Ako')
Pogi Ako
PL/SQL procedure successfully completed.
then issue a command like:
Pogi Ako
PL/SQL procedure successfully completed.
Utility PLSQL Function for Retrieving MEANING from FND_LOOKUP_VALUES
Java function from the utility class
String lookupType,
String lookupCode,
OADBTransaction oaDBTransaction) {
CallableStatement callableStatement = null;
String s = "BEGIN ? := xxhls_util_pkg.get_fnd_meaning_fn(?,?,?); END;";
try {
callableStatement = oaDBTransaction.createCallableStatement(s, -1);
callableStatement.registerOutParameter(1, OracleTypes.VARCHAR);
callableStatement.setDate(2, effectiveDate);
callableStatement.setString(3, lookupType);
callableStatement.setString(4, lookupCode);
callableStatement.execute();
return callableStatement.getString(1);
} catch (Exception sqlexception) {
throw new OAException(sqlexception.getMessage());
} finally {
try {
if (callableStatement != null)
callableStatement.close();
} catch (SQLException sqlexception1) {
throw new OAException(sqlexception1.getMessage());
}
}
}
Java function inside the Application Module (pretty short =w=;; )
public String getFndLookupValue(String lookupType, String lookupCode) {
Date date = new Date(new java.util.Date().getTime());
return XxhlsServerUtil.getFndLookupValue(date, lookupType, lookupCode, this.getOADBTransaction());
}
PLSQL code
FUNCTION get_fnd_meaning_fn (i_effective_date IN DATE,
i_lookup_type IN FND_LOOKUP_VALUES.LOOKUP_TYPE%TYPE,
i_lookup_code IN FND_LOOKUP_VALUES.LOOKUP_CODE%TYPE)
RETURN FND_LOOKUP_VALUES.MEANING%TYPE
IS
l_meaning FND_LOOKUP_VALUES.MEANING%TYPE;
BEGIN
SELECT MEANING
INTO l_meaning
FROM FND_LOOKUP_VALUES
WHERE LOOKUP_TYPE = i_lookup_type
AND LOOKUP_CODE = i_lookup_code
AND i_effective_date BETWEEN START_DATE_ACTIVE AND END_DATE_ACTIVE;
RETURN l_meaning;
EXCEPTION
WHEN NO_DATA_FOUND THEN
SELECT MEANING
INTO l_meaning
FROM FND_LOOKUP_VALUES
WHERE LOOKUP_TYPE = i_lookup_type
AND LOOKUP_CODE = i_lookup_code
AND END_DATE_ACTIVE IS NULL;
RETURN l_meaning;
END get_fnd_meaning_fn;
Thursday, November 11, 2010
Returning VARCHAR/String from a PLSQL call in Application Module
Well, not all the time you want a CURSOR
public String getNextReferenceNumber(String loanTypeCode) {
CallableStatement callableStatement = null;
String s = "BEGIN ? := xxhls_housing_loan_pkg.get_next_reference_number_fn(?); END;";
try {
callableStatement = getOADBTransaction().createCallableStatement(s, -1);
callableStatement.registerOutParameter(1, OracleTypes.VARCHAR);
callableStatement.setString(2, loanTypeCode);
callableStatement.execute();
return ((OracleCallableStatement)callableStatement).getString(1);
} catch (Exception sqlexception) {
throw new OAException(sqlexception.getMessage());
} finally {
try {
if (callableStatement != null)
callableStatement.close();
} catch (SQLException sqlexception1) {
throw new OAException(sqlexception1.getMessage());
}
}
}
public String getNextReferenceNumber(String loanTypeCode) {
CallableStatement callableStatement = null;
String s = "BEGIN ? := xxhls_housing_loan_pkg.get_next_reference_number_fn(?); END;";
try {
callableStatement = getOADBTransaction().createCallableStatement(s, -1);
callableStatement.registerOutParameter(1, OracleTypes.VARCHAR);
callableStatement.setString(2, loanTypeCode);
callableStatement.execute();
return ((OracleCallableStatement)callableStatement).getString(1);
} catch (Exception sqlexception) {
throw new OAException(sqlexception.getMessage());
} finally {
try {
if (callableStatement != null)
callableStatement.close();
} catch (SQLException sqlexception1) {
throw new OAException(sqlexception1.getMessage());
}
}
}
Wednesday, November 10, 2010
Retrieving the Active Address of an Employee using PERSON_ID
note : the critical thing to know is PER_ADDRESSES table; since the employee's address is not explicitly defined in PER_ALL_PEOPLE_F
FUNCTION get_address_fn (i_application_date IN DATE,
i_person_id IN XXHLS_TYPES_PKG.t_person_id)
RETURN VARCHAR2
IS
l_address_line1 VARCHAR2(240) DEFAULT '';
l_address_line2 VARCHAR2(240) DEFAULT '';
l_address_line3 VARCHAR2(240) DEFAULT '';
BEGIN
SELECT ADDRESS_LINE1, ADDRESS_LINE2, ADDRESS_LINE3
INTO l_address_line1, l_address_line2, l_address_line3
FROM PER_ADDRESSES
WHERE PERSON_ID = 7890
AND PRIMARY_FLAG = 'Y'
AND i_application_date BETWEEN DATE_FROM AND DATE_TO;
RETURN l_address_line1 || ' ' || l_address_line2 || ' ' || l_address_line3;
EXCEPTION
-- case for future dated record, open ended record
WHEN NO_DATA_FOUND THEN
SELECT ADDRESS_LINE1, ADDRESS_LINE2, ADDRESS_LINE3
INTO l_address_line1, l_address_line2, l_address_line3
FROM PER_ADDRESSES
WHERE PERSON_ID = 7890
AND PRIMARY_FLAG = 'Y'
AND DATE_TO IS NULL;
RETURN l_address_line1 || ' ' || l_address_line2 || ' ' || l_address_line3;
END get_address_fn;
i_person_id IN XXHLS_TYPES_PKG.t_person_id)
RETURN VARCHAR2
IS
l_address_line1 VARCHAR2(240) DEFAULT '';
l_address_line2 VARCHAR2(240) DEFAULT '';
l_address_line3 VARCHAR2(240) DEFAULT '';
BEGIN
SELECT ADDRESS_LINE1, ADDRESS_LINE2, ADDRESS_LINE3
INTO l_address_line1, l_address_line2, l_address_line3
FROM PER_ADDRESSES
WHERE PERSON_ID = 7890
AND PRIMARY_FLAG = 'Y'
AND i_application_date BETWEEN DATE_FROM AND DATE_TO;
RETURN l_address_line1 || ' ' || l_address_line2 || ' ' || l_address_line3;
EXCEPTION
-- case for future dated record, open ended record
WHEN NO_DATA_FOUND THEN
SELECT ADDRESS_LINE1, ADDRESS_LINE2, ADDRESS_LINE3
INTO l_address_line1, l_address_line2, l_address_line3
FROM PER_ADDRESSES
WHERE PERSON_ID = 7890
AND PRIMARY_FLAG = 'Y'
AND DATE_TO IS NULL;
RETURN l_address_line1 || ' ' || l_address_line2 || ' ' || l_address_line3;
END get_address_fn;
Tuesday, November 9, 2010
Monday, November 8, 2010
Inserting a Row at the End of an OAF Table / Advanced Table
OAF inserts table rows on zero index by default. However there are times that you want to insert a row at the end of the table and you could accomplish that by:
not straightforward but it works :)
OARow oaRow = (OARow) VOImpl.createRow();
VOImpl.setRangeSize(VOImpl.getRowCount() + 1);
VOImpl.insertRowAtRangeIndex(VOImpl.getRowCount(), oaRow);
not straightforward but it works :)
OAF Sub Tab Layout Control
setting the active tab
OASubTabLayoutBean subTabLayout =
(OASubTabLayoutBean) webBean.findChildRecursive("SubTabLayout");
subTabLayout.setSelectedIndex(pageContext, 0);
getSelectedIndex method returns the index of the active tab
show or hide the tab by the boolean parameter (false = show it; true = hide it)
subTabLayout.hideSubTab(0, true);
OASubTabLayoutBean subTabLayout =
(OASubTabLayoutBean) webBean.findChildRecursive("SubTabLayout");
subTabLayout.setSelectedIndex(pageContext, 0);
getSelectedIndex method returns the index of the active tab
show or hide the tab by the boolean parameter (false = show it; true = hide it)
subTabLayout.hideSubTab(0, true);
Task Kill in CMD
issue the command 'tasklist'
C:\Documents and Settings\r21>tasklist
Image Name PID Session Name Session# Mem Usage
========================= ====== ================ ======== ============
System Idle Process 0 Console 0 28 K
System 4 Console 0 252 K
smss.exe 620 Console 0 420 K
csrss.exe 684 Console 0 8,180 K
winlogon.exe 708 Console 0 1,696 K
services.exe 752 Console 0 6,376 K
lsass.exe 764 Console 0 1,988 K
svchost.exe 960 Console 0 6,860 K
svchost.exe 1028 Console 0 5,820 K
svchost.exe 1068 Console 0 51,324 K
svchost.exe 1160 Console 0 4,836 K
svchost.exe 1196 Console 0 8,536 K
spoolsv.exe 1292 Console 0 8,172 K
svchost.exe 1360 Console 0 5,732 K
FireSvc.exe 1428 Console 0 1,596 K
HIPSvc.exe 1476 Console 0 3,236 K
jqs.exe 1492 Console 0 1,428 K
nsd.exe 1644 Console 0 4,124 K
EngineServer.exe 1716 Console 0 468 K
Image Name PID Session Name Session# Mem Usage
========================= ====== ================ ======== ============
System Idle Process 0 Console 0 28 K
System 4 Console 0 252 K
smss.exe 620 Console 0 420 K
csrss.exe 684 Console 0 8,180 K
winlogon.exe 708 Console 0 1,696 K
services.exe 752 Console 0 6,376 K
lsass.exe 764 Console 0 1,988 K
svchost.exe 960 Console 0 6,860 K
svchost.exe 1028 Console 0 5,820 K
svchost.exe 1068 Console 0 51,324 K
svchost.exe 1160 Console 0 4,836 K
svchost.exe 1196 Console 0 8,536 K
spoolsv.exe 1292 Console 0 8,172 K
svchost.exe 1360 Console 0 5,732 K
FireSvc.exe 1428 Console 0 1,596 K
HIPSvc.exe 1476 Console 0 3,236 K
jqs.exe 1492 Console 0 1,428 K
nsd.exe 1644 Console 0 4,124 K
EngineServer.exe 1716 Console 0 468 K
afterward issue 'taskkill' using this pattern: taskkill /f /pid 516
SUCCESS: The process with PID 516 has been terminated.
Sunday, November 7, 2010
Oracle Function Overloading
things to keep in mind
1. you can't overload by merely changing the return type
- meaning you must change the number, name, order or data type of the parameters (but I'm a bit skeptic over changing the name - I haven't tested it yet)
1. you can't overload by merely changing the return type
- meaning you must change the number, name, order or data type of the parameters (but I'm a bit skeptic over changing the name - I haven't tested it yet)
Parsing DATE to VARCHAR
SELECT TO_CHAR(TO_DATE('01-JAN-2008', 'DD-MM-YYYY'), 'YY')
FROM dual;
in here I would just like to extract the last 2 digits of the year and retrieve it as VARCHAR
FROM dual;
Calling PL/SQL from OAF Application Module
Note: probably the most critical part is getOADBTransaction().createCallableStatement(s, -1). take note of the CallableStatment object - this might have a generic implementation on Java or other frameworks.
primary method (insideAMImpl.java)
utility methods
Another way I found on Andries blog . I think I like this because it's much simpler; but you need to manually populate the View Objects
1. calling from CO
2. calling from AM
primary method (inside
public void searchRequiredDocuments (String loanTypeCode) {
if (getXxhlsRequiredDocumentsVO1().getRowCount() == 0) {
OAViewObject vo = getXxhlsRequiredDocumentsVO1();
CallableStatement cs = null;
ResultSet rs = null;
String s = "BEGIN ? := xxhls_test_pkg.get_actv_loan_docs_applied_fn(?); END;";
try {
cs = getOADBTransaction().createCallableStatement(s, -1);
cs.registerOutParameter(1, OracleTypes.CURSOR);
cs.setString(2, loanTypeCode);
cs.execute();
rs = ((OracleCallableStatement)cs).getCursor(1);
populateViewObject(rs, vo);
} catch (Exception sqlexception) {
throw new OAException(sqlexception.getMessage());
} finally {
try {
if (cs != null)
cs.close();
if (rs != null)
rs.close();
} catch (SQLException sqlexception1) {
throw new OAException(sqlexception1.getMessage());
}
}
}
}
utility methods
protected static void populateViewObject (ResultSet rs, OAViewObject vo) throws SQLException {
Map rsvo = new java.util.HashMap();
if (vo == null) {
return;
}
rsvo = mapAttrNames(vo);
int cnt = 0;
while (rs.next()) {
Row row = vo.createRow();
vo.setRangeSize(cnt + 1);
vo.insertRowAtRangeIndex(cnt, row);
ResultSetMetaData rsmd = rs.getMetaData();
int numOfCol = rsmd.getColumnCount();
for (int i = 0; i < numOfCol; i++) {
String colName = rsmd.getColumnName(i + 1);
String attrName = (String)rsvo.get(colName);
if (attrName != null)
setVoAttribute(vo, row, attrName, rs.getObject(colName));
}
cnt++;
}
}
protected static Map mapAttrNames (OAViewObject vo) {
Map attrNames = new java.util.HashMap();
if (vo == null) {
return null;
}
AttributeDef[] attrDefs = vo.getAttributeDefs();
int attrCount = (attrDefs == null) ? 0 : attrDefs.length;
if (attrCount == 0) {
return null;
}
for (int i = 0; i < attrCount; i++) {
byte attrKind = attrDefs[i].getAttributeKind();
if (!(attrKind == AttributeDef.ATTR_ASSOCIATED_ROW || attrKind == AttributeDef.ATTR_ASSOCIATED_ROWITERATOR || attrKind == AttributeDef.ATTR_DYNAMIC)) {
String colName = attrDefs[i].getColumnNameForQuery();
String attrName = attrDefs[i].getName();
attrNames.put(colName, attrName);
}
}
return attrNames;
}
protected static void setVoAttribute (OAViewObject vo, Row row, String attrName, Object attrVal) {
if (vo.lookupAttributeDef(attrName) != null) {
if (attrVal != null) {
row.setAttribute(attrName, attrVal);
}
}
}
Another way I found on Andries blog . I think I like this because it's much simpler; but you need to manually populate the View Objects
1. calling from CO
// Invoke the method
HashMap returnValues = (HashMap) am.invokeMethod("executePlsql");
// Get the returned values from the method
String status = (String) returnValues.get("Status");
String message = (String) returnValues.get("Message");
if (!status.equals("SUCCESS")) {
am.invokeMethod("rollback");
// ERRORS from executePlsql
MessageToken[] tokens =
{new MessageToken("STATUS", status),
new MessageToken("MESSAGE", message)};
OAException errorMessage = new OAException("XX",
"XX_PLSQL_ERR", tokens,
OAException.ERROR, null);
pageContext.putDialogMessage(errorMessage);
}
2. calling from AM
import com.sun.java.util.collections.HashMap;
import java.sql.CallableStatement;
import java.sql.SQLException;
import java.sql.Types;
public HashMap executePlsql(String objectId, String objectSubType) {
CallableStatement st = null;
HashMap returnValues = new HashMap(2);
try {
String stmt = "BEGIN xx_pkg.xx_procedure( "
+ "p_object_id => :1, "
+ "p_object_sub_type => :2, "
+ "p_status => :3, "
+ "p_message => :4); END;";
OADBTransaction tr = getOADBTransaction();
st = tr.createCallableStatement(stmt, 1);
// Bind the input parameters
st.setInt(1, Integer.parseInt(objectId));
st.setString(2, objectSubType);
// Register return variables
st.registerOutParameter(3, Types.VARCHAR);
st.registerOutParameter(4, Types.VARCHAR);
st.execute();
// Assign returned values to variables
String status = st.getString(3);
String message = st.getString(4);
st.close();
// Populate HashMap with return variables
returnValues.put("Status", status);
returnValues.put("Message", message);
OAExceptionUtils.checkErrors(tr);
}
catch (SQLException sqle) {
throw OAException.wrapperException(sqle);
}
return returnValues;
}
Oracle ALL_OBJECTS table
SELECT *
FROM ALL_OBJECTS
http://download.oracle.com/docs/cd/B19306_01/server.102/b14237/statviews_2005.htm
SELECT *
FROM ALL_OBJECTS
WHERE OBJECT_TYPE = 'TABLE'
retrieve tables accessible to the user
SELECT UNIQUE(OBJECT_TYPE)
FROM ALL_OBJECTS
CONSUMER GROUP
INDEX PARTITION
TABLE SUBPARTITION
SEQUENCE
SCHEDULE
TABLE PARTITION
JAVA DATA
QUEUE
PROCEDURE
OPERATOR
WINDOW
LOB PARTITION
PACKAGE BODY
PACKAGE
LIBRARY
PROGRAM
LOB
INDEX SUBPARTITION
CONTEXT
JAVA RESOURCE
XML SCHEMA
TYPE BODY
TRIGGER
JOB CLASS
DIRECTORY
MATERIALIZED VIEW
TABLE
INDEX
SYNONYM
VIEW
FUNCTION
WINDOW GROUP
JAVA CLASS
INDEXTYPE
JAVA SOURCE
CLUSTER
TYPE
EVALUATION CONTEXT
LOB SUBPARTITION
FROM ALL_OBJECTS
contains information on objects accessible to the USER (schema)
http://download.oracle.com/docs/cd/B19306_01/server.102/b14237/statviews_2005.htm
SELECT *
FROM ALL_OBJECTS
WHERE OBJECT_TYPE = 'TABLE'
retrieve tables accessible to the user
SELECT UNIQUE(OBJECT_TYPE)
FROM ALL_OBJECTS
CONSUMER GROUP
INDEX PARTITION
TABLE SUBPARTITION
SEQUENCE
SCHEDULE
TABLE PARTITION
JAVA DATA
QUEUE
PROCEDURE
OPERATOR
WINDOW
LOB PARTITION
PACKAGE BODY
PACKAGE
LIBRARY
PROGRAM
LOB
INDEX SUBPARTITION
CONTEXT
JAVA RESOURCE
XML SCHEMA
TYPE BODY
TRIGGER
JOB CLASS
DIRECTORY
MATERIALIZED VIEW
TABLE
INDEX
SYNONYM
VIEW
FUNCTION
WINDOW GROUP
JAVA CLASS
INDEXTYPE
JAVA SOURCE
CLUSTER
TYPE
EVALUATION CONTEXT
LOB SUBPARTITION
Thursday, November 4, 2010
Looping Through CURSOR
Note: Cursor is basically a representation of the result set generated from an SQL; this example shows how to loop through that result set and access its values
PROCEDURE delete_loan_type_history_pr (i_loan_type_code IN XXHLS.XXHLS_LOAN_TYPE_LIST.LOAN_TYPE_CODE%TYPE)
IS
BEGIN
FOR l_cursor IN (SELECT LOAN_TYPE_HISTORY_ID
FROM XXHLS.XXHLS_LOAN_TYPE_HISTORY
WHERE LOAN_TYPE_CODE = i_loan_type_code)
LOOP
-- delete documents
delete_loan_docs_applied_pr(l_cursor.LOAN_TYPE_HISTORY_ID);
-- delete history record
DELETE FROM XXHLS.XXHLS_LOAN_TYPE_HISTORY
WHERE LOAN_TYPE_HISTORY_ID = l_cursor.LOAN_TYPE_HISTORY_ID;
END LOOP;
END delete_loan_type_history_pr;
IS
BEGIN
FOR l_cursor IN (SELECT LOAN_TYPE_HISTORY_ID
FROM XXHLS.XXHLS_LOAN_TYPE_HISTORY
WHERE LOAN_TYPE_CODE = i_loan_type_code)
LOOP
-- delete documents
delete_loan_docs_applied_pr(l_cursor.LOAN_TYPE_HISTORY_ID);
-- delete history record
DELETE FROM XXHLS.XXHLS_LOAN_TYPE_HISTORY
WHERE LOAN_TYPE_HISTORY_ID = l_cursor.LOAN_TYPE_HISTORY_ID;
END LOOP;
END delete_loan_type_history_pr;
PLSQL Error Handling Sample
accomplished by defining an EXCEPTION block right before the END of the procedure. You could specifically handle every type of Oracle predefined exceptions (or your own custom exception) using the WHEN <exception type> THEN clause. <exception type> = OTHERS serves as a catch basin for all excpetions.
TODO: review the list of Oracle predefined exceptions
it is also possible to handle errors within an exception block like:
-- case for future dated record, open ended record
WHEN NO_DATA_FOUND THEN
BEGIN
SELECT LOAN_TYPE_HISTORY_ID
INTO l_loan_type_history_id
FROM XXHLS.XXHLS_LOAN_TYPE_HISTORY
WHERE LOAN_TYPE_CODE = i_loan_type_code
AND EFFECTIVE_END_DATE IS NULL;
RETURN l_loan_type_history_id;
EXCEPTION
WHEN OTHERS THEN
DBMS.OUTPUT(SQLERRM);
...
Take note of the SQLERRM object @A@ this contains the error message from the exception caught.
TODO: review the list of Oracle predefined exceptions
FUNCTION get_actv_loan_typ_hist_id_fn(i_loan_type_code IN XXHLS.XXHLS_LOAN_TYPE_LIST.LOAN_TYPE_CODE%TYPE)
RETURN XXHLS.XXHLS_LOAN_TYPE_HISTORY.LOAN_TYPE_HISTORY_ID%TYPE
IS
l_loan_type_history_id XXHLS.XXHLS_LOAN_TYPE_HISTORY.LOAN_TYPE_HISTORY_ID%TYPE DEFAULT NULL;
BEGIN
SELECT LOAN_TYPE_HISTORY_ID
INTO l_loan_type_history_id
FROM XXHLS.XXHLS_LOAN_TYPE_HISTORY
WHERE LOAN_TYPE_CODE = i_loan_type_code
AND SYSDATE BETWEEN
EFFECTIVE_START_DATE AND EFFECTIVE_END_DATE;
RETURN l_loan_type_history_id;
EXCEPTION
-- case for future dated record, open ended record
WHEN NO_DATA_FOUND THEN
SELECT LOAN_TYPE_HISTORY_ID
INTO l_loan_type_history_id
FROM XXHLS.XXHLS_LOAN_TYPE_HISTORY
WHERE LOAN_TYPE_CODE = i_loan_type_code
AND EFFECTIVE_END_DATE IS NULL;
RETURN l_loan_type_history_id;
END get_actv_loan_typ_hist_id_fn;
RETURN XXHLS.XXHLS_LOAN_TYPE_HISTORY.LOAN_TYPE_HISTORY_ID%TYPE
IS
l_loan_type_history_id XXHLS.XXHLS_LOAN_TYPE_HISTORY.LOAN_TYPE_HISTORY_ID%TYPE DEFAULT NULL;
BEGIN
SELECT LOAN_TYPE_HISTORY_ID
INTO l_loan_type_history_id
FROM XXHLS.XXHLS_LOAN_TYPE_HISTORY
WHERE LOAN_TYPE_CODE = i_loan_type_code
AND SYSDATE BETWEEN
EFFECTIVE_START_DATE AND EFFECTIVE_END_DATE;
RETURN l_loan_type_history_id;
EXCEPTION
-- case for future dated record, open ended record
WHEN NO_DATA_FOUND THEN
SELECT LOAN_TYPE_HISTORY_ID
INTO l_loan_type_history_id
FROM XXHLS.XXHLS_LOAN_TYPE_HISTORY
WHERE LOAN_TYPE_CODE = i_loan_type_code
AND EFFECTIVE_END_DATE IS NULL;
RETURN l_loan_type_history_id;
END get_actv_loan_typ_hist_id_fn;
it is also possible to handle errors within an exception block like:
...
EXCEPTION-- case for future dated record, open ended record
WHEN NO_DATA_FOUND THEN
BEGIN
SELECT LOAN_TYPE_HISTORY_ID
INTO l_loan_type_history_id
FROM XXHLS.XXHLS_LOAN_TYPE_HISTORY
WHERE LOAN_TYPE_CODE = i_loan_type_code
AND EFFECTIVE_END_DATE IS NULL;
RETURN l_loan_type_history_id;
EXCEPTION
WHEN OTHERS THEN
DBMS.OUTPUT(SQLERRM);
...
Take note of the SQLERRM object @A@ this contains the error message from the exception caught.
Subscribe to:
Posts (Atom)