Writing an sql query output to a File in PLSQL Package

We are developing ETL projects and sometimes we need to write output of a table or view query to a file. The problem is that for each project it should be written another package or procedure to write table or query data to a file. This is a needless operation and I decided to write a package to overcome this problem.

The package that I coded is PKG_QUERY_TO_FILE that has two public procedure to write a query’s output to a file. Example calling of the procedures are listed below:

BEGIN 

PKG_QUERY_TO_FILE.WRITE(
pv_sql_query => ‘SELECT * FROM ODS_ETL.TTA01EXTLOAD_DEFINITIONS WHERE SOURCE_SYSTEM = ”BSCS”’,
pv_disk_directory => ‘/ETLfs’,
pv_file_name => ‘extload.txt’,
pb_include_column_header => TRUE,
pv_column_header_encloser => ‘”‘,
pv_column_header_seperator => ‘;’,
pv_file_seperator => ‘,’,
pb_append_mode => FALSE,
pv_null_replacer => ‘NULL’
);

PKG_QUERY_TO_FILE.WRITE(
pv_sql_query => ‘SELECT * FROM ODS_ETL.TTA01EXTLOAD_DEFINITIONS WHERE SOURCE_SYSTEM = ”BSCS”’,
pv_disk_directory => ‘/ETLfs’,
pv_file_name => ‘extload2.txt’
);

EXECUTE IMMEDIATE ‘CREATE OR REPLACE DIRECTORY SIL_TMPDIR AS ”/ETLfs/fuat”’;
PKG_QUERY_TO_FILE.WRITE_SIMPLE(
pv_sql_query => ‘SELECT * FROM ODS_ETL.TTA01EXTLOAD_DEFINITIONS WHERE SOURCE_SYSTEM = ”BSCS”’,
pv_directory_object => ‘SIL_TMPDIR’,
pv_file_name => ‘extload3.txt’
);
EXECUTE IMMEDIATE ‘DROP DIRECTORY SIL_TMPDIR’;
END;

You can analyse, download and use free the code of PKG_QUERY_TO_FILE package, from here. You can add your log system instead DBMS_OUTPUT.

It may have some bugs if you specify that I will fix it or you can create your own generic package by using my package.

Also Thomas Kyte has written a package about this problem ( http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:95212348059 ).

Running Shell Script in PL/SQL on a RAC Environment

Sometimes we need to run shell script within the PL/SQL code. To do accompplish this we have two options :

1 ) Create a java stored class that runs shell script with Java Runtime class.
2 ) Using DBMS_SCHEDULER Oracle supplied package

When you are on second option and you work on a RAC environment you should be aware of somethings that are listed below:

1 ) Unix user who had installed the Oracle Database ( generally oracle ) should have been granted to run specified shell script. This is a requirement whether you use Oracle RAC or not.
2 ) In shell script, use exact path of supplied unix utilities instead of using its actual name. For example, if shell script use “echo” utility and you do not call explicitly profile file or set environment variables, you should specify its path exactly what it is, like “/bin/echo”.
3 ) Shell script that will be run by Oracle DB should be placed on all of the nodes with same grants. Because you do not know which node will execute the shell script.
Assume that you have 2 nodes a. Your shell script is located on /home/oracle/demoSh/demo.sh . And instance names that match nodes which are listed below :

node1 : galatats1
node2 : galatats2

By the way you can learn your instance name in your session via querying v$instance system view.

On instance2 :

[oracle@galatats02.no.turkcell.tgc]:/home/oracle/demoSh> ls -la
total 20
drwxr-xr-x 2 oracle oinstall 4096 Sep 26 01:49 .
drwx—— 6 oracle 501 4096 Sep 26 01:49 ..
-rwxr-xr-x 1 oracle oinstall 1239 Sep 26 01:49 demo.sh
-rw-r–r– 1 oracle oinstall 20 Sep 26 01:49 output.txt

In order to execute demo.sh inside the PL/SQL we are creating a DBMS_SCHEDULER job like that :

BEGIN
dbms_scheduler.create_job(
job_name => ‘DEMO’,
job_type => ‘EXECUTABLE’,
job_action => ‘/home/oracle/demoSh/demo.sh’,
start_date => SYSTIMESTAMP,
number_of_arguments=>0,
enabled => true,
auto_Drop => true,
comments => ‘Demo’);
END;

As soon as job is created, it started to run. As soon as job completed its run, it is dropped automatically. Because of auto_drop clause was set to true while job was creating. ( By the way you do not necessary to do this ). How can I check status of my job that has already dropped? You can use USER_SCHEDULER_JOB_RUN_DETAILS view to check status of all scheduler jobs that run. Also In a RAC environment you can see node that job was executed on.

If you change name of demo.sh file on node1, the job we have created above will run successfully sometimes. If you check the status code of user_scheduler_job_run_details you can see both SUCCESSFUL and FAILED status of your job. In the FAILED row you may see this in ADDITIONAL_INFO column:

ORA-27369: job of type EXECUTABLE failed with exit code: No such file or directory

So that, in order to execute shell script as successful via PL/SQL you have to obey some rules. In this article I tried to tell what they are.

Oracle CEP Bug – org.springframework.beans.TypeMismatchException

I have installed the Oracle Complex Event Processing 11.1.3. I will have described what I am doing by the end of this month. Anyway I decided to use Event
Partitioning feature to achieve scalability. When I use a channel with event partitioning feature I was getting error :

org.springframework.beans.factory.BeanCreationException: Error creating bean with name

‘inputChannel’: Invocation of init method failed; nested exception is

org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.TypeMismatchException: Failed to convert

property value of type [java.lang.String] to required type

[com.bea.wlevs.channel.EventPartitioner] for property ‘eventPartitioner’; nested exception is

java.lang.IllegalArgumentException: Cannot convert value of type [java.lang.String] to required

type [com.bea.wlevs.channel.EventPartitioner] for property ‘eventPartitioner’: no matching

editors or conversion strategy found

In CEP documentation,
( Section 19.1, “How to Configure Scalability With an Event Partitioner Channel” )

it says we could achieve scalability by putting this piece of code into channel configuration part of EPN assembly file:

<wlevs:instance-property name=”eventPartitioner” value=”true” />

However, it does not working. I created a Metalink SR and they answered me as they filed a bug about this issue(9964253).

Getting rid of this error is simple. Change name of instance-property from “eventPartitioner” to “partitionByEventProperty” and change value parameter to a varible name of your Event Class like this:

<wlevs:instance-property name=”partitionByEventProperty” value=”symbol” />

Your event class should have a “symbol” variable.

public String symbol;

SIMPLE_INTEGER as performance booster [ Comparing SIMPLE_INTEGER, PLS_INTEGER, NUMBER data types ]

I’ve given education about the Advanced features of PL/SQL in our company academy. While i was preparing the education, simple_integer data type drawn my attention. This data type introduced with Oracle 11g. I wanted to compare this data type to pls_integer and number.

If you are sure with simple_integer variable that won’t be null, you can use this data type instead of pls_integer ( Also you know that pls_integer faster than number variable because it uses the hardware calculations instead of programmatic calculations like number).

To compare this i’ve written 3 split functions that takes an in parameter and takes an out parameter that is array of splitted parts of this string.

Firstly we create a string array type :

CREATE OR REPLACE TYPE AQ_ADM_PRTP_V204.ARR_VARCHAR_100 IS TABLE OF VARCHAR2(100)
/

Secondly write 3 split functions that uses simple_integer, pls_integer, number data types respectively.

Procedure that uses simple_integer data types :

CREATE OR REPLACE PROCEDURE AQ_ADM_PRTP_V204.PROC_SPLIT_SIMPLE_INTEGER(pv_param_string VARCHAR2, strings IN OUT NOCOPY ARR_VARCHAR_100)
IS
ln_comma simple_integer := 1;
ln_next simple_integer := 1;
ln_index simple_integer := 0;
BEGIN

ln_comma := instr(pv_param_string, ‘,’, 1, 1);
WHILE (ln_comma > 0) LOOP
ln_index := ln_index + 1;
strings(ln_index) := substr(pv_param_string,
ln_next,
ln_comma – ln_next);
ln_next := ln_comma + 1;
ln_comma := instr(pv_param_string, ‘,’, ln_next, 1);
END LOOP;

ln_index := ln_index + 1;
ln_comma := length(pv_param_string) + 1;
strings(ln_index) := substr(pv_param_string, ln_next, ln_comma – ln_next);

END;
/

Procedure that uses pls_integer data types :

CREATE OR REPLACE PROCEDURE AQ_ADM_PRTP_V204.PROC_SPLIT_PLS_INTEGER(pv_param_string VARCHAR2, strings IN OUT NOCOPY ARR_VARCHAR_100)
IS
ln_comma pls_integer := 1;
ln_next pls_integer := 1;
ln_index pls_integer := 0;
BEGIN

ln_comma := instr(pv_param_string, ‘,’, 1, 1);
WHILE (ln_comma > 0) LOOP
ln_index := ln_index + 1;
strings(ln_index) := substr(pv_param_string,
ln_next,
ln_comma – ln_next);
ln_next := ln_comma + 1;
ln_comma := instr(pv_param_string, ‘,’, ln_next, 1);
END LOOP;

ln_index := ln_index + 1;
ln_comma := length(pv_param_string) + 1;
strings(ln_index) := substr(pv_param_string, ln_next, ln_comma – ln_next);

END;
/

Procedure that uses number data types :

CREATE OR REPLACE PROCEDURE AQ_ADM_PRTP_V204.PROC_SPLIT_NUMBER(pv_param_string VARCHAR2, strings IN OUT NOCOPY ARR_VARCHAR_100)
IS
ln_comma NUMBER := 1;
ln_next NUMBER := 1;
ln_index NUMBER := 0;
BEGIN

ln_comma := instr(pv_param_string, ‘,’, 1, 1);
WHILE (ln_comma > 0) LOOP
ln_index := ln_index + 1;
strings(ln_index) := substr(pv_param_string,
ln_next,
ln_comma – ln_next);
ln_next := ln_comma + 1;
ln_comma := instr(pv_param_string, ‘,’, ln_next, 1);
END LOOP;

ln_index := ln_index + 1;
ln_comma := length(pv_param_string) + 1;
strings(ln_index) := substr(pv_param_string, ln_next, ln_comma – ln_next);

END;
/

After those we write test cases :

DECLARE

ln_iteration_no SIMPLE_INTEGER := 1000000;
strings ARR_VARCHAR_100 := ARR_VARCHAR_100();
ln_temp VARCHAR2(1000);
ln_time1 NUMBER;
ln_time2 NUMBER;
ln_time3 NUMBER;
ln_time4 NUMBER;
BEGIN

strings.extend(47);
ln_temp :=

’2000,2,123553168,1,10,64895,65535,27662,64860,64895,65535,27662,64860,0,,,,,,0,0,2491039806,,,,,,,,,0,0,1,,24910391

06,,,,,,,’ ||
’1′ || ‘,,,,,’;

ln_time1 := DBMS_UTILITY.GET_TIME;
FOR i IN 1..ln_iteration_no
LOOP

proc_split_simple_integer(ln_temp,strings);

END LOOP;
ln_time2 := DBMS_UTILITY.GET_TIME;
FOR i IN 1..ln_iteration_no
LOOP

proc_split_pls_integer(ln_temp,strings);

END LOOP;
ln_time3 := DBMS_UTILITY.GET_TIME;
FOR i IN 1..ln_iteration_no
LOOP

proc_split_number(ln_temp,strings);

END LOOP;
ln_time4 := DBMS_UTILITY.GET_TIME;

DBMS_OUTPUT.PUT_LINE(‘Total Duration of proc_split_simple_integer procedure is : ‘||((ln_time2-ln_time1)/100)||

‘ seconds.’);
DBMS_OUTPUT.PUT_LINE(‘Total Duration of proc_split_pls_integer procedure is : ‘||((ln_time3-ln_time2)/100)|| ‘

seconds.’);
DBMS_OUTPUT.PUT_LINE(‘Total Duration of proc_split_number procedure is : ‘||((ln_time4-ln_time3)/100)|| ‘

seconds.’);

END;

results :

Total Duration of proc_split_simple_integer procedure is : 16,7 seconds.
Total Duration of proc_split_pls_integer procedure is : 18,6 seconds.
Total Duration of proc_split_number procedure is : 33,19 seconds.

In this example, SIMPLE_INTEGER data type is faster twice time than NUMBER data type.

If you do not use the native compilation method, you could see much time of previous results. Notice that as specified in document, if you do not use native compilation, procedure that uses simple_integer variable takes much time of pls_integer.

Interpreted compilation results :

Total Duration of proc_split_simple_integer procedure is : 29,1 seconds.
Total Duration of proc_split_pls_integer procedure is : 27,24 seconds.
Total Duration of proc_split_number procedure is : 46,42 seconds.

SIMPLE_INTEGER slower than PLS_INTEGER when you are not using NATIVE compilation method.

To get more information about NATIVE and INTERPRETED compilation, here.

Automatically Backuping Apex Applications

Automatically Backuping Apex Applications

We can export our apex applications as an sql file in “Home>Application Builder>Application $ID>Export / Import>Export” menu. You can do this as manually, so if you want to backup your apex application(s) you should do this for each time for each application.

As you guess this operation runs a plsql command in background to export application.

“wwv_flow_utilities” public package of apex, includes “export_application_to_clob” function that returns clob variable that containts sql statements. These sql statements those are application metadata that will be imported your workspace. Spec part of function is below :

function export_application_to_clob (
p_application_id in number,
p_export_saved_reports in varchar2 default ‘N’)
return clob
;

Application ID is a number that user specified or automatically got from apex. That is on right of f?p= parameter of url string. You should specify application id to export application. Another parameter is p_export_saved_reports is optional, if you want to export saved report you can set this as ‘Y’.

You can write a dbms_scheduler job that runs this plsql for every specified interval time. Or you can write a unix shell script that produces an sql file, put this shell script to crontab to run this backup operations for every specified interval time. Or anything else…

Also you can export only a page of an application, this function is under wwv_flow_utilities package too, spec part of this :

function export_page_to_clob (
p_application_id in number,
p_page_id in number)
return CLOB
;

Example :

CREATE TABLE EXPORT_CLOB
(
APP_EXPORT CLOB
);

BEGIN

INSERT INTO EXPORT_CLOB
VALUES (WWV_FLOW_UTILITIES.EXPORT_APPLICATION_TO_CLOB(’107′));

END;

SELECT length(app_export) FROM EXPORT_CLOB;

954956

To backup your all of applications you can get application id from “select * from apex_applications”.

This example was tested on Oracle 11.1.0.6 and Apex 3.2.

Apex Interactive Reports with Dynamic Sql

Interactive Reports in Apex, presents too many features that will be performed on reports. You can apply specified column filtering, highlighted specified values in a column, use aggregation functions, ajax paginations are some of these features. To use these features you can create a report region as Interactive report ( In a page attributes, Create Region > Report > Interactive Report ).

While creating Interactive Reports, apex wants from you an sql word. It must be pure sql unlike varchar2 variable that stores sql ( in standart reports you can use a varchar2 variable that stores sql. For example lv_dynamic_sql := ‘SELECT EMP_NO FROM EMPLOYEE’; return lv_dynamic_sql; ). So in normally you can’t use dynamic sql in interactive report. I said “in normally” :)

By using PIPELINED FUNCTIONS you can use dynamic sql in Apex Interactive Reports.

In Interactive Reports, you will specify sql as “SELECT * FROM TABLE(table_function);”

After that you should design your “table_function()” function.

First of all you should create an object type that matches a report row fields.

CREATE OR REPLACE TYPE OBJ_STREAM_FILTERED AS OBJECT
(
a_rowid VARCHAR2(100),
ActivationType VARCHAR2(100),
ActivationCellCgi VARCHAR2(100),
TerminationCellCgi VARCHAR2(100),
IMSI VARCHAR2(100),
IMEI_TAC VARCHAR2(100),
IMEI_LAC VARCHAR2(100),
ActivationSec VARCHAR2(100),
OriginationCellCgi VARCHAR2(100),
TargetCellCgi VARCHAR2(100),
ENQ_DATE DATE,
INSERT_DATE DATE,
REMOTE_HOST VARCHAR2(100),
IMEI VARCHAR2(100),
MSISDN_NUMBER VARCHAR2(100),
GENERAL_SEGMENT VARCHAR2(100),
GENERAL_SUB_SEGMENT VARCHAR2(100)
)
/

Your report fields should match these object type fields.

After that you should design your “table_function” function.

CREATE OR REPLACE FUNCTION AQ_ADM_PRTP_V204.get_table_rows2(p_table_name VARCHAR2)
RETURN OBJ_STREAM_FILTERED_ARR
PIPELINED IS
out_rec OBJ_STREAM_FILTERED := OBJ_STREAM_FILTERED(NULL,
null,
NULL,
NULL,
null,
null,
null,
null,
null,
null,
null,
null,
null,
NULL,
NULL,
NULL,
NULL);
p sys_refcursor;

v0 VARCHAR2(100);
v1 VARCHAR2(100);
v2 VARCHAR2(100);
v3 VARCHAR2(100);
v4 VARCHAR2(100);
v5 VARCHAR2(100);
v6 VARCHAR2(100);
v7 VARCHAR2(100);
v8 VARCHAR2(100);
v9 VARCHAR2(100);
v10 VARCHAR2(100);
v11 VARCHAR2(100);
v12 VARCHAR2(100);
v13 VARCHAR2(100);
v14 VARCHAR2(100);
v15 VARCHAR2(100);
v16 VARCHAR2(100);
t1 TIMESTAMP(6);
t2 TIMESTAMP(6);
BEGIN
OPEN p FOR ‘SELECT
t.rowid,
t.*,
t2.imei,
t2.msisdn_number,
t2.general_Segment,
t2.general_sub_segment
FROM
‘ || p_table_name || ‘ t,
syn_rds_imsi_info t2
WHERE
CONCAT(CONCAT(column15,column16),column17) = t2.IMSI(+)’;
LOOP
FETCH p
INTO v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, t1, t2, v12, v13, v14, v15, v16;
EXIT WHEN p%NOTFOUND;
out_rec.a_rowid := v0;
out_rec.ActivationType := v1;
Out_rec.ActivationCellCgi := v2;
out_rec.TerminationCellCgi := v3;
out_rec.IMSI := v4 || v5 || v6;
out_rec.IMEI_TAC := v7;
out_rec.IMEI_LAC := v8;
out_rec.OriginationCellCgi := v10;
out_rec.TargetCellCgi := v11;
out_rec.ActivationSec := v9;
out_rec.ENQ_DATE := t1;
out_rec.INSERT_DATE := t2;
out_rec.REMOTE_HOST := v12;
out_rec.IMEI := v13;
out_rec.MSISDN_NUMBER := v14;
out_rec.GENERAL_SEGMENT := v15;
out_rec.GENERAL_SUB_SEGMENT := v16;
PIPE ROW(out_rec);
END LOOP;
CLOSE p;
RETURN;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.format_error_backtrace);
DBMS_OUTPUT.PUT_LINE(SQLCODE);
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/

You can check this function accuracy:

SELECT * FROM TABLE(get_table_rows2(‘galata_report.FUAT123′));

Anymore, there is no need to do anything to use this sql in interactive report.

If you get an uniquely related error you can specify a unique column ( a_rowid in this example ) in Report Attributes > Link Column section.

Edited on 05.10.2010 :
There is a better solution to handle more dynamic sql. Which means that you can prepare dynamic interactive report for any sql. Those sqls do not need to has same number of columns or same column names. It is demonstrated at http://www.oracleapplicationexpress.com/tutorials/71 .

Solution of “ORA-25307: Enqueue rate too high”

One of the method of to speed up the performance of Oracle Advanced Queue is using Buffered Messages. In default, maxiumum 5000 non-dequeued messages can reside in memory. If you enqueued more than 5000 messages that have not dequeued yet, you will get an error like : “ORA-25307: Enqueue rate too high”. So, your messages will be written to disk.

