You are on page 1of 37

Oracle Tips & Tricks

Shane Zhang

Dec 24, 2016

Slide 1

AGENDA

CASE Statement
Joins
Timestamp Data Type
Rename Tables, Columns
Merge Statement
Subqueries/With
Groupset/Rollup/Cube
Skip Scanning of Indexes
Index Compression
Index Organized Tables (IOTs)
Temp Tables
Dec 24, 2016

Slide 2

CASE Statement vs. Decode

2 ways to implement IF-THEN-ELSE logic within a SQL statement

CASE complies to ANSI SQL and is new to Oracle release 9i

DECODE Example (Oracle specific):


SELECT last_name, job_cd, salary,
DECODE(job_cd, IT,salary*1.10,
SALES, salary*1.15,
salary*1.05)
FROM employees ;

CASE Example:
SELECT last_name, job_cd, salary,
CASE job_cd WHEN IT THEN salary*1.10
WHEN SALES THEN salary*1.15
ELSE salary*1.05
END
FROM employees;

Dec 24, 2016

Slide 3

ANSI Standard Join Syntax

Oracle 9i introduced ANSI compliant join syntax


INNER JOIN, LEFT OUTER JOIN, RIGHT OUTER JOIN,
FULL OUTER JOIN

Oracle 9i Outer Join (all rows from table on the left are retained in the
result set)
SELECT p.part_id, s.supplier_name
FROM part p left outer supplier s
ON p.supplier_id = s.supplier_id

Dec 24, 2016

Slide 4

Join Operators

Cross Join:
Produces cross product resulting in Cartesian join. MOST LIKELY A MISTAKE!
SELECT empid, deptno FROM emp CROSS JOIN dept;
Without the operator: SELECT empid, deptno FROM emp, dept;
Natural Join:
Join based on like columns
SELECT empid, deptno, dname FROM emp NATURAL JOIN dept;
Without the operator: SELECT a.empid, a,deptno, b.dname FROM emp a,
dept b WHERE a.deptno = b.deptno;

Dec 24, 2016

Slide 5

Join Operators Contd

ON:
Much like WHERE clause. Can be used to join columns that
are named differently.
SELECT empid, dname FROM emp a JOIN dept b ON
(a.deptno = b.department_no AND a.empid < 20);
Without the operator: SELECT empid, dname FROM emp a,
dept b WHERE a.deptno = b.department_no AND a.empid <
20;

Dec 24, 2016

Slide 6

New in 9i - Full Outer Joins

Full Outer Syntax in Oracle 9i:


SELECT p.part_id p, s.supplier_name
FROM part p FULL OUTER JOIN supplier s
ON p.supplier_id = s.supplier_id
Result SQL is smaller in size; more elegant and more efficient than
UNION method

Dec 24, 2016

Slide 7

Self Joins

Create routes using lane segment


SELECT a.origapt, a.destapt, b.destapt
From lanes a, lanes b
Where a.destapt=b.origapt;

Dec 24, 2016

Slide 8

Renaming Columns, Constraints, Tables

Syntax
Renaming a column:
ALTER TABLE test RENAME COLUMN a_flg TO my_flg;
Renaming a constraint:
ALTER TABLE test RENAME constraint a_flg_pk TO
a_flg_pk_new;
Renaming a table:
ALTER TABLE test RENAME to test_new;

Dec 24, 2016

Slide 9

Top N Analysis
SELECT [column_list], ROWNUM
FROM (SELECT [column_list]
FROM table
ORDER BY Top-N_column)
WHERE ROWNUM <= N;
Rank by group
SELECT Empno, Ename, Job, Mgr, Hiredate, Sal
FROM
(SELECT Empno, Ename, Job, Mgr, Hiredate, Sal,
RANK() OVER
(ORDER BY SAL Desc NULLS LAST) AS Emp_Rank
FROM Emp
ORDER BY SAL Desc NULLS LAST)
WHERE Emp_Rank < 6;

Dec 24, 2016

Slide 10

Windowing Function

Three month moving average

SELECT month, SUM(tot_sales) monthly_sales,


AVG(SUM(tot_sales)) OVER (ORDER BY month
ROWS BETWEEN 1 PRECEDING AND 1
FOLLOWING) rolling_avg
FROM orders
WHERE year = 2001
AND region_id = 6
GROUP BY month
ORDER BY month;

Cumulative total
SELECT month,
SUM(tot_sales) monthly_sales,
SUM(SUM(tot_sales)) OVER (ORDER BY month
ROWS BETWEEN UNBOUNDED PRECEDING AND
CURRENT ROW) running_total
FROM orders
WHERE year = 2001
AND region_id = 6
GROUP BY month
ORDER BY month;

Dec 24, 2016

Slide 11

Traverse the Hierarchical tree

Organization Chart
SELECT level, lname, emp_id,
manager_emp_id
FROM employee
START WITH manager_emp_id IS NULL
CONNECT BY manager_emp_id =
PRIOR emp_id;

Dec 24, 2016

Does JONES have any authority over


BLAKE?
SELECT *
FROM employee
WHERE lname = 'BLAKE'
START WITH lname = 'JONES'
CONNECT BY manager_emp_id = PRIOR
emp_id;

Slide 12

XML

Create XML elements from table


SELECT XMLElement("supplier_id", s.supplier_id) ||
XMLElement("name", s.name) xml_fragment
FROM supplier s;

Dec 24, 2016

Slide 13

Using subquery
Inline View subquery in the from clause Inline views are always executed
prior to the containing query and, thus, may not reference columns from
other tables or inline views from the same query.
SELECT [column_list], ROWNUM FROM (SELECT [column_list]
FROM table ORDER BY Top-N_column) WHERE ROWNUM <= N;

Nested query subquery in the where clause

SELECT lname FROM employee WHERE salary > (SELECT AVG(salary)


FROM employee);

select ename ,sal ,deptno from emp a where


a.sal < (select avg(sal) from emp b
where a.deptno = b.deptno)
order by deptno;

Dec 24, 2016

Slide 14

Using subquery Contd

You can update through a view


update ( select a.data old_data, b.data new_data
from table1 A, table2 B
where a.key = b.key )
set old_Data = new_data

Delete duplicate records


