5. SUBQUERIES (single value using =)
select max(salary) from employees;
select *
from employees
where salary = (select max(salary) from employees);
select *
from employees
where salary = (select min(salary) from employees);
6. SUBQUERIES (multiple values using IN)
SELECT department_id
FROM departments
WHERE LOCATION_ID = 1700;
SELECT first_name, last_name, department_id
FROM employees
WHERE department_id IN (SELECT department_id
FROM departments
WHERE LOCATION_ID = 1700);
SELECT first_name, last_name, department_id
FROM employees
WHERE department_id NOT IN (SELECT department_id
FROM departments
WHERE LOCATION_ID = 1700);
7. Co-Related Queries
SELECT EMPLOYEE_ID, salary, department_id
FROM employees t1
WHERE salary > (SELECT avg(salary)
FROM employees t2
WHERE t1.department_id = t2.department_id);
8. Subqueries (Multiple column)
SELECT min_salary, job_id
FROM jobs;
SELECT *
FROM employees
WHERE (salary, job_id) in (SELECT min_salary, job_id
FROM jobs);
9. Inline views
Eg1:
How many employees are assigned to each department?
SELECT department_id, count(*) emp_count FROM employees GROUP BY department_id;
You also want to display depart name? (You can use sub query)
Select * from (SELECT department_id, count(*) emp_count FROM employees GROUP BY department_id) emp join departments dept on
emp.department_id=dept.department_id;
Eg2:
select * from employees Where commission_pct is null Order by salary desc;
select * from (select * from employees where commission_pct is null Order by salary desc) top_salaries Where rownum <=3;
17. Creating Index
CREATE INDEX emp_sal_idx ON employees (salary);
select * from employees where salary = 24000;
select * from employees where salary between 24000 and 2500;
Composite index:
CREATE INDEX emp_idx2 ON employees (salary, hire_date);
select * from employees where salary between 24000 and 2500
and hire_date < sysdate-365;
drop index emp_idx2;
21. USE DICT if you don’t know metadata you are searching contained on which view …
select table_name from dict;
select table_name from dict
where table_name = 'ALL_TABLES';
select table_name from dict
where table_name like '%TRIGGERS%';
select table_name from dict
where table_name like '%INDEXES%';
22. select * from all_tables;
select * from user_tables;
select * from user_tables
where table_name = 'EMPLOYEES';
select * from user_tab_columns
where table_name = 'EMPLOYEES';
select * from user_ind_columns
where table_name = 'EMPLOYEES';
select username, program, machine from v$session;
select * from v$instance;
select * from v$lock;
select * from all_users;
26. Isolation and locks
Until COMMIT happen each connection to DB sees their own values
Eg: Among 2 concurrent one is update and one operation is select
27. Isolation Example
Connection1: TRANSACTION1
update employees set salary
= 25000 where employee_id
= 100;
select employee_id, salary
from employees where
employee_id=100;
=> o/p 25000
Connection2: TRANSACTION2
select employee_id, salary
from employees where
employee_id=100;
=> o/p: 25000
28. Isolation and locks
Eg: Among 2 concurrent both is update and one operation; so second
transaction will wait until first transaction COMMIT/ROLLBACK
29. Example LOCKS
Session1: TRANSACTION1
update employees set salary
= 30000 where employee_id
= 100;
=> 1 row updated will create
lock to row with emp_id =100
Session2: TRANSACTION2
update employees set salary =
35000 where employee_id = 100;
=> WAITING……
NOTE: If we COMMIT/ROLLBACK in transaction1, then transaction 2 will be completed
NOTE:: SEE all sessions connected to database: THERE ARE VIEWS CREATED ALREADY::
SELECT username, osuser, sid, serial#, lockwait, status, module, machine, program FROM
v$session;
=> You will see many of active session from internal of Oracle; Scroll and find session (above 2)
we generate
30. NOTE:: SEE all sessions connected to database: THERE ARE VIEWS CREATED
ALREADY::
SELECT username, osuser, sid, serial#, lockwait, status, module, machine,
program FROM v$session;
=> You will see many of active session from internal of Oracle; Scroll and find 2
session from SQL DEVELOPER we generate
35. Trigger:
EG1:
CREATE TABLE table1 (col1 number(5), col2 varchar2(50));
CREATE TABLE table2 (col1 number(5), col2 varchar2(50));
CREATE OR REPLACE TRIGGER test_trg1
AFTER INSERT ON table1
FOR EACH ROW
BEGIN
insert into table2 values (:new.col1 , :new.col2);
END;
/
36. Eg2:
CREATE TABLE audit_table (op_time date, col1 number(5), col2_before varchar2(50),
col2_after varchar2(50));
CREATE OR REPLACE TRIGGER audit_trg
AFTER INSERT OR DELETE OR UPDATE ON table1
FOR EACH ROW
BEGIN
insert into audit_table values (sysdate, :new.col1 , :old.col2, :new.col2);
END;
/
Verify::
UPDATE TABLE1 set col2= 'Hello World 2' where col1 = 1;
SELECT * FROM audit_table;
40. PL/SQL : Procedure: Example
CREATE OR REPLACE PROCEDURE proc1 (emp_id IN NUMBER)
IS
emp_fname VARCHAR2(50);
BEGIN
SELECT first_name INTO emp_fname FROM employees where employee_id =
emp_id;
DBMS_OUTPUT.PUT_LINE('Employee name is: ' || emp_fname);
END;
SET SERVEROUTPUT ON
EXECUTE::
EXEC proc1(100)
41. Where and How it is executed?
=> It’s different than procedure in sence that it’s executed within SQL statement
OR; i.e.
42. PL/SQL Function: Example
CREATE OR REPLACE Function func1 (emp_id IN NUMBER)
RETURN VARCHAR2
IS
emp_fname VARCHAR2(50);
BEGIN
SELECT first_name INTO emp_fname FROM employees where employee_id =
emp_id;
RETURN emp_fname;
END;
SELECT func1(100) from dual;
SELECT func1(200) from dual;
43. PL/SQL Packages
Groups multiple procedures, functions, types, varibales, and so on that
share a business purpose
Has 2 mandatory parts:
1. Package Specification
2. Package Body
44.
45.
46. Views
CREATING VIEW::
create or replace view emp_sales
as
select * from employees where job_id = 'SA_MAN';
USES:
=> select * from emp_sales;
This means same as below
select * from (select * from employees where job_id = 'SA_MAN');
=> You can have all normal SQL query operation on views as in table
select * from emp_sales where salary > 12000;
REMOVE:: DROP VIEW emp_sales;
47. Complex views
CREATE OR REPLACE VIEW emp_sales
as
select employee_id, first_name, last_name from employees where job_id =
'SA_MAN';
SELECT emp_sales.first_name, departments.department_name
FROM emp_sales JOIN departments ON emp_sales.department_id = departments.department_id;
CREATE VIEW locations_view AS
SELECT d.department_id, d.department_name, l.location_id, l.city
FROM departments d, locations l
WHERE d.location_id = l.location_id;
=> SELECT * FROM locations_view;
DROP VIEW emp_sales;
50. Table Partitioning/Partition:
=> Allows table to sub-divided into smaller pieces or element; Each these pieces
are known as table partition
=> Each table partition has it’s own name and is separate physical and logical
object
From application
view point tble
without partition
and with
partition are
equivalent but
partitioned table
has advantage
(next slide)
57. List:
1. Create partiton on table(see previous query/ in notes)
2. Insert values:
INSERT INTO sales_list VALUES (100, 'Picard', 'CA', 100, '01-JAN-2017’);
INSERT INTO sales_list VALUES (200, 'Janeway', 'NY', 500, '02-JAN-2017’);
INSERT INTO sales_list VALUES (300, 'Kirk', 'TX', 1000, '03-JAN-2017’);
INSERT INTO sales_list VALUES (100, 'Picard', 'IL', 500, '04-JAN-2017’);
3. Verify:
TOTAL COUNT: SELECT COUNT(*) FROM sales_list; -- 4
SELECT COUNT(*) FROM sales_list partition (sales_ca); -- 1
SELECT COUNT(*) FROM sales_list partition (sales_ny); -- 1
SELECT COUNT(*) FROM sales_list partition (sales_central); -- 2
SELECT COUNT(*) FROM sales_list partition (sales_other); -- 0
58. Split already existing partition in table:
Eg: Split existing partition sales_other into 2 new partitions sales_nv & sales_other
ALTER TABLE sales_list
SPLIT PARTITION sales_other VALUES ('NV')
INTO
(PARTITION sales_nv,
PARTITION sales_other);
SELECT count(*) FROM SALES_LIST PARTITION (sales_nv); -- 0
INSERT INTO sales_list VALUES (300, 'Kirk', 'NV', 2300, '01-JAN-2017');
SELECT count(*) FROM SALES_LIST PARTITION (sales_nv); -- 1
59.
60. RANGE PARTITION::
CREATE TABLE sales_range
(
salesrep_id NUMBER(5),
salesrep_name VARCHAR2(30),
sales_amount NUMBER(10),
sales_date DATE)
PARTITION BY RANGE(sales_date)
(
PARTITION sales_jan2017 VALUES LESS THAN(TO_DATE('01/02/2017','DD/MM/YYYY')),
PARTITION sales_feb2017 VALUES LESS THAN(TO_DATE('01/03/2017','DD/MM/YYYY')),
PARTITION sales_mar2017 VALUES LESS THAN(TO_DATE('01/04/2017','DD/MM/YYYY')),
PARTITION sales_apr2017 VALUES LESS THAN(TO_DATE('01/05/2017','DD/MM/YYYY'))
);
NOTE: ALTER TABLE sales_range ADD PARTITION sales_may2017 VALUES LESS THAN(TO_DATE('01/06/2017','DD/MM/YYYY'))
61.
62. Hash partition::
CREATE TABLE sales_hash
(
salesrep_id NUMBER(5),
salesrep_name VARCHAR2(30),
sales_amount NUMBER(10),
sale_no NUMBER(5))
PARTITION BY HASH(sale_no)
PARTITIONS 4 ; -- Just specify number; no explicit name is required
ANALYZE TABLE sales_hash COMPUTE STATISTICS;
SELECT table_name, partition_name, num_rows FROM user_tab_partitions
WHERE table_name = 'SALES_HASH';
Hinweis der Redaktion
Password is: oracleISSUE OPENING IN mac irtualBox:$ sudo kextload -b org.virtualbox.kext.VBoxDrv
update employees set salary = 25000 where employee_id = 100;
select employee_id, salary from employees where employee_id=100;
commit;
update employees set salary = 25000 where employee_id = 100;
select employee_id, salary from employees where employee_id=100;
commit;
SEE all sessions connected to database:SELECT username,
osuser,
sid,
serial#,
lockwait,
status,
module,
machine,
program
FROM v$session;
1.Create trigger
2. See initial values
SELECT * FROM table1;
SELECT * FROM table2;
3. insert
INSERT INTO table1 VALUES (1,'Hello World!’);
4. Verify values in table
SELECT * FROM table1;
SELECT * FROM table2;
Benefits:
Partition Pruning
Separate DBA operation per partition
LIST PARTITIONING (specify specific matched value)
Group based on same value in certain column
Good for columns having few values and all values are known
RANGE (specify range to matched value)=> partiton based on range of values
Create table (Above query)
Insert values
INSERT INTO sales_range VALUES (100, 'Picard', 100, '01-JAN-2017');
INSERT INTO sales_range VALUES (100, 'Picard', 100, '01-FEB-2017’);
Verify
SELECT COUNT(*) FROM sales_range partition (sales_jan2017);
SELECT COUNT(*) FROM sales_range partition (sales_feb2017);
INSERT INTO sales_range VALUES (100, 'Picard', 100, '01-MAY-2017');
SELECT COUNT(*) FROM sales_range partition (sales_may2017);
ALTER TABLE sales_range ADD PARTITION sales_may2017 VALUES LESS THAN(TO_DATE('01/06/2017','DD/MM/YYYY'))
HASH=> we don’t specify explicit partition names and values when creating your table
=> Useful when you want to divide table for performance but don’t know how to partition or don’t have visual pertitioning idea
Oracle Db uses hash to evenly distribute data
Suitble for tables where no natural distribution you know
Useful when you want to divide table for performance but don’t know how to partition or don’t have visual pertitioning idea
Create
Analyse
SELECT table_name, partition_name, num_rows FROM user_tab_partitions WHERE table_name = 'SALES_HASH';
INSERT INTO sales_hash VALUES (100,'Picard', 500, 1423);
ANALYZE TABLE sales_hash COMPUTE STATISTICS;
SELECT table_name, partition_name, num_rows FROM user_tab_partitions WHERE table_name = 'SALES_HASH’;
3. Insert
INSERT INTO sales_hash VALUES (100,'Picard', 500, 1423);
INSERT INTO sales_hash VALUES (100,'Picard', 600, 1424);
INSERT INTO sales_hash VALUES (100,'Picard', 200, 1425);
INSERT INTO sales_hash VALUES (100,'Picard', 100, 1426);
INSERT INTO sales_hash VALUES (100,'Picard', 500, 1427);
INSERT INTO sales_hash VALUES (100,'Picard', 600, 1428);
INSERT INTO sales_hash VALUES (100,'Picard', 200, 1429);
INSERT INTO sales_hash VALUES (100,'Picard', 100, 1430);
4. Analyze again
ANALYZE TABLE sales_hash COMPUTE STATISTICS;
SELECT table_name, partition_name, num_rows FROM user_tab_partitions WHERE table_name = 'SALES_HASH';