VIEWS IN SQL SERVER



VIEWS IN SQL SERVER


A View is a method of Encapsulating a Complex query into a simple form, For example, your Client has no idea how to write  Complex Queries with multiple joins, Aggregate functions, and Complex SQL Functions, so you can create a View and now your client has to run a SIMPLE select statement against a view and the problem is solved.

A view can be used to Focus on Specific data or a view can be used to Simplify Complex data which can be presented in a simple format and the view can be used to Customize data




VIEWS AS A SECURITY OPTION (ROW-LEVEL SECURITY)

Suppose you have got a request from the “HR” team to share the list of all the employees working in the “HR” Departments. Now your Departments table has data for other Departments as well such as “IT” and  “PAYROLL”, so it’s obvious that you cannot share the table name with the “HR” team, instead you can create a view and in that view, YOU can include only department ID “HR” and share the view name with the HR team.

This can provide a way to hide sensitive information from the users, in this case, you are hiding “IT” and “payroll” department information from “HR” guys.

This is also known as row-level security where you want a specific department to see the information which they are intended to see and hide information related to other departments.


IF OBJECT_ID(N'DEPARTMENTS', N'U') IS NOT NULL           
DROP TABLE DEPARTMENTS;
IF OBJECT_ID(N'VW_DEPARTMENTS_HR', N'V') IS NOT NULL           
DROP VIEW VW_DEPARTMENTS_HR;
CREATE TABLE DEPARTMENTS
(EMP_NAME VARCHAR(20),DEPARTMENTS VARCHAR(20),SALARY INT);
INSERT INTO DEPARTMENTS VALUES
('ROB','HR',5000),('RAY','IT',7000),('ROB','PAYROLL',5000);
GO
CREATE VIEW VW_DEPARTMENTS_HR
AS
SELECT * FROM DEPARTMENTS WHERE DEPARTMENTS='HR';
GO
SELECT * FROM VW_DEPARTMENTS_HR;


VIEWS AS A SECURITY OPTION (COLUMN-LEVEL SECURITY)

Suppose you have got a request from the HR team and you need to share the list of all the employees working in the HR department but in the department’s table, you also have the salary column and you don’t want to share the salaries of employees working in the HR department


IF OBJECT_ID(N'DEPARTMENTS', N'U') IS NOT NULL           
DROP TABLE DEPARTMENTS;
IF OBJECT_ID(N'VW_DEPARTMENTS_HR', N'V') IS NOT NULL           
DROP VIEW VW_DEPARTMENTS_HR;
CREATE TABLE DEPARTMENTS
(EMP_NAME VARCHAR(20),DEPARTMENTS VARCHAR(20),SALARY INT);
INSERT INTO DEPARTMENTS VALUES
('ROB','HR',5000),('RAY','IT',7000),('ROB','PAYROLL',5000);
GO
CREATE VIEW VW_DEPARTMENTS_HR
AS
SELECT EMP_NAME,DEPARTMENTS--,SALARY /*Hiding the salary Column/*
FROM DEPARTMENTS WHERE DEPARTMENTS='HR';
GO
SELECT * FROM VW_DEPARTMENTS_HR;



WITH CHECK OPTION

WITH CHECK OPTION allows the view to check that all modifications to data through the view should fall within the scope of the view.

In the below example, we have created a view with the condition in where clause “WHERE Location_ID=1” so now if we try to update the view and try to update the location_Id =2 where location_Id = 1 then without the WITH CHECK OPTION all the Location_ID which were previously Equals to 1 now becomes 2, remember? our view is made from the where condition “Where Location_Id=1” so in this case when all the Location_Ids are updated to 2 the existence of the view vanishes. to stop this kind of behavior we use WITH CHECK OPTION.

With “WITH CHECK OPTION” in place, SQL Server will throw an error as shown in the screenshot below and will not allow us to update the Location_ID from 1 to 2.

The attempted insert or update failed because the target view either specifies WITH CHECK OPTION or spans a view that specifies WITH CHECK OPTION and one or more rows resulting from the operation did not qualify under the CHECK OPTION constraint





IF OBJECT_ID(N'products', N'U') IS NOT NULL DROP TABLE products; IF OBJECT_ID(N'PRODUCTS_WITH_CHECK_OPTION', N'V') IS NOT NULL DROP VIEW PRODUCTS_WITH_CHECK_OPTION; create table products (Location_ID int,Location_Name varchar(20)); insert into products values (1,'USA'),(2,'CHINA'),(3,'INDIA'),(4,'USA'); SELECT * FROM PRODUCTS; GO CREATE VIEW PRODUCTS_WITH_CHECK_OPTION AS SELECT * FROM PRODUCTS WHERE Location_ID=1 WITH CHECK OPTION; GO SELECT * FROM PRODUCTS_WITH_CHECK_OPTION; UPDATE PRODUCTS_WITH_CHECK_OPTION SET Location_ID=5 WHERE Location_ID=1; SELECT * FROM PRODUCTS_WITH_CHECK_OPTION; SELECT * FROM PRODUCTS;


 

WITH ENCRYPTION

WITH ENCRYPTION allows you to hide the code of the View, 

View with “WITH ENCRYPTION ” Clause
IF OBJECT_ID(N'products', N'U') IS NOT NULL DROP TABLE products; IF OBJECT_ID(N'PRODUCTS_WITH_ENCRYPTION', N'V') IS NOT NULL DROP VIEW PRODUCTS_WITH_CHECK_OPTION; create table products (Location_ID int,Location_Name varchar(20)); insert into products values (1,'USA'),(2,'CHINA'),(3,'INDIA'),(4,'USA'); GO CREATE VIEW PRODUCTS_WITH_ENCRYPTION WITH ENCRYPTION AS SELECT * FROM PRODUCTS WHERE Location_ID=1 ; GO SP_HELPTEXT PRODUCTS_WITH_ENCRYPTION






View without “WITH ENCRYPTION ” Clause
IF OBJECT_ID(N'products', N'U') IS NOT NULL DROP TABLE products; IF OBJECT_ID(N'PRODUCTS_WITHOUT_ENCRYPTION', N'V') IS NOT NULL DROP VIEW PRODUCTS_WITH_CHECK_OPTION; create table products (Location_ID int,Location_Name varchar(20)); insert into products values (1,'USA'),(2,'CHINA'),(3,'INDIA'),(4,'USA'); GO CREATE VIEW PRODUCTS_WITHOUT_ENCRYPTION --WITH ENCRYPTION AS SELECT * FROM PRODUCTS WHERE Location_ID=1 ; GO SP_HELPTEXT PRODUCTS_WITHOUT_ENCRYPTION





SCHEMABINDING option

SCHEMABINDING allows your VIEW to not get orphaned in case the base table is Dropped, Suppose you have created a view on a table and someone by mistake or intentionally drops the base table, what will happen to the view?

IF OBJECT_ID(N'PRODUCTS_WITH_SCHEMABINDING', N'V') IS NOT NULL DROP VIEW PRODUCTS_WITH_SCHEMABINDING; IF OBJECT_ID(N'products', N'U') IS NOT NULL DROP TABLE products; create table products (Location_ID int,Location_Name varchar(20)); insert into products values (1,'USA'),(2,'CHINA'),(3,'INDIA'),(4,'USA'); GO CREATE VIEW PRODUCTS_WITH_SCHEMABINDING WITH SCHEMABINDING AS SELECT Location_ID,Location_Name FROM DBO.PRODUCTS WHERE Location_ID=1 ;

Now if we try to drop the base table “PRODUCTS” then we will get the below error.

DROP TABLE products;






Materialized Views or Indexed Views

A Materialized or Indexed View is similar to a normal view, However, the Materialized view is stored in the database similar to an index on a table.

Please note that the view is still a virtual table, but the index on the view is physically stored in the database.

The first index on a Materialized view must be a clustered Index, after that, you can add a non-clustered index as well.

The view on which you want to create an index must be DETERMINISTIC. and PRECISE

Any Index created on a view should be created using WITH SCHEMABINDING Option

If you are using a GROUP BY Clause in a view then you can use only the columns which are used for Unique Clustered Index.



SPACE USED IN A NORMAL VIEW

In the below example, we are creating a normal view and will see how much space a normal view uses, a normal view is still a virtual table and will not take up any space in a database.

IF OBJECT_ID(N'Normal_View_Test', N'V') IS NOT NULL DROP VIEW Normal_View_Test GO IF OBJECT_ID(N'DBO.EMPLOYEES_Normal_View', N'U') IS NOT NULL DROP TABLE DBO.EMPLOYEES_Normal_View GO CREATE TABLE DBO.EMPLOYEES_Normal_View (ID INT PRIMARY KEY,F_NAME VARCHAR(20),L_NAME VARCHAR(20),SALARY INT,dept varchar(20)); INSERT INTO DBO.EMPLOYEES_Normal_View VALUES (1,'SHANE','RAY',5000,'IT'),(2,'JACK','STRONG',7000,'IT'),(3,'OLGER','PHILLIPS',9000,'HR'); select * from DBO.EMPLOYEES_Normal_View GO --NORMAL VIEW CREATE VIEW Normal_view_Test WITH SCHEMABINDING AS SELECT ID,F_NAME,L_NAME,SALARY,dept FROM DBO.EMPLOYEES_Normal_View GO SELECT * FROM Normal_view_Test GO sp_spaceused '[Normal_view_Test]' GO


 

SPACE USED IN A MATERIALIZED OR INDEXED VIEW

In the below example, we are creating a Deterministic Materialized view and will see how much space a Materialized view uses, a Materialized view is still a virtual table and but when a Unique Clustered Index is created on it, That index will be stored in the database like any other index on a table.

IF OBJECT_ID(N'Materialized_Test', N'V') IS NOT NULL DROP VIEW Materialized_Test GO IF OBJECT_ID(N'DBO.EMPLOYEES_Materialized_Test', N'U') IS NOT NULL DROP TABLE DBO.EMPLOYEES_Materialized_Test GO CREATE TABLE DBO.EMPLOYEES_Materialized_Test (ID INT PRIMARY KEY,F_NAME VARCHAR(20),L_NAME VARCHAR(20),SALARY INT,dept varchar(20)); INSERT INTO DBO.EMPLOYEES_Materialized_Test VALUES (1,'SHANE','RAY',5000,'IT'),(2,'JACK','STRONG',7000,'IT'),(3,'OLGER','PHILLIPS',9000,'HR'); select * from DBO.EMPLOYEES_Materialized_Test GO --Materialized VIEW WITH DETERMINISTIC FUNCTION CREATE VIEW Materialized_Test WITH SCHEMABINDING AS SELECT ID,F_NAME,L_NAME,SALARY,dept FROM DBO.EMPLOYEES_Materialized_Test GO SELECT * FROM Materialized_Test; DROP INDEX IF EXISTS ix_index on Materialized_Test CREATE UNIQUE CLUSTERED INDEX ix_index ON Materialized_Test(SALARY) GO sp_spaceused '[Materialized_Test]' GO


 

CAN WE USE A DETERMINISTIC FUNCTION IN A MATERIALIZED OR INDEXED VIEW

A Deterministic function will always return the same result on a given input value, In the below query we are using “SALARY+100” to get the incremented salary of an employee, this computed column is the deterministic column as adding something to the salary will always yield the same value. So in this case we will be able to create a view on a table with a Deterministic computed column without any issues.

IF OBJECT_ID(N'Deterministic_Materialized_Test', N'V') IS NOT NULL DROP VIEW Deterministic_Materialized_Test GO IF OBJECT_ID(N'DBO.EMPLOYEES_Deterministic_Materialized_Test', N'U') IS NOT NULL DROP TABLE DBO.EMPLOYEES_Deterministic_Materialized_Test GO CREATE TABLE DBO.EMPLOYEES_Deterministic_Materialized_Test (ID INT PRIMARY KEY,F_NAME VARCHAR(20),L_NAME VARCHAR(20),SALARY INT,dept varchar(20)); INSERT INTO DBO.EMPLOYEES_Deterministic_Materialized_Test VALUES (1,'SHANE','RAY',5000,'IT'),(2,'JACK','STRONG',7000,'IT'),(3,'OLGER','PHILLIPS',9000,'HR'); select * from DBO.EMPLOYEES_Deterministic_Materialized_Test GO --Materialized VIEW WITH DETERMINISTIC FUNCTION CREATE VIEW Deterministic_Materialized_Test WITH SCHEMABINDING AS SELECT ID,F_NAME,L_NAME,SALARY,dept, salary+100 incremented_salary FROM DBO.EMPLOYEES_Deterministic_Materialized_Test GO SELECT * FROM Deterministic_Materialized_Test; DROP INDEX IF EXISTS ix_index on Deterministic_Materialized_Test CREATE UNIQUE CLUSTERED INDEX ix_index ON Deterministic_Materialized_Test(SALARY) GO sp_spaceused '[Deterministic_Materialized_Test]' GO


 

CAN WE USE A NON-DETERMINISTIC FUNCTION IN A MATERIALIZED OR INDEXED VIEW

A Deterministic function will always return the same result on a given input value, In the below query we are using “SALARY+100” to get the incremented salary of an employee, this computed column is the deterministic column as adding something to the salary will always yield the same value. So in this case we will be able to create a view on a table with a Deterministic computed column without any issues.

IF OBJECT_ID(N'NONDETERMINISTIC_Materialized_Test', N'V') IS NOT NULL DROP VIEW NONDETERMINISTIC_Materialized_Test GO IF OBJECT_ID(N'DBO.EMPLOYEES_NONDeterministic_Materialized_Test', N'U') IS NOT NULL DROP TABLE DBO.EMPLOYEES_NONDeterministic_Materialized_Test GO CREATE TABLE DBO.EMPLOYEES_NONDeterministic_Materialized_Test (ID INT PRIMARY KEY,F_NAME VARCHAR(20),L_NAME VARCHAR(20),SALARY INT,dept varchar(20)); INSERT INTO DBO.EMPLOYEES_NONDeterministic_Materialized_Test VALUES (1,'SHANE','RAY',5000,'IT'),(2,'JACK','STRONG',7000,'IT'),(3,'OLGER','PHILLIPS',9000,'HR'); select * from DBO.EMPLOYEES_NONDeterministic_Materialized_Test GO --Materialized VIEW WITH NON-PRECISE FUNCTION CREATE VIEW NONDETERMINISTIC_Materialized_Test WITH SCHEMABINDING AS SELECT ID,F_NAME,L_NAME,SALARY,dept,GETDATE() Tdy_date FROM DBO.EMPLOYEES_NONDeterministic_Materialized_Test GO SELECT * FROM NONDETERMINISTIC_Materialized_Test; DROP INDEX IF EXISTS ix_index on NONDETERMINISTIC_Materialized_Test CREATE UNIQUE CLUSTERED INDEX ix_index ON NONDETERMINISTIC_Materialized_Test(SALARY) GO sp_spaceused '[NONDETERMINISTIC_Materialized_Test]'


 

CAN WE USE A NONPRECISE FUNCTION IN A MATERIALIZED OR INDEXED VIEW

A Deterministic function will always return the same result on a given input value, In the below query we are using “SALARY+100” to get the incremented salary of an employee, this computed column is the deterministic column as adding something to the salary will always yield the same value. So in this case we will be able to create a view on a table with a Deterministic computed column without any issues.

IF OBJECT_ID(N'NONPRECISE_Materialized_Test', N'V') IS NOT NULL DROP VIEW NONPRECISE_Materialized_Test GO IF OBJECT_ID(N'DBO.EMPLOYEES_NONPRECISE_Materialized_Test', N'U') IS NOT NULL DROP TABLE DBO.EMPLOYEES_NONPRECISE_Materialized_Test GO CREATE TABLE DBO.EMPLOYEES_NONPRECISE_Materialized_Test (ID INT PRIMARY KEY,F_NAME VARCHAR(20),L_NAME VARCHAR(20),SALARY INT,dept varchar(20)); INSERT INTO DBO.EMPLOYEES_NONPRECISE_Materialized_Test VALUES (1,'SHANE','RAY',5000,'IT'),(2,'JACK','STRONG',7000,'IT'),(3,'OLGER','PHILLIPS',9000,'HR'); select * from DBO.EMPLOYEES_NONPRECISE_Materialized_Test GO --Materialized VIEW WITH NON-PRECISE FUNCTION CREATE VIEW NONPRECISE_Materialized_Test WITH SCHEMABINDING AS SELECT ID,F_NAME,L_NAME,SALARY*CAST(.009 AS FLOAT) SALARY,dept FROM DBO.EMPLOYEES_NONPRECISE_Materialized_Test GO SELECT * FROM NONPRECISE_Materialized_Test; DROP INDEX IF EXISTS ix_index on NONPRECISE_Materialized_Test CREATE UNIQUE CLUSTERED INDEX ix_index ON NONPRECISE_Materialized_Test(SALARY) GO sp_spaceused '[NONPRECISE_Materialized_Test]'


 

Partitioned View

A Materialized or Indexed

IF OBJECT_ID(N'ORDER_MONTH', N'V') IS NOT NULL DROP VIEW ORDER_MONTH; IF OBJECT_ID(N'ORDERS', N'U') IS NOT NULL DROP TABLE ORDERS; IF OBJECT_ID(N'ORDERS_JAN', N'U') IS NOT NULL DROP TABLE ORDERS_JAN; IF OBJECT_ID(N'ORDERS_FEB', N'U') IS NOT NULL DROP TABLE ORDERS_FEB; IF OBJECT_ID(N'ORDERS_MAR', N'U') IS NOT NULL DROP TABLE ORDERS_MAR; CREATE TABLE ORDERS(order_id INT,order_name VARCHAR(30),order_date VARCHAR(30),order_month VARCHAR(30)); CREATE TABLE ORDERS_JAN(order_id INT,order_name VARCHAR(30),order_date VARCHAR(30),order_month SMALLINT NOT NULL CONSTRAINT CK_OM_M1 CHECK (order_month = 1) CONSTRAINT PK_MONTH1 PRIMARY KEY (order_id, order_month)); CREATE TABLE ORDERS_FEB(order_id INT,order_name VARCHAR(30),order_date VARCHAR(30),order_month SMALLINT NOT NULL CONSTRAINT CK_OM_M2 CHECK (order_month = 2) CONSTRAINT PK_MONTH2 PRIMARY KEY (order_id, order_month)); CREATE TABLE ORDERS_MAR(order_id INT,order_name VARCHAR(30),order_date VARCHAR(30),order_month SMALLINT NOT NULL CONSTRAINT CK_OM_M3 CHECK (order_month = 3) CONSTRAINT PK_MONTH3 PRIMARY KEY (order_id, order_month)); SELECT * FROM ORDERS; SELECT * FROM ORDERS_JAN; SELECT * FROM ORDERS_FEB; SELECT * FROM ORDERS_MAR; CREATE VIEW ORDER_MONTH WITH SCHEMABINDING AS SELECT order_id,order_name,order_date,order_month FROM DBO.ORDERS_JAN UNION ALL SELECT order_id,order_name,order_date,order_month FROM DBO.ORDERS_FEB UNION ALL SELECT order_id,order_name,order_date,order_month FROM DBO.ORDERS_MAR; GO INSERT INTO DBO.ORDER_MONTH VALUES(111,'MUK',GETDATE(),1) INSERT INTO DBO.ORDER_MONTH VALUES(222,'RAJ',GETDATE(),2) INSERT INTO DBO.ORDER_MONTH VALUES(333,'JAI',GETDATE(),3) INSERT INTO DBO.ORDER_MONTH VALUES(444,'SAI',GETDATE(),1) SELECT * FROM ORDERS; SELECT * FROM ORDERS_JAN; SELECT * FROM ORDERS_FEB; SELECT * FROM ORDERS_MAR;


 

Note

  • Triggers can be created in Views

Post a Comment

0 Comments