DELETE FROM our_table WHERE rowid not in
(SELECT MIN(rowid) FROM our_table
GROUP BY column1, column2, column3... ;;
Dec 24, 2016

Slide 15

With Clause

To eliminate the inefficiency of executing the same subquery multiple times,


Oracle introduced the WITH clause in the Oracle9i release. Using the WITH
clause, you can place the subquery that calculates the average salary at the top
of the query and reference it throughout the query: The WITH clause creates a
temporary data set called, in this case, avg_sal,

WITH avg_sal AS (SELECT AVG(salary) val FROM employee)


SELECT e.emp_id, e.lname, e.fname,
(SELECT ROUND(e.salary - val) FROM avg_sal) above_avg
FROM employee e
WHERE e.salary > (SELECT val FROM avg_sal);

Dec 24, 2016

Slide 16

Having Clause

SELECT department, SUM(sales) as "Total sales"


FROM order_details GROUP BY department
HAVING SUM(sales) > 1000;
SELECT department, COUNT(*) as "Number of employees"
FROM employees
WHERE salary > 25000
GROUP BY department
HAVING COUNT(*) > 10;

Dec 24, 2016

Slide 17

Oracle 9i TIMESTAMP Data Type

Extension of the DATE data type


Stores year, month, & day of the date + hour, minute, second and fractional seconds
select current_timestamp from dual
13:53:29 SQL> /
CURRENT_TIMESTAMP
--------------------------------------------------------------------------14-MAR-05 01.53.30.458397 PM -06:00
insert into time_stamp_example (select current_timestamp from dual);
1 row created.
13:46:13 SQL> insert into time_stamp_example (select sysdate from dual) ;
1 row created.
Elapsed: 00:00:00.02
13:46:23 SQL> select * from time_stamp_example;
EXAMPLE_DATE
--------------------------------------------------------------------------14-MAR-05 01.46.23.0000 PM
1 row selected.
Elapsed: 00:00:00.00

Dec 24, 2016

Slide 18

Information of a table

Find out the creation date of a table


select substr(object_name,1,15),created from obj;

Find out who has what privileges on your tables


select table_name,grantee,privilege from user_tab_privs;

Dec 24, 2016

Slide 19

Information on Space
Get an estimation of the size of a table, get avg_row_len and pctfree information
from user_tables
tablesize=number of rows*avg_row_len*(1+pctfree/100)
SQL> select num_rows,pct_free,avg_row_len from user_tables where
table_name='DOCDATA_IND';
Find out the total free space available to current use
select tablespace_name,sum(bytes/1000) from user_free_space group by
tablespace_name
Find out how much space used and what is your quota
select * from user_ts_quota;

Dec 24, 2016

Slide 20

Group By Enhancements Grouping Set


Union all method,
multiple table scan , slow
select count(*) CNT, deptno, 'summary' as job
from emp
group by deptno
UNION ALL
select count(*), deptno, job
from emp
group by deptno, job
/
CNT
DEPTNO JOB
--- ---------- --------3
10 Summary
1
10 PRESIDENT
1
10 MANAGER
1
10 CLERK
5
1
2
2

20
20
20
20

Summary
MANAGER
CLERK
ANALYST

6
4
1
1

30
30
30
30

Summary
SALESMAN
MANAGER
CLERK

Dec 24, 2016

New method, fast


select count(*) CNT, deptno
, CASE GROUPING_ID(job)
WHEN 1 THEN 'Summary'
ELSE job
END AS job
from emp
group by GROUPING SETS
( (deptno)
, (deptno, job )
)
/
CNT
DEPTNO JOB
--- ---------- --------3
10 Summary
1
10 PRESIDENT
1
10 MANAGER
1
10 CLERK
5
1
2
2

20
20
20
20

Summary
MANAGER
CLERK
ANALYST

6
4
1
1

30
30
30
30

Summary
SALESMAN
MANAGER
CLERK
Slide 21

Group By Enhancements ROLLUP / CUBE

ROLLUP - Used for subtotaling along a hierarchical dimension


such as time or geography.
CUBE = ROLLUP + other combinations
Can simplify and speed up population and maintenance of
summary tables.

Dec 24, 2016

Slide 22

ROLLUP Example Query

SELECT a.shp_rcv_src_cd,
a.tndr_type_cd,
SUM(a.nbr_of_pkgs),
SUM(a.net_rev),
SUM(a.ratd_wgt)
FROM shipment a,
location b
WHERE a.shp_dt_yyyymm='200312'
and a.shp_rcv_src_cd in ('3','4','5')
and b.loc_nbr=a.loc_nbr
and b.hist_yyyymm=a.shp_dt_yyyymm
and b.drpbx_type_cd in ('IC','IS','IW','IM','OM','IY','OW')
GROUP BY rollup(shp_rcv_src_cd,tndr_type_cd)
ORDER BY shp_rcv_src_cd,tndr_type_cd
Dec 24, 2016

Slide 23

ROLLUP Example Output

SHP_RCV_SRC_CD

Dec 24, 2016

TNDR_TYPE_CD

SUM(A.NBR_OF_PKGS)

SUM(A.NET_REV)

SUM(A.RATD_WGT)

CCC

15204

452297

76297

DRPF

688169

12653173

3509281

SOLD

570572

8422926

3112950

1273945

21528396

6698529

CCC

26

1414

100

DRPF

484

28301

4350

SOLD

759

23706

5306

1269

53421

9756

CCC

18

975

80

DRPF

2123

101847

12510

SOLD

230

7026

1625

2371

109849

14215

1277585

21691666

6722500
Slide 24

CUBE Example Query

SELECT a.shp_rcv_src_cd,
a.tndr_type_cd,
SUM(a.nbr_of_pkgs),
SUM(a.net_rev),
SUM(a.ratd_wgt)
FROM shipment a,
location b
WHERE a.shp_dt_yyyymm='200312'
and a.shp_rcv_src_cd in ('3','4','5')
and b.loc_nbr=a.loc_nbr
and b.hist_yyyymm=a.shp_dt_yyyymm
and b.drpbx_type_cd in ('IC','IS','IW','IM','OM','IY','OW')
GROUP BY cube(shp_rcv_src_cd,tndr_type_cd)
ORDER BY shp_rcv_src_cd,tndr_type_cd
Dec 24, 2016

Slide 25

CUBE Example Output

SHP_RCV_SRC_CD

TNDR_TYPE_CD

CCC

15204

452297

76297

DRPF

688169

12653173

3509281

SOLD

570572

8422926

3112950

1273945

21528396

6698529

CCC

26

1414

100

DRPF

484

28301

4350

SOLD

759

23706

5306

1269

53421

9756

CCC

18

975

80

DRPF

2123

101847

12510

SOLD

230

7026

1625

2371

109849

14215

CCC

15248

454686

76478

DRPF

690776

12783322

3526141

SOLD

571561

8453658

3119881

1277585

21691666

6722500

Dec 24, 2016

SUM(A.NBR_OF_PKGS)

SUM(A.NET_REV)

SUM(A.RATD_WGT)

Slide 26

MERGE

Performs single step INSERT and UPDATE


INTO clause specifies the target table
USING clause specifies the source
Key exists: Update performed
Key does not exist: Row inserted

Dec 24, 2016

Slide 27

MERGE Contd

SQL> select * from my_table;


ACCT_NBR
CO_NM
--------------------------------------------1 GE
1 row selected.
SQL>select * from my_staging_table;
ACCT_NBR
CO_NM
--------------------------------------------1 GE
2 Oracle Corp
2 rows selected.
Dec 24, 2016

Slide 28

MERGE Contd

SQL> merge into my_table a


using my_staging_table b on (a.acct_nbr = b.acct_nbr)
when matched then
update set a.co_nm = b.co_nm
when not matched then
insert
(a.acct_nbr, a.co_nm)
values
(b.acct_nbr, b.co_nm);
2 rows merged.

Dec 24, 2016

Slide 29

MERGE Contd

SQL>select * from my_table;


ACCT_NBR
---------------1
2

CO_NM
-----------------------------GE
Oracle Corp

2 rows selected.

Dec 24, 2016

Slide 30

Skip Scanning of Indexes

Earlier versions: Index will NOT be used if the WHERE clause


columns are not in the leading edge of the query.
With Oracle9i:
This is not an issue because of skip scanning of indexes
feature.
Indexes may be used regardless of the order the columns are
specified on WHERE stmt.
Bitmap indexes cannot take advantage of this feature.

Dec 24, 2016

Slide 31

Index Compression

Compression option on indexes was introduced in Oracle 8i; but


enhanced features are easier to use in Oracle 9i
A properly compressed index would use a smaller number of leaf
blocks to store the indexresulting in lower i/o when the index is
used = better performance on index scans.
At creation time, compress the 1st 2 columns of a composite index:
CREATE INDEX my_idx ON my_tbl(col1, col2, col3) compress 2;
Index already exists, compress first 2 columns:
ALTER index my_idx rebuild compress 2;
Dec 24, 2016

Slide 32

All my Indexes should be compressed, right?

No - should not ALWAYS compress indexes.


How do I know if I should compress and what columns to
compress?
Use VALIDATE INDEX:
VALIDATE INDEX my_idx;
Look at OPT_CMPR_COUNT and OPT_COMPR_PCTSAVE
columns:
SELECT opt_cmpr_countm, opt_cmpr_pctsave FROM
index_stats;
Dec 24, 2016

Slide 33

Temporary Tables

Not really a 9i feature. Enhanced/bug fixed


Holds session based or transaction based data.
Inserts by user A not visible to user B
Data automatically purged at the end of the session/transaction
but the table structure will be retained.
CREATE TABLE: key word GLOBAL TEMPORARY TABLE

Dec 24, 2016

Slide 34

Temporary Table Contd

Example:
SQL>CREATE GLOBAL TEMPORARY TABLE t_transaction
(c VARCHAR2(4000)) ON COMMIT DELETE ROWS;
Table created.
SQL> CREATE GLOBAL TEMPORARY TABLE t_session
(c VARCHAR2(4000)) ON COMMIT PRESERVE ROWS;
Table created.

Dec 24, 2016

Slide 35

Temporary Table Contd

SQL> INSERT INTO t_transaction (c)


VALUES ('data persists for the transaction');
1 row created.
SQL> INSERT INTO t_session (c)
VALUES ('data persists for the session');
1 row created.
SQL> commit;

Dec 24, 2016

Slide 36

Temporary Table Contd

Commit complete.
SQL> SELECT * FROM t_transaction;
no rows selected =========> the transaction is over, the data is gone
SQL> SELECT * FROM t_session;
C
---------------------------------------data persists for the session
1 row selected.
Dec 24, 2016

Slide 37

You might also like