Archive for the ‘Oracle’ Category
Oracle VM.
Oracle just announced the release of Oracle Virtualization software, Oracle VM. It sounds all great and fun but it needs two machines, one for installing the server and another for managing it. I don’t have two machines for this. I have two machines but this approach seems like a little too much effort for “virtualization”. How does this make it simple. I am sticking with VMWare for now.
Oracle timestamp in Informatica
To extract values from an oracle table column of timestamp datatype, you need to convert it to a character datatype since the Oracle Timestamp datatype is not currently supported by PowerCenter. To extract the value do the following.
SQL> insert into tst1 values (current_timestamp);
1 row created.
SQL> /
1 row created.
SQL> /
1 row created.
SQL> /
1 row created.
SQL> /
1 row created.
SQL> commit;
Commit complete.
SQL> select * from tst1;
TMSTMP
————————————————-
10-SEP-07 02.44.14.807930 PM
10-SEP-07 02.44.16.700373 PM
10-SEP-07 02.44.17.357597 PM
10-SEP-07 02.44.18.163876 PM
10-SEP-07 02.44.18.685926 PM
SQL> select tmstmp, to_char(tmstmp,’YYYY-MM-DD HH:MM:SS.FF6′) as CHAR_TMSTMP from tst1;
TMSTMP CHAR_TMSTMP
—————————- ————————–
10-SEP-07 02.44.14.807930 PM 2007-09-10 02:09:14.807930
10-SEP-07 02.44.16.700373 PM 2007-09-10 02:09:16.700373
10-SEP-07 02.44.17.357597 PM 2007-09-10 02:09:17.357597
10-SEP-07 02.44.18.163876 PM 2007-09-10 02:09:18.163876
10-SEP-07 02.44.18.685926 PM 2007-09-10 02:09:18.685926
The resultant column CHAR_TMSTMP in the output of the query is now ready to be extracted in a mapping.
Hope this helps…
Kirtan
Pivot Query
So how to pivot data in a table?
I was asked about this by someone at work today. Let’s say you have a table that looks like following. I have included create and insert statements so that you can see it and understand it yourself.
Create table t1 (a number, b number);
insert into t1 values (1,1);
insert into t1 values (1,2);
insert into t1 values (1,3);
insert into t1 values (2,1);
insert into t1 values (2,2);
insert into t1 values (2,3);
insert into t1 values (3,1);
insert into t1 values (3,2);
insert into t1 values (3,3);
select * from t1 order by 1,2;
####
(A hint aside: You must specify the order in which you want the data to be back. It is completely wrong to say that oracle will return the data in order it was inserted.)
####
A B
----- ------
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
Now, let’s say you want to retrieve all the records from table t1 in a fashion where all the values in column B that belong to the group Column A should be shown side by side. Something like
A Val1 Val2 Val3
-- ---- ---- ----
1 1 2 3
One way would be to write a procedural code that stores different values of a group in an array or a series of variables and then displays them on screen or returns them to the calling program.
Or
You could just write a simple SQL statement that does it for you. You could write a piece of code that looks like this…
select
a
,max(decode(b,1,b,null)) col1
,max(decode(b,2,b,null)) col2
,max(decode(b,3,b,null)) col3
from t1
group by a;
A COL1 COL2 COL3
—– ——- ——- ——-
1 1 2 3
2 1 2 3
3 1 2 3
3 rows selected
… and you won’t have to worry about supporting an object such as a function or a procedure.
What if you had null values in one of the columns.
update t1 set b=null where a=2 and b=2;
One row updated
select
a
,max(decode(b,1,b,null)) col1
,max(decode(b,2,b,null)) col2
,max(decode(b,3,b,null)) col3
from t1
group by a;
A COL1 COL2 COL3
—– ——- ——- ——-
1 1 2 3
2 1 3
3 1 2 3
3 rows selected
There are many ways to write pivot queries. This is probably the easiest way of doing it.
Using Informatica to perform pivot operation.
You can use the Normalizer Transformation to generate rows out of columns. But to pivot values in rows into columns you would have to use Aggregator Transformation. You have to use the *FIRST* or *LAST* function to achieve this. First or last functions will pick first or last of the incoming rows if there are duplicates. Here is an example…
Suppose you have a source table with this data that is a record of monthly expenses for each of your departments. create table deptexp (sales_id number(5), mon char(3), amt number(10,2));
insert into deptexp values (1,’JAN’,100);
insert into deptexp values (1,’FEB’,120);
insert into deptexp values (1,’MAR’,135);
insert into deptexp values (2,’JAN’,110);
insert into deptexp values (2,’FEB’,130);
insert into deptexp values (2,’MAR’,120);
Commit;
You want to load this data after denormalizing it into this structure.
create table deptexp1 (DEPT_ID number(5), JAN_AMT number(10,2), FEB_AMT number(10,2), MAR_AMT number(10,2))
The data after our process would look like…
DEPT_ID JAN_AMT FEB_AMT MAR_AMT
1 100 120 135
2 110 130 120
Do the following to accomplish this.
1. Create an Aggregator transformation with the following ports and expressions:
NAME IN/OUT EXPRESSION GROUP BY 2. Connect the DEPT_ID, MONTH and the AMOUNT ports from the Source Qualifier to the Aggregator.
DEPT_ID IN YES
MONTH IN NO
AMOUNT IN NO
JAN_AMT OUT FIRST(AMOUNT, MONTH='JAN')
FEB_AMT OUT FIRST(AMOUNT, MONTH='FEB')
MAR_AMT OUT FIRST(AMOUNT, MONTH='MAR')
APR_AMT OUT FIRST(AMOUNT, MONTH='APR')
3. Connect the JAN_AMT, FEB_AMT, MAR_AMT, etc. ports to the target.
And that would do it…
Hope this helps…
Kirtan
Analytic functions:
Analytic functions:
All my findings regarding analytic functions will go in this post. In other words I will keep on adding my finding to this post instead of creating new one all the time. I will also make sure that everytime when I update this post I bring up to the top of the list so that people notice the change.
Below is a small but sweet example that shows the difference between using three different functions.
DENSE_RANK()
RANK()
ROW_NUMBER()
create table t1 (
a number,
b varchar2(10)
);
insert into t1 values (5, ‘ABC’);
insert into t1 values (6, ‘ABC’);
insert into t1 values (5, ‘ABC’);
insert into t1 values (3, ‘ABC’);
insert into t1 values (5, ‘ABC’);
insert into t1 values (3, ‘ABC’);
insert into t1 values (6, ‘ABC’);
insert into t1 values (4, ‘XYZ’);
insert into t1 values (8, ‘XYZ’);
insert into t1 values (4, ‘XYZ’);
insert into t1 values (8, ‘XYZ’);
insert into t1 values (4, ‘XYZ’);
commit;
SQL> select * from t1;
A B
———- ———-
5 ABC
6 ABC
5 ABC
3 ABC
5 ABC
3 ABC
6 ABC
4 XYZ
8 XYZ
4 XYZ
8 XYZ
A B
———- ———-
4 XYZ
12 rows selected.
SQL> select dense_rank() over (partition by b order by a) “denserank”,
rank() over (partition by b order by a) “rank”,
row_number() over (partition by b order by a) “rownumber”,
a,b
from t1;
denserank rank rownumber A B
———- ———- ———- ———- ———-
1 1 1 3 ABC
1 1 2 3 ABC
2 3 3 5 ABC
2 3 4 5 ABC
2 3 5 5 ABC
3 6 6 6 ABC
3 6 7 6 ABC
1 1 1 4 XYZ
1 1 2 4 XYZ
1 1 3 4 XYZ
2 4 4 8 XYZ
denserank rank rownumber A B
———- ———- ———- ———- ———-
2 4 5 8 XYZ
12 rows selected.
SQL>
Hope this helps.
Kirtan
##### UPDATES BELOW #####
The example below uses MAX() function to show highest salary in each department right next to each employee record. It also shows what an employee’s salary is compared to the highest salary in the department.
Here the key is (PARTITION BY DEPTNO) part of the analytic function. That’s what tells oracle to break data up based on the partition details.
SQL> SELECT
ENAME,
SAL,
DEPTNO,
MAX(SAL) OVER (PARTITION BY DEPTNO) MGR_SAL_BY_DEPT,
sal/MAX(SAL) OVER (PARTITION BY DEPTNO) *100 EMP_percent_SAL
FROM EMP
ORDER BY DEPTNO;
ENAME SAL DEPTNO MGR_SAL_BY_DEPT EMP_PERCENT_SAL
———- ———- ———- ————— —————
CLARK 2450 10 5000 49
KING 5000 10 5000 100
MILLER 1300 10 5000 26
JONES 2975 20 3000 99.1666667
FORD 3000 20 3000 100
ADAMS 1100 20 3000 36.6666667
SMITH 800 20 3000 26.6666667
SCOTT 3000 20 3000 100
WARD 1250 30 2850 43.8596491
TURNER 1500 30 2850 52.6315789
ALLEN 1600 30 2850 56.1403509
JAMES 950 30 2850 33.3333333
BLAKE 2850 30 2850 100
MARTIN 1250 30 2850 43.8596491
14 rows selected.
SQL>
Now by adding one more MAX() function to the query we can have max salary across departments and a comparision of what an empolyee is making compared to the maximum salary across all departments.
SQL> SELECT
ENAME, SAL,DEPTNO,
MAX(SAL) OVER (PARTITION BY DEPTNO) max_dept_sal
,sal/MAX(SAL) OVER (PARTITION BY DEPTNO) *100 dept_percent
,MAX(SAL) OVER () max_comp_sal
,sal/MAX(SAL) OVER () *100 comp_percent
FROM EMP
ORDER BY DEPTNO;
ENAME SAL DEPTNO MAX_DEPT_SAL DEPT_PERCENT MAX_COMP_SAL COMP_PERCENT
———- ———- ———- ———— ———— ———— ————
CLARK 2450 10 5000 49 5000 49
KING 5000 10 5000 100 5000 100
MILLER 1300 10 5000 26 5000 26
JONES 2975 20 3000 99.1666667 5000 59.5
FORD 3000 20 3000 100 5000 60
ADAMS 1100 20 3000 36.6666667 5000 22
SMITH 800 20 3000 26.6666667 5000 16
SCOTT 3000 20 3000 100 5000 60
WARD 1250 30 2850 43.8596491 5000 25
TURNER 1500 30 2850 52.6315789 5000 30
ALLEN 1600 30 2850 56.1403509 5000 32
ENAME SAL DEPTNO MAX_DEPT_SAL DEPT_PERCENT MAX_COMP_SAL COMP_PERCENT
———- ———- ———- ———— ———— ———— ————
JAMES 950 30 2850 33.3333333 5000 19
BLAKE 2850 30 2850 100 5000 57
MARTIN 1250 30 2850 43.8596491 5000 25
14 rows selected.
SQL>
##############UPDATES ###################
example showing the use of LAG and LEAD functions. Here, LAG is used for reading rows before the current row and LEAD is used for reading rows after the current row. Example below shows the difference between salaries of row and its previous row and row and its next row. The key here would be the ORDER BY clause in the OVER() section of the analytic function.
SQL> SELECT
2 EMPNO,
3 ENAME,
4 JOB,
5 SAL,
6 LAG(sal, 1, 0) OVER (ORDER BY sal) AS sal_prev,
7 sal - LAG(sal, 1, 0) OVER (ORDER BY sal) AS LAG_sal_diff,
8 LEAD(sal, 1, 0) OVER (ORDER BY sal) AS sal_NEXT,
9 sal - LEAD(sal, 1, 0) OVER (ORDER BY sal) AS LEAD_sal_diff
10 FROM
11 EMP;
EMPNO ENAME JOB SAL SAL_PREV LAG_SAL_DIFF SAL_NEXT LEAD_SAL_DIFF
---------- ---------- --------- ---------- ---------- ------------ ---------- -------------
7369 SMITH CLERK 800 0 800 950 -150
7900 JAMES CLERK 950 800 150 1100 -150
7876 ADAMS CLERK 1100 950 150 1250 -150
7521 WARD SALESMAN 1250 1100 150 1250 0
7654 MARTIN SALESMAN 1250 1250 0 1300 -50
7934 MILLER CLERK 1300 1250 50 1500 -200
7844 TURNER SALESMAN 1500 1300 200 1600 -100
7499 ALLEN SALESMAN 1600 1500 100 2450 -850
7782 CLARK MANAGER 2450 1600 850 2850 -400
7698 BLAKE MANAGER 2850 2450 400 2975 -125
7566 JONES MANAGER 2975 2850 125 3000 -25
EMPNO ENAME JOB SAL SAL_PREV LAG_SAL_DIFF SAL_NEXT LEAD_SAL_DIFF
---------- ---------- --------- ---------- ---------- ------------ ---------- -------------
7788 SCOTT ANALYST 3000 2975 25 3000 0
7902 FORD ANALYST 3000 3000 0 5000 -2000
7839 KING PRESIDENT 5000 3000 2000 0 5000
14 rows selected.
SQL>
COALESCE
COALESCE is one of many convenient ways provided by oracle to handle NULL values in the database. The Oracle COALESCE function accepts a varying length list of arguments and returns the first non-NULL value/expr in the list. If all arguments in the list evaluate to a NULL value, then the COALESCE function will return a NULL value. Instead of scanning through all the arguments, oracle takes a short-circuit evaluation approach to processing what’s provided. In other words, it evaluates each expr value and determines whether it is NULL, rather than evaluating all of the expr values before determining whether any of them is NULL. As soon as it find the first non-NULL value it will stop processing rest of the provided arguments.
There is always more than one way to achieve the same outcome. You can use COALESCE as a variety of the CASE or DECODE expression.
For example,
Using DECODE, you would do something like
SELECT DECODE(mgr, NULL, 9999, mgr) FROM SCOTT.EMP
OR
Using CASE, you would do something like
SELECT
CASE
WHEN MGR IS NULL THEN
9999
ELSE
MGR
END
FROM SCOTT.EMP;
The following demonstrates how to substitute in a default value in a SELECT statement when there are NULL values present using COALESCE function.
SELECT COALESCE(mgr, 9999) FROM SCOTT.EMP;
The statement above looks much cleaner, well at least to everyone who knows what’s going on. In examples above, 9999 is a default value that you would like to assign to any null values in the list.
But a better use of COALESCE would be when more than 1 value is passed to it as input.\
For example,
SQL> select coalesce(null,null, 5, null) from dual;
COALESCE(NULL,NULL,5,NULL)
--------------------------
5
SQL> select coalesce(null,5,null,10, null) from dual;
COALESCE(NULL,5,NULL,10,NULL)
-----------------------------
5
SQL> select coalesce(null, null, null, null,555) from dual;
COALESCE(NULL,NULL,NULL,NULL,555)
---------------------------------
555
SQL>
As you can notice COALESCE picks up the first non-null value from a given list.
hope this helps.
Kirtan
Name Parser
There was a question asked on InformaticaDevelopement yahoo group about parsing names. I had a piece of code saved from asktom. I don’t know when I got it from asktom, but I know I got it from asktom. I just wanted to put it out here for reference. To parse names you would have to do the following.
SQL>create table name_test ( a varchar2(15) );
Table created.SQL>insert into name_test values ( 'kirtan' );
1 row created.
SQL>insert into name_test values ( 'kirtan desai' );
1 row created.
SQL>insert into name_test values ( 'kirtan desai s' );
1 row created.
SQL>select substr( a||' ', 1, instr(a||' ' ' ')-1 ) first_name,
2 substr( a||' ', instr( a||' ' ' ') +1, instr( a||' ' ' ', 1, 2 )-instr(a||' ' ' ')-1 ) last_name,
3 rtrim(substr( a||' ', instr( a||' ' ' ',1,2)+1),' ') middle_init
4 from name_test
5 /
FIRST_NAME LAST_NAME MIDDLE_INIT
---------------- ----------------- -----------------
kirtan
kirtan desai
kirtan desai s
hope this helps
Kirtan
hope this helpsKirtan
Flashback Queries
Flashback features were there in 9i. 10g is providing something new/extra.
### From new features guide ###
What if you ever need to do a resetlogs operation for recovery purposes, you can take the
database back to a point in time before the resetlogs if you find that you made a
mistake. This provides administrators more flexibility to detect and correct human
error situations.
It is now possible to flashback the primary and standby databases to an SCN or a point in
time prior to the switchover operation. Using flashback in this way on a physical standby
database preserves the standby role. Using flashback in this way on a logical standby
database changes the role of the standby database to what it was at the target SCN/time.
### ###
Here is how you can use Flashback options.
SQL> create table ksdesai.fstes (a number(2));Table created.
SQL> insert into ksdesai.fstes values (1);
1 row created.
SQL> insert into ksdesai.fstes values (2);
1 row created.
SQL> insert into ksdesai.fstes values (3);
1 row created.
SQL> insert into ksdesai.fstes values (4);
1 row created.
SQL> insert into ksdesai.fstes values (5);
1 row created.
SQL> commit;
Commit complete.
SQL> select * from ksdesai.fstes;
A
----------
1
2
3
4
5
SQL> delete from ksdesai.fstes where a<3;
2 rows deleted.
SQL> commit;
Commit complete.
SQL> SELECT versions_xid XID, versions_startscn START_SCN,
2 versions_endscn END_SCN, versions_operation OPERATION,
3 A AS TABLE_COLUMN FROM KSDESAI.FSTES
4 VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE
5 ;\
6
SQL> SELECT versions_xid XID, versions_startscn START_SCN,
2 versions_endscn END_SCN, versions_operation OPERATION,
3 A AS TABLE_COLUMN FROM KSDESAI.FSTES
4 VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE;
XID START_SCN END_SCN O TABLE_COLUMN
---------------- ---------- ---------- - ------------
000A001B00078D60 660961162 D 2
000A001B00078D60 660961162 D 1
0005002E0007F815 660961134 I 5
0005002E0007F815 660961134 I 4
0005002E0007F815 660961134 I 3
0005002E0007F815 660961134 660961162 I 2
0005002E0007F815 660961134 660961162 I 1
7 rows selected.
SQL> insert into ksdesai.fstes
2 select a from ksdesai.fstes
3 VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE
4 where versions_operation='D';
2 rows created.
SQL> commit;
Commit complete.
SQL> select * from ksdesai.fstes;
A
----------
3
4
5
2
1
Magical!!! Or is it?
Kirtan
####UPDATES####
Retriving delete records from a table within certain period.
SQL> create table t1 (a number);
Table created.
SQL> desc t1;
Name Null? Type
------ ------ --------
A NUMBER
SQL> insert into t1 values (1);
1 row created.
SQL> insert into t1 values (2);
1 row created.
SQL> insert into t1 values (3);
1 row created.
SQL> commit;
Commit complete.
SQL> select * from t1;
A
----------
1
2
3
SQL> create table t3 (a number);
Table created.
SQL> insert into t3 values (1);
1 row created.
SQL> insert into t3 values (2);
1 row created.
SQL> insert into t3 values (3);
1 row created.
SQL> commit;
Commit complete.
SQL> select * from t3;
A
----------
1
2
3
######################
SQL> delete from t1 where a=2;
1 row deleted.
SQL> commit;
Commit complete.
SQL> select * from t1;
A
----------
1
3
SQL> select * from t3;
A
----------
1
2
3
########################
SQL> select versions_xid XID, versions_startscn START_SCN,
2 versions_endscn END_SCN, versions_operation OPERATION,
3 A AS TABLE_COLUMN from t1
4 VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE;
XID START_SCN END_SCN O TABLE_COLUMN
---------------- ---------- ---------- - ------------
000B000D0006B0E0 661139198 D 2
000B002C0006B412 661139095 I 3
000B002C0006B412 661139095 661139198 I 2
000B002C0006B412 661139095 I 1
######################
SQL> select * from t3;
A
----------
1
2
3
SQL> delete from t3 where a in (
2 select a from t1
3 VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE
4 where
5 versions_operation='D'
6 );
1 row deleted.
SQL> select * from t3;
A
----------
1
3
#######################
SQL> select * from t1 a, t1 b where a.a=b.a;
A A
---------- ----------
1 1
3 3
######################
SQL> insert into t1
2 select a from t1
3 VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE
4 where
5 versions_operation='D';
1 row created.
SQL> commit;
Commit complete.
SQL> select * from t1;
A
----------
1
3
2
######################
duplicate file check
I just wrote this procedure below that does duplicate file (dataset, i should say) check.
Let’s say, you have a system where your clients/users have rights to write straight to your “staging” or “landing” tables. You have a system where multiple users are feeding multiple files everyday. You have a requirement to check whether users are sending duplicate files into your system intentionally or unintentionally. You could probably find a million ways of doing a duplicate file check. I just wrote a simple stored procedure that does that for me. Let’s have a look at it. \
create or replace PROCEDURE clob_to_hash IS
i number(5);
mychar VARCHAR2(4000);
myclob CLOB;
myraw raw(2000);
rec_cnt NUMBER(2);
CURSOR mycur1 IS
SELECT column_name AS
field_name
FROM sys.all_tab_cols
WHERE owner = 'SCOTT'
AND TABLE_NAME = 'EMP'
ORDER BY column_id;
mycur mycur1%ROWTYPE;
col_names VARCHAR2(4000);
mysqlstr varchar2(4000);
BEGIN
i:=0;
OPEN mycur1;
LOOP
FETCH mycur1 INTO mycur;
EXIT WHEN mycur1%NOTFOUND;
IF i = 0 THEN
col_names := mycur.field_name;
ELSE
col_names := col_names || ',' || mycur.field_name;
end if;
i:=i+1;
END LOOP;
close mycur1;
mysqlstr := 'SELECT xmlagg(xmlelement("emp",' || col_names || ')).getclobval() FROM scott.emp';
execute immediate mysqlstr INTO myclob;
myraw := dbms_crypto.hash(src => myclob, typ => dbms_crypto.hash_md5);
mychar := rawtohex(myraw);
SELECT COUNT(*) INTO rec_cnt FROM hashtest WHERE mchar = mychar;
IF rec_cnt = 0 THEN
INSERT INTO hashtest VALUES(mychar);
ELSE
INSERT INTO hashtest VALUES('duplicate data set');
END IF;
COMMIT;
END;
This procedure creates a list of column names of ‘emp’ table from sys.all_tab_cols in order they were created. It builds a clob of xml data out of the emp table and create an MD5 key for that clob. It converts the ‘raw’ value returned by DBMS_CRYPTO.HASH function to a ‘hex’ value. After that it tries to find a row in the “hashtest” table to see if the same ‘hash’ key exists. If it finds duplicate records, it write ‘duplicate data set’ in the hashtest table. otherwise it writes the ‘hex’ value generated from the ‘hash’ value which was returned in ‘raw’ format by DBMS_CRYPTO.HASH function.
SQL> truncate table hashtest;
Table truncated.
SQL> exec clob_to_hash;
PL/SQL procedure successfully completed.
SQL> desc hashtest;
Name Null? Type
----------------------------------------- -------- ----------------------------
MCHAR VARCHAR2(255)
SQL> select * from hashtest;
MCHAR
--------------------------------------------------------------------------------
4FCD4351B718B46FC8DCE7BA01B3F910
SQL> exec clob_to_hash;
PL/SQL procedure successfully completed.
SQL> select * from hashtest;
MCHAR
--------------------------------------------------------------------------------
17A6E53EA979BFB0E67CCE2E5BDDB769
duplicate data set
SQL> update scott.emp set sal=sal+100 where empno=7844;
1 rows updated.
SQL> commit;
Commit complete
SQL> exec clob_to_hash;
PL/SQL procedure successfully completed.
SQL> select * from hashtest;
MCHAR
--------------------------------------------------------------------------------
17A6E53EA979BFB0E67CCE2E5BDDB769
duplicate data set
4FCD4351B718B46FC8DCE7BA01B3F910
That’s it!!! With a little modification, you could pretty much use this to compare any two datasets.
Useful Scripts.
Below are some useful scripts that i found in one of my old hard drives. If you want to gather stat reports for the oracle ser sessions you could use the following scripts. Right before posting this i tried them on 8i, 9i, and 10g.
To find total cpu usage by each/all sessions, you could use the following sql statement.
Select nvl ( sess.username, 'oracle_process' ) username
, sess_stat.sid session_id, value cpu_usage
From v$session sess
, v$sesstat sess_stat
, v$statname stat_name
Where sess_stat.statistic# = stat_name.statistic#
And name like '%cpu used by this session%'
And sess_stat.sid = sess.sid
And value > 0
Order by value desc
/
To find total resource usage by each user, you could use the following sql statement.
Select sess.sid, nvl ( sess.username, 'oracle_process' ) username
, sess_stat.sid session_id, stat_name.name statistic, value cpu_usage
From v$session sess
, v$statname stat_name
, v$sesstat sess_stat
Where sess_stat.sid = sess.sid
And stat_name.statistic# = sess_stat.statistic#
And value != 0
Order by value desc
, sess.username
, sess.sid
, stat_name.name
/
To find session i/o activity by each user, you could use the following sql statement.
Select nvl ( sessions.username, 'oracle_process' ) username, osuser os_user
, process pid, sessions.sid sid, serial#, physical_reads, block_gets
, consistent_gets, block_changes, consistent_gets, block_changes
, consistent_changes
From v$session sessions
, v$sess_io session_io
Where sessions.sid = session_io.sid
Order by physical_reads desc
, sessions.username
/
hope this helps…
Kirtan
Oracle Function:Translate & Replace
Using Oracle function TRANSLATE and REPLACE to remove special characters from a string.
This is the definition of the function.
TRANSLATE(expr, from_string, to_string)
Descrption: [FROM ORACLE DOCUMENTATION]
TRANSLATE returns expr with all occurrences of each character in from_string replaced by its corresponding character in to_string. Characters in expr that are not in from_string are not replaced. If expr is a character string, then you must enclose it in single quotation marks. The argument from_string can contain more characters than to_string. In this case, the extra characters at the end of from_string have no corresponding characters in to_string. If these extra characters appear in char, then they are removed from the return value.
You cannot use an empty string for to_string to remove all characters in from_string from the return value. Oracle Database interprets the empty string as null, and if this function has a null argument, then it returns null.
Let’s see…
SQL> create table t6 (a varchar2(20));
Table created.
SQL> insert into t6 values ('ABC!@#$%^&*XYZ');
1 row created.
SQL> commit;
Commit complete.
SQL> select * from t6;
A
--------------
ABC!@#$%^&*XYZ
SQL> SELECT TRANSLATE(a, '!@#$%^&*', ' ') FROM t6;
TRANSLATE(A,'!@#$%^&
---------------------
ABC XYZ
#####
Notice that I removed the $ (DOLLAR) sign from the list of junk.
#####
SQL> SELECT TRANSLATE(a, '!@#%^&*', ' ') FROM t6;
TRANSLATE(A,'!@#%^&*
--------------------
ABC $XYZ
#####
I would create a function that accepts a varchar2 and returns a ‘cleaned’ varchar2 for this purpose.
#####
SQL> create or replace function clean_str(in_string in varchar2)
2 return varchar2
3 is
4 out_string varchar2(4000);
5 remove_char varchar2(100);
6 begin
7 remove_char:='!@#$%^&*æ';
8 select TRANSLATE(in_string,remove_char , ' ') into out_string FROM dual;
9 return (out_string);
10 end;
11 /
Function created.
SQL> select clean_str(a) from t6;
CLEAN_STR(A)
------------
ABC XYZ
I kept the last argument ‘ ‘ (a space) because of the NULL rule mentioned above in the description. I just asked Oracle to assign a single space instead.
SQL> insert into t6 values ('ABC!@#$XYZ%^&*XML');
1 row created.
SQL> commit;
Commit complete.
SQL> select * from t6;
A
-----------------
ABC!@#$%^&*XYZ
ABC!@#$XYZ%^&*XML
SQL> select clean_str(a) from t6;
CLEAN_STR(A)
------------
ABC XYZ
ABC XYZXML
Now that I have a string like ‘ABC XYZ’ and ‘ABC XYZXML’, I am going to use Oracle function REPLACE to remove the extra space(s). The advantage of REPLACE is that it replaces all the occurances of the string/character with the provided replacement string. So lets change the function a little bit.
SQL> create or replace function clean_str(in_string in varchar2)
2 return varchar2
3 is
4 out_string varchar2(4000);
5 remove_char varchar2(100);
6 begin
7 remove_char:='!@#$%^&*æ';
8 select
9 REPLACE(TRANSLATE(in_string,remove_char , ' '),' ',NULL)
10 into out_string
11 FROM dual;
12 return (out_string);
13 end;
14 /
Function created.
SQL> select clean_str(a) from t6;
CLEAN_STR(A)
------------
ABCXYZ
ABCXYZXML
So now all you have to do is keep a list of unwanted or special characters in the remove_char variable of the function and you are golden.
I hope this helps.
-Kirtan
Updated!!!
I just realized that there is no need to use REPLACE function above. I will keep it as it is just in case if someone wants to use it as it is. Below is an updated(and better IMHO) version of clean_str() function. The idea is to pass the character that you want to remove as the THIRD argument and concatenate the variable remove_char with the same character. It is going to be a space for this example.
create or replace function clean_str(in_string in varchar2)
return varchar2
is
out_string varchar2(4000);
remove_char varchar2(100);
begin
remove_char:=' ' || '!@#''''$%^&*æ';
select
--REPLACE(TRANSLATE(in_string,remove_char , ' '),' ',NULL)
TRANSLATE(in_string,remove_char , ' ')
into out_string
FROM dual;
return (out_string);
end;
/
What you can also do is you can allow the character that you want to be removed as an input to the function.
create or replace function clean_str1(in_string in varchar2,culprit in char)
return varchar2
is
out_string varchar2(4000);
remove_char varchar2(100);
begin
remove_char:=culprit || '!@#''''$%^&*æ';
select
--REPLACE(TRANSLATE(in_string,remove_char , ' '),' ',NULL)
TRANSLATE(in_string,remove_char , culprit)
into out_string
FROM dual;
return (out_string);
end;
/SQL> select clean_str1('KIR$#@%TAN',' ') from dual;
CLEAN_STR1('KIR$#@%TAN','')
--------------------------------------------------------------------------------
KIRTAN
SQL>
You are currently browsing the archives for the Oracle category.