Oracle uses this error to prevent memory overflow when you are enqueuing messages. You can increase this number by setting a system parameter.

SQL> alter system set “_buffered_publisher_flow_control_threshold”=500000 scope=both;

System altered

SQL> show parameter buffered;

NAME TYPE VALUE
———————————— ———– ——————————
_buffered_publisher_flow_control_threshold integer 500000

SQL>

After that, you can observe how many messages were spilled to the disk:

SQL> select queue_name,subscriber_name,total_spilled_msg
2 from
3 v$buffered_subscribers
4 ;

QUEUE_NAME SUBSCRIBER_NAME TOTAL_SPILLED_MSG
—————————— —————————— —————–
NLIZT01_STREAM_Q NLIZT01 0
NLCR01_STREAM_Q NLCR01 0
NLER01_STREAM_Q NLER01 0
NLER03_STREAM_Q NLER03 0
NLER02_STREAM_Q NLER02 0
NLCR03_STREAM_Q NLCR03 0
NLCR02_STREAM_Q NLCR02 0
NLIZT03_STREAM_Q NLIZT03 0
NLIZT02_STREAM_Q NLIZT02 0
NLBRS03_STREAM_Q NLBRS03 0
NLBRS02_STREAM_Q NLBRS02 0
NLBRS01_STREAM_Q NLBRS01 0
NLBLK03_STREAM_Q NLBLK03 0
NLBLK02_STREAM_Q NLBLK02 0
NLBLK01_STREAM_Q NLBLK01 0

15 rows selected

SQL>

If you use dbms_capture package, you can use :
alter system set “_capture_publisher_flow_control_threshold”=500000 scope=both;

About Oracle Date and useful functions

Oracle has powerful date functions. Sometimes you need to convert it to another type or another type has to be converted to date type or you need trunc date to display only part of date or anything else.

So, you can lots of things on date type. I will try to tell some useful operations on date types.

Date type placed as 7 bytes on disk. It stores year, month, day, hour, minute, second. Timestamp type placed as 11 bytes. And it stores addition to date fraction of seconds and time zone information. Especially, it is useful for real time applications to measure where does the time pass. ( because of I used this type )

For example for 15.05.2009 18:01:00, Oracle do not store it as how it was written. It is stored as a different internal style as 7 bytes and this style of storing is advantageous when you trunc or convert it to another type or sort date datas.

Formatting date is useful and necessary. When you rely on the default date format, your application may be in the future affected negatively ( I have experienced it twice :) ).

First and most known function is to_date and to_char functions.
For DATE type, you can convert this date type to char :

TO_CHAR(date,’DATEFORMAT’);
If you do not specify the date format, your date type will be trunced.

SQL> select to_Char(sysdate) from dual;

TO_CHAR(SYSDATE)
—————-
10/06/2009

What is the date format? What part of dates can be specified?
There are lots of documents on web that mentions about it and i don’t repeat it
( Oracle Date Parts that can be extracted ). Most known and used of them are DD, MM, YYYY, HH24, HH, MI, SS.

For example :

SQL> select to_Char(sysdate,’DD/MM/YYYY HH24:MI:SS’) from dual;

TO_CHAR(SYSDATE,’DD/MM/YYYYHH2
——————————
10/06/2009 23:39:39

So far, we saw that how date type can be converted to char. Inversely, convert char to date is similar to it.

SQL> select to_date(’12:00:00 04.06.2009′,’HH24:MI:SS DD.MM.YYYY’) from dual;

TO_DATE(’12:00:0004.06.2009′,’
——————————
6/4/2009 12:00:00 PM

Date Arithmetics and Useful other Date functions:

Adding X days to a date you use “datevariable + 1″ : SYSDATE + 1
Adding X seconds to a date you use “datevariable + 1/(24*60*60)” : SYSDATE + 1/(24*60*60)
Another adding or substracting operations you can use your mind :)

Adding months you can use ADD_MONTHS(variable,#months):

SQL> select sysdate, add_months(sysdate,1), add_months(add_months(sysdate,1),1) from dual;

SYSDATE ADD_MONTHS(SYSDATE,1) ADD_MONTHS(ADD_MONTHS(SYSDATE,
———– ——————— ——————————
6/10/2009 1 7/10/2009 11:55:22 PM 8/10/2009 11:55:22 PM

Format is : MONTH DAY YEAR HH24 MI SS

No difference, if current month has 30 or 31 days only month number will increase 1. If we are in the 30 January, according to year add_months(date,1) will return 28-Feb or 29-Feb.

Months_Between :

SQL> select months_between(sysdate+75,sysdate) from dual;

MONTHS_BETWEEN(SYSDATE+75,SYSD
——————————
2.45161290322581

You can trunc it to 2.

First Day Of Month :

SQL> SELECT TO_CHAR(TRUNC(SYSDATE,’MONTH’),’DAY’) FROM DUAL;

TO_CHAR(TRUNC(SYSDATE,’MONTH’)
——————————
MONDAY

Last Day Of Month :

SQL> SELECT TO_CHAR(LAST_DAY(SYSDATE),’DAY’) FROM DUAL;

TO_CHAR(LAST_DAY(SYSDATE),’DAY
——————————
TUESDAY

When next first Friday :

SQL> SELECT TO_CHAR(NEXT_DAY(SYSDATE,’FRIDAY’),’DD’) FROM DUAL;

TO_CHAR(NEXT_DAY(SYSDATE,’FRID
——————————
12

First day of Month

SQL> SELECT TO_CHAR(LAST_DAY(add_months(SYSDATE,-1))+1,’DAY’) FROM DUAL;

TO_CHAR(LAST_DAY(ADD_MONTHS(SY
——————————
PAZARTESI

Now, which # of week we are in :

SQL> select to_Char(sysdate,’IW’) from dual;

TO_CHAR(SYSDATE,’IW’)
———————
24
SQL>

EXTRACT
To extract specified date part from date or timestamp variable. Alternative way is convert date to char and perform substr operation. Former takes less time than latter.

EXTRACT (
{ YEAR | MONTH | DAY | HOUR | MINUTE | SECOND }
| { TIMEZONE_HOUR | TIMEZONE_MINUTE }
| { TIMEZONE_REGION | TIMEZONE_ABBR }
FROM { date_value | interval_value } )

SQL> select extract(hour from systimestamp)||’:'||extract(minute from systimestamp)||’:'||extract(second from systimestamp) from dual;

EXTRACT(HOURFROMSYSTIMESTAMP)|
——————————————————————————–
7:40:7,142039

HOUR, SECOND, MINUTE, TIMEZONE_HOUR, TIMEZONE_MINUTE can be extracted only timestamp.

A number that how many days, hours, minutes, seconds : NUMTODSINTERVAL(num,):

SQL> select numtodsinterval(1440,’MINUTE’) FROM DUAL;

NUMTODSINTERVAL(1440,’MINUTE’)
——————————
+000000001 00:00:00

1440 minutes equals to 1 day ( leftmost piece ).

SQL> SELECT NUMTODSINTERVAL(3602,’SECOND’) FROM DUAL;

NUMTODSINTERVAL(3602,’SECOND’)
——————————
+000000000 01:00:02

3602 seconds equals to 1 hour 2 seconds.

About NLS_DATE

To set default date format for session based.

SQL> ALTER SESSION SET NLS_DATE_FORMAT = ‘YYYY MM DD’;

Session altered

SQL> select sysdate from dual;

SYSDATE
———–
6/17/2009 1

SQL>

Converting unix timestamp to Oracle in PL/SQL
This is may useful your application to convert unix timestamp to oracle date.
Read this post
( Responsibility of adding or subtracting GMT is belong to you )

Another DATE functions :

# NUMTOYMINTERVAL, converts a NUMBER or expression into a YEAR TO MONTH interval.
# TO_DSINTERVAL converts string to DAY TO SECOND interval.
# TO_YMINTERVAL converts a character string to YEAR TO MONTH type

Log4PL/SQL – Log Api For PL/SQL

Log4PL/SQL

In some situations you need to developed big applications with PL/SQL. And you want to see that what operations were executed so far and which of them caused an error? May be you want to logged exception blocks to solve your application leaks, logged other informations to debug your application. To perform all of these you can use Log4PL/SQL api.

It is similar to Log4J and logged various information about your application. It is a PL/SQL package. If you want, you can logged only specific information for example, you can log only exception or all information. You can select log level to perform this operation. You may use this package in your code but if you don’t want to log anymore, you can disable logging only by changing a little piece of code.

An Example:

DECLARE

ln_count NUMBER;

pCTX PLOG.LOG_CTX := PLOG.init(pSECTION     => ‘RTDF’,

pLEVEL       => PLOG.LALL,

pLOG4J       => FALSE,

pLOGTABLE    => TRUE,

pOUT_TRANS   => TRUE,

pALERT       => FALSE,

pTRACE       => FALSE,

pDBMS_OUTPUT => FALSE);

BEGIN

SELECT COUNT(*) INTO ln_count FROM ALL_OBJECTS WHERE OBJECT_NAME = ‘TLEVEL’ AND OBJECT_TYPE = ‘TABLE’;

IF ( ln_count > 0 ) THEN

PLOG.info(pctx, ‘Table is exist.’);

ELSE

PLOG.info(pctx, ‘Table is exist.’);

END IF;

EXCEPTION

WHEN OTHERS THEN

plog.error;

plog.full_call_stack;

END;

SELECT * FROM TLOG

SELECT * FROM VLOG — This view only one column that consists of columns of tlog and only includes last 24 record. You can edit view sql to show more records.

For more information, visit Log4PL/SQL Homepage.

Pairing Java objects with Oracle Types

When you send your java object variables to Oracle, you can divide objects into attributes, then send them to database. It makes no sense and takes much development time than sending directly as object. Before sending java object to oracle, you should do some steps.

1 ) Firstly, you should set up your java objects.

> Import java.sql.SQLData, SQLException, SQLInput, SQLOutput classes to your object class
> Your class implements SQLData Interface but not necessary
> readSql, writeSql, getSqlTypeName methods must be declared and they process (read or write) class variables

import java.sql.SQLData;
import java.sql.SQLException;
import java.sql.SQLInput;
import java.sql.SQLOutput;

/**
*
* @author TTASUNGUR
*/
public class StreamType implements SQLData
{

private String sql_type;
public String dataType = “”;
public String activation_Type = “”;

public
StreamType()
{
}

public
StreamType(String sql_type)
{
this.sql_type = sql_type;
}

public void readSQL(SQLInput inStream, String typeName) throws
SQLException
{

sql_type = typeName;
dataType = inStream.readString();
activation_Type = inStream.readString();
// this order should be similar to defining order

}

public void writeSQL(SQLOutput outStream) throws SQLException
{
outStream.writeString(dataType);
outStream.writeString(activation_Type);
// this order should be similar to defining order

}

public
String getSQLTypeName() throws SQLException
{
return sql_type;
}
}

2 ) You should create Oracle type that will be matched your java object :

CREATE OR REPLACE TYPE stream_type AS OBJECT
(
dataType VARCHAR2(50),
activation_Type VARCHAR2(50)
);

3 ) There should be mapping java object to oracle object.

java.util.Map myMap = (Map)conn.getTypeMap(); // conn is a Connection object, Map class casts it ( also Map class should be imported your java class )
myMap.put(oracle_gb_file_type, Class.forName(“nor.GB_File”));

4 ) If your new object is ready for sending database, you can pass it to a statement object.

StreamType st = new StreamType();
st.dataType = “foo”;
st.activation_Type = “foo2″;
CallableStatement cstmt = conn.prepareCall(“{ call AQ_ADM_PRTP.AQ_PRTP.ENQUEUE_STREAM_TYPE(?) }”); //plsql procedure that gets StreamType type that has already created in Database
cstmt.setObject(1,st,OracleTypes.STRUCT);

Other link(s):
> Working with Oracle Objects : http://download.oracle.com/docs/cd/B19306_01/java.102/b14355/oraoot.htm

Follow

Get every new post delivered to your Inbox.