Table of Contents
VIEWS in Oracle
- VIEW is a database object which does not contain any data but acts as a logical window to view its base table data.
- VIEW can be created based on one or more tables or views or both
- VIEW helps us to view the completed data in simple format
Types of VIEW:
- SIMPLE VIEW
- COMPLEX VIEW
SIMPLE VIEW:
- Simple view is created based on a single table.
- It contains no function or group data
- We can perform DML operations through simple views.
CREATE TABLE EMP_VIEW_TAB (EMPLOYEE_ID NUMBER(6), FIRST_NAME VARCHAR2(20), LAST_NAME VARCHAR2(25), JOB_ID VARCHAR2(10), HIRE_DATE DATE, SALARY NUMBER(8,2), DEPARTMENT_ID NUMBER(4), CONSTRAINT EMP_VIEW_PK PRIMARY KEY(EMPLOYEE_ID) );
INSERT INTO EMP_VIEW_TAB SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, JOB_ID, HIRE_DATE, SALARY, DEPARTMENT_ID FROM EMPLOYEES ORDER BY EMPLOYEE_ID;
CREATE VIEW VW_EMP_DATA_SIMPLE AS SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, JOB_ID, HIRE_DATE, SALARY, DEPARTMENT_ID FROM EMP_VIEW_TAB;
SELECT * FROM VW_EMP_DATA_SIMPLE;
Querying data dictionary view:
SELECT VIEW_NAME, TEXT, VIEW_TYPE, READ_ONLY FROM USER_VIEWS WHERE VIEW_NAME = 'VW_EMP_DATA_SIMPLE';
DML operations through SIMPLE VIEW:
If we perform DML operation through simple views then ultimately it will impact the base table. Because view contains no data.
INSERT:
INSERT INTO VW_EMP_DATA_SIMPLE (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,JOB_ID,HIRE_DATE,SALARY,DEPARTMENT_ID) VALUES (209,'Steve','Smith','PU_CLERK',to_date('18-OCT-2003','DD-MON-YYYY'),1000,30);
Querying the inserted data in VIEW:
SELECT * FROM VW_EMP_DATA_SIMPLE WHERE EMPLOYEE_ID = 209;
Querying the inserted data in base table EMP_VIEW_TAB:
SELECT * FROM EMP_VIEW_TAB WHERE EMPLOYEE_ID = 209;
SELECT COUNT(1) COUNT_EMP FROM EMP_VIEW_TAB;
So we can check that through view data is ultimately inserted into base table.
UPDATE:
UPDATE VW_EMP_DATA_SIMPLE SET SALARY = 12000 WHERE EMPLOYEE_ID = 209;
Querying the updated data in base table EMP_VIEW_TAB:
SELECT * FROM EMP_VIEW_TAB WHERE EMPLOYEE_ID = 209;
DELETE:
DELETE VW_EMP_DATA_SIMPLE WHERE EMPLOYEE_ID = 209;
Querying the deleted data in base table EMP_VIEW_TAB:
SELECT * FROM EMP_VIEW_TAB WHERE EMPLOYEE_ID = 209;
COMPLEX VIEW:
- A view is usually called COMPLEX VIEW when it contains one of the following:
- More than one table's data
- Contains functions in its definition query
- Contains grouping data
- Contains DISTINCT keyword
- Contains ROWNUM pseudocolumn
- COMPLEX VIEW does not allow DML operations always
COMPLEX VIEW created on multiple tables:
CREATE VIEW VW_EMP_DATA_COMPLEX_MULT_TAB AS SELECT A.EMPLOYEE_ID, A.FIRST_NAME, A.LAST_NAME, A.JOB_ID, A.HIRE_DATE, A.SALARY, A.DEPARTMENT_ID, B.DEPARTMENT_NAME, B.LOCATION_ID FROM EMP_VIEW_TAB A, DEPARTMENTS B WHERE A.DEPARTMENT_ID = B.DEPARTMENT_ID ORDER BY A.EMPLOYEE_ID;
SELECT * FROM VW_EMP_DATA_COMPLEX_MULT_TAB;
COMPLEX VIEW created with Function:
CREATE VIEW VW_EMP_DATA_COMPLEX_FUN AS SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, JOB_ID, TO_CHAR(HIRE_DATE, 'DD-MON-RRRR HH24:MI:SS') HIRE_DATE, SALARY, DEPARTMENT_ID FROM EMP_VIEW_TAB;
SELECT * FROM VW_EMP_DATA_COMPLEX_FUN;
COMPLEX VIEW created with Grouping data:
CREATE VIEW VW_EMP_DATA_COMPLEX_GROUP AS SELECT DEPARTMENT_ID, COUNT(EMPLOYEE_ID) NO_OF_EMPLOYEES, MIN(HIRE_DATE) OLDEST_HIRE_DATE, MAX(HIRE_DATE) LATEST_HIRE_DATE, MIN(SALARY) LOWEST_SALARY, MAX(SALARY) HIGHEST_SALARY, ROUND(AVG(SALARY), 0) AVERAGE_SALARY, SUM(SALARY) TOTAL_SALARY FROM EMP_VIEW_TAB GROUP BY DEPARTMENT_ID ORDER BY DEPARTMENT_ID;
SELECT * FROM VW_EMP_DATA_COMPLEX_GROUP;
COMPLEX VIEW created with DISTINCT keyword:
CREATE VIEW VW_EMP_DATA_COMPLEX_DISTINCT AS SELECT DISTINCT A.DEPARTMENT_ID, B.DEPARTMENT_NAME, B.LOCATION_ID FROM EMP_VIEW_TAB A, DEPARTMENTS B WHERE A.DEPARTMENT_ID = B.DEPARTMENT_ID ORDER BY A.DEPARTMENT_ID;
SELECT * FROM VW_EMP_DATA_COMPLEX_DISTINCT;
COMPLEX VIEW created with ROWNUM pseudocolumn:
CREATE OR REPLACE VIEW VW_EMP_DATA_COMPLEX_ROWNUM AS SELECT ROWNUM SLNO, EMPLOYEE_ID, FIRST_NAME, LAST_NAME, JOB_ID, HIRE_DATE, SALARY, DEPARTMENT_ID FROM EMP_VIEW_TAB;
SELECT * FROM VW_EMP_DATA_COMPLEX_ROWNUM;
DML operations through COMPLEX VIEW:
INSERT:
INSERT INTO VW_EMP_DATA_COMPLEX_FUN (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,JOB_ID,HIRE_DATE,SALARY,DEPARTMENT_ID) VALUES (209,'Steve','Smith','PU_CLERK',to_date('18-OCT-2003 00:00:00','DD-MON-YYYY HH24:MI:SS'),1000,30);
Now trying to insert data without HIRE_DATE column:
INSERT INTO VW_EMP_DATA_COMPLEX_FUN (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,JOB_ID,SALARY,DEPARTMENT_ID) VALUES (209,'Steve','Smith','PU_CLERK',1000,30);
SELECT * FROM VW_EMP_DATA_COMPLEX_FUN WHERE EMPLOYEE_ID = 209;
So without HIRE_DATE data has been inserted.
Another example of INSERT operation:
SELECT * FROM VW_EMP_DATA_COMPLEX_ROWNUM;
INSERT INTO VW_EMP_DATA_COMPLEX_ROWNUM (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,JOB_ID,HIRE_DATE, SALARY,DEPARTMENT_ID) VALUES (209,'Steve','Smith','PU_CLERK',TO_DATE('18-OCT-2003', 'DD-MON-YYYY'), 1000,30);
UPDATE:
SELECT * FROM VW_EMP_DATA_COMPLEX_FUN WHERE EMPLOYEE_ID = 208;
UPDATE VW_EMP_DATA_COMPLEX_FUN SET SALARY = 1200 WHERE EMPLOYEE_ID = 208;
Since the view VW_EMP_DATA_COMPLEX_FUN does not contain any function on SALARY column, so its allowing the update operation.
SELECT * FROM VW_EMP_DATA_COMPLEX_FUN WHERE EMPLOYEE_ID = 208;
Trying to update HIRE_DATE column:
UPDATE VW_EMP_DATA_COMPLEX_FUN SET HIRE_DATE = '18-OCT-2004' WHERE EMPLOYEE_ID = 208;
So its not allowing to update HIRE_DATE column as it has a function in its definition.
Another example of UPDATE operation:
SELECT * FROM VW_EMP_DATA_COMPLEX_ROWNUM WHERE EMPLOYEE_ID = 208;
UPDATE VW_EMP_DATA_COMPLEX_ROWNUM SET SALARY = 1200 WHERE EMPLOYEE_ID = 208;
DELETE:
DELETE VW_EMP_DATA_COMPLEX_ROWNUM WHERE EMPLOYEE_ID = 208;
Rules for performing DML transactions on VIEW:
- SIMPLE VIEW
- The base table should not have any NOT NULL column which is excluded in VIEW definition
- COMPLEX VIEW
- View does not contain any GROUP BY clause
- View does not contain group function
- View does not contain DISTINCT keyword
- View does not contain ROWNUM pseudocolumn
- View does not contain any column defined as an expression
Creating VIEW with different column name from Base Table:
CREATE VIEW VW_EMP_DATA_DIFF_COL_NAME (EMPID, FNAME, LNAME, JOBID, DOJ, SAL, DEPTID ) AS SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, JOB_ID, HIRE_DATE, SALARY, DEPARTMENT_ID FROM EMP_VIEW_TAB;
SELECT * FROM VW_EMP_DATA_DIFF_COL_NAME;
Modifying a VIEW:
VIEW can be modified with CREATE OR REPLACE statement.
We have a view VW_EMP_DATA_SIMPLE with below columns:
Now we want to add FULL_NAME column in the above view without dropping it.
CREATE OR REPLACE VIEW VW_EMP_DATA_SIMPLE AS SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, FIRST_NAME||' '||LAST_NAME FULL_NAME, JOB_ID, HIRE_DATE, SALARY, DEPARTMENT_ID FROM EMP_VIEW_TAB;
SELECT * FROM VW_EMP_DATA_SIMPLE;
WITH CHECK OPTION in a VIEW:
We can enable referential integrity constraint through VIEW. It is done through WITH CHECK OPTION clause.
CREATE VIEW VW_EMP_DATA_DEPT_30 AS SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, JOB_ID, HIRE_DATE, SALARY, DEPARTMENT_ID FROM EMP_VIEW_TAB WHERE DEPARTMENT_ID = 30 WITH CHECK OPTION CONSTRAINT DEPT_CHECK_30;
We have created a view VW_EMP_DATA_DEPT_30 which is having data of DEPARTMENT_ID 30 only.
SELECT * FROM VW_EMP_DATA_DEPT_30;
Querying data dictionary:
SELECT VIEW_NAME, TEXT, VIEW_TYPE, READ_ONLY FROM USER_VIEWS WHERE VIEW_NAME = 'VW_EMP_DATA_DEPT_30';
SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME, STATUS FROM USER_CONSTRAINTS WHERE CONSTRAINT_NAME = 'DEPT_CHECK_30';
Trying to insert and update data through view VW_EMP_DATA_DEPT_30 when DEPARTMENT_ID is not equals to 30:
INSERT INTO VW_EMP_DATA_DEPT_30 (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,JOB_ID,HIRE_DATE,SALARY,DEPARTMENT_ID) VALUES (209,'Tom','Kyte','PU_CLERK',to_date('18-OCT-2003','DD-MON-YYYY'),1000,20);
SELECT * FROM VW_EMP_DATA_DEPT_30;
But if try to insert any data for DEPARTMENT_ID 20 then oracle will allow that
INSERT INTO VW_EMP_DATA_DEPT_30 (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,JOB_ID,HIRE_DATE,SALARY,DEPARTMENT_ID) VALUES (209,'Tom','Kyte','PU_CLERK',to_date('18-OCT-2003','DD-MON-YYYY'),1000,30);
SELECT * FROM VW_EMP_DATA_DEPT_30;
Updating DEPARTMENT_ID with value other than 30:
UPDATE VW_EMP_DATA_DEPT_30 SET DEPARTMENT_ID = 20 WHERE EMPLOYEE_ID = 209;
But if try to update any data for DEPARTMENT_ID 30 then oracle will allow that:
UPDATE VW_EMP_DATA_DEPT_30 SET DEPARTMENT_ID = 30 WHERE EMPLOYEE_ID = 114;
SELECT * FROM VW_EMP_DATA_DEPT_30;
ROLLBACK;
WITH READ ONLY Option in a VIEW:
We can restrict DML operation in VIEWS through WITH READ ONLY option. This clause indicates that the view is created with read only option and no write operation is allowed. If we try to do any DML operation on this view then oracle will raise an error.
CREATE VIEW VW_EMP_DATA_DEPT_30_READ_ONLY AS SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, JOB_ID, HIRE_DATE, SALARY, DEPARTMENT_ID FROM EMP_VIEW_TAB WHERE DEPARTMENT_ID = 30 WITH READ ONLY CONSTRAINT DEPT_READ_ONLY_30;
SELECT * FROM VW_EMP_DATA_DEPT_30_READ_ONLY;
Querying data dictionary:
SELECT VIEW_NAME, TEXT, VIEW_TYPE, READ_ONLY FROM USER_VIEWS WHERE VIEW_NAME = 'VW_EMP_DATA_DEPT_30_READ_ONLY';
SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE, TABLE_NAME, STATUS FROM USER_CONSTRAINTS WHERE CONSTRAINT_NAME = 'DEPT_READ_ONLY_30';
Trying to insert another data into view VW_EMP_DATA_DEPT_30_READ_ONLY for DEPARTMENT_ID 30:
INSERT INTO VW_EMP_DATA_DEPT_30_READ_ONLY (EMPLOYEE_ID,FIRST_NAME,LAST_NAME,JOB_ID,HIRE_DATE,SALARY,DEPARTMENT_ID) VALUES (209,'Tom','Kyte','PU_CLERK',to_date('18-OCT-2003','DD-MON-YYYY'),1000,30);
Trying to update any record:
UPDATE VW_EMP_DATA_DEPT_30_READ_ONLY SET DEPARTMENT_ID = 30 WHERE EMPLOYEE_ID = 208;
Trying to delete any record from view VW_EMP_DATA_DEPT_30_READ_ONLY:
DELETE VW_EMP_DATA_DEPT_30_READ_ONLY WHERE EMPLOYEE_ID = 208;
So oracle is not allowing to any DML operation on a READ ONLY VIEW.
Removing a VIEW:
DROP VIEW VW_EMP_DATA_DEPT_30_READ_ONLY;
Inline VIEWs:
Inline View is a subquery which can be used in :
- AS A COLUMN OF A SELECT STATEMENT
- AS A TABLE IN FROM CLAUSE
Inline view is not a database object. It exists in the select statement only.
AS A COLUMN OF A SELECT STATEMENT
SELECT A.EMPLOYEE_ID, A.FIRST_NAME, A.LAST_NAME, A.JOB_ID, A.SALARY, A.DEPARTMENT_ID, (SELECT DEPARTMENT_NAME FROM DEPARTMENTS WHERE DEPARTMENT_ID = A.DEPARTMENT_ID) DEPARTMENT_NAME, (SELECT SUM(SALARY) FROM EMPLOYEES WHERE DEPARTMENT_ID = A.DEPARTMENT_ID) DEPT_TOTAL_SAL, (SELECT MAX(SALARY) FROM EMPLOYEES WHERE DEPARTMENT_ID = A.DEPARTMENT_ID) DEPT_MAX_SAL, (SELECT MIN(SALARY) FROM EMPLOYEES WHERE DEPARTMENT_ID = A.DEPARTMENT_ID) DEPT_MIN_SAL FROM EMPLOYEES A WHERE A.DEPARTMENT_ID IN (10, 20, 30) ORDER BY A.DEPARTMENT_ID;
AS A TABLE IN FROM CLAUSE
SELECT A.EMPLOYEE_ID, A.FIRST_NAME, A.LAST_NAME, A.JOB_ID, A.SALARY, A.DEPARTMENT_ID, B.DEPARTMENT_NAME, B.DEPT_TOTAL_SAL, B.DEPT_MAX_SAL, B.DEPT_MIN_SAL FROM EMPLOYEES A, (SELECT P.DEPARTMENT_ID, Q.DEPARTMENT_NAME, SUM(P.SALARY) DEPT_TOTAL_SAL, MAX(P.SALARY) DEPT_MAX_SAL, MIN(P.SALARY) DEPT_MIN_SAL FROM EMPLOYEES P, DEPARTMENTS Q WHERE P.DEPARTMENT_ID = Q.DEPARTMENT_ID GROUP BY P.DEPARTMENT_ID, Q.DEPARTMENT_NAME ) B WHERE A.DEPARTMENT_ID IN (10, 20, 30) AND A.DEPARTMENT_ID = B.DEPARTMENT_ID ORDER BY A.DEPARTMENT_ID;
Top – n Analysis:
Top – n analysis helps us to extract top n records of a table based on a column.
In the below example we can see the list of employees in descending order of SALARY column.
SELECT A.EMPLOYEE_ID, A.FIRST_NAME, A.LAST_NAME, A.JOB_ID, A.SALARY, A.DEPARTMENT_ID FROM EMPLOYEES A ORDER BY A.SALARY DESC;
Now we want to show the top 5 employees having highest salaries. For that we will use the TOP – n analysis.
Showing the top 5 salaries:
SELECT ROW_NUM RANK, EMPLOYEE_ID, FIRST_NAME, LAST_NAME, JOB_ID, SALARY, DEPARTMENT_ID FROM( SELECT ROWNUM ROW_NUM, A.EMPLOYEE_ID, A.FIRST_NAME, A.LAST_NAME, A.JOB_ID, A.SALARY, A.DEPARTMENT_ID FROM (SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, JOB_ID, SALARY, DEPARTMENT_ID FROM EMPLOYEES P ORDER BY SALARY DESC ) A ) WHERE ROW_NUM <= 5;
Showing the 3rd highest salary:
SELECT ROW_NUM RANK, EMPLOYEE_ID, FIRST_NAME, LAST_NAME, JOB_ID, SALARY, DEPARTMENT_ID FROM( SELECT ROWNUM ROW_NUM, A.EMPLOYEE_ID, A.FIRST_NAME, A.LAST_NAME, A.JOB_ID, A.SALARY, A.DEPARTMENT_ID FROM (SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, JOB_ID, SALARY, DEPARTMENT_ID FROM EMPLOYEES P ORDER BY SALARY DESC ) A ) WHERE ROW_NUM = 3;
Showing the 5th highest salary:
SELECT ROW_NUM RANK, EMPLOYEE_ID, FIRST_NAME, LAST_NAME, JOB_ID, SALARY, DEPARTMENT_ID FROM( SELECT ROWNUM ROW_NUM, A.EMPLOYEE_ID, A.FIRST_NAME, A.LAST_NAME, A.JOB_ID, A.SALARY, A.DEPARTMENT_ID FROM (SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, JOB_ID, SALARY, DEPARTMENT_ID FROM EMPLOYEES P ORDER BY SALARY DESC ) A ) WHERE ROW_NUM = 5;
Showing the 1st and 5th highest salaries:
SELECT ROW_NUM RANK, EMPLOYEE_ID, FIRST_NAME, LAST_NAME, JOB_ID, SALARY, DEPARTMENT_ID FROM( SELECT ROWNUM ROW_NUM, A.EMPLOYEE_ID, A.FIRST_NAME, A.LAST_NAME, A.JOB_ID, A.SALARY, A.DEPARTMENT_ID FROM (SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, JOB_ID, SALARY, DEPARTMENT_ID FROM EMPLOYEES P ORDER BY SALARY DESC ) A ) WHERE ROW_NUM IN (1, 5);
RELATED TOPICS: