0% found this document useful (0 votes)
38 views

SQL Server Student Guide-2

Uploaded by

Madhaw Shukla
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
38 views

SQL Server Student Guide-2

Uploaded by

Madhaw Shukla
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 112

Trademark Acknowledgements

All products are registered trademarks of their respective


organizations.All software is used for educational
purposes only.

QDUS - II_SG /12-M11-V01


Copyright ©NIIT. All rights reserved.

No part of this publication may be reproduced, stored in


retrieval system or transmitted in any form, or by any
means, electronic, mechanical, photocopying, recording or
otherwise, without the prior written permission of the
publisher.
After completing this course, the students should be able
to:
 Query and manage databases using SQL Server.
About This Course
Conventions
Prologue
Convention Indicates...
Description Note
The Querying Data Using SQL Server - II course is
designed to provide students the necessary skills to query Animation
and manage databases using SQL Server. The course starts
with an introduction to client-server architecture and an
overview of SQL Server. Next, it familiarizes the students Exercise in Activity Book
with Structured Query Language (SQL) and builds on the
complexity of query handling in SQL Server with every Just a Minute
progressing session. It also introduces the students to some
advanced concepts in SQL Server such as implementing
managed code and implementing services for message-
based communication.

Rationale
Databases are an integral part of an organization. Aspiring
database developers should be able to efficiently
implement and maintain databases. This knowledge will
enable them to build robust database solutions.

Objectives
After completing this course, the student should be able to:
 Identify SQL Server tools
 Query data from a single table
 Query data from multiple tables
 Manage databases and tables
 Manipulate data in tables
 Implement indexes, views, and full-text search
 Implement stored procedures and functions
 Implement triggers and transactions
 Implement managed code
 Implement services for message-based
communication

Entry Profile
The students who want to take this course should have:
 Knowledge of RDBMS concepts.
 Basic knowledge of computers.

Exit Profile
the data is to be inserted. The INTO keyword is optional.
column_list specifies an optional parameter. You can
use it when partial data is to be inserted in a table or when
Chapter 5 the columns to be inserted are defined in a different order.
DEFAULT specifies the clause that you can use to insert
Manipulating Data in Tables the default value specified for the column. If a default
value is not specified for a column and the column
After creating a database and tables, the next step is to property is specified as NULL, NULL is inserted in the
store data in the database. As a database developer, you column. If the column does not have any default constraint
will be required to update or delete data. You can perform attached to it and does not allow NULL as the column
these data manipulations by using the DML statements of value, SQL Server returns an error message and the insert
T-SQL. operation is rejected.
The data stored in the database can be used by different values_list specifies the list of values for the table
types of client applications, such as mobile devices or Web columns that have to be inserted as a row in the table. If a
applications. Therefore, data should be stored in a format column has to contain a default value, you can use the
that can be interpreted by any application. For this, SQL DEFAULT keyword instead of a column value. The
Server allows you to store data in the XML format that can column value can also be an expression.
be read by any application. select_statement specifies a nested SELECT
This chapter discusses how to use the DML statements to statement that you can use to insert rows into the table.
manipulate data in the tables. In addition, it explains how
to manipulate the XML data in the database tables. Guidelines for Inserting Rows
While inserting rows into a table, you need to consider the
Objectives following guidelines:
 The number of data values must be the same as
In this chapter, you will learn to: the number of attributes in the table or column
 Manipulate data by using DML statements list.
 Manipulate XML data  The order of inserting the information must be the
same as the order in which attributes are listed for
insertion.
Manipulating Data by Using DML  The values clause need not contain the column
Statements with the IDENTITY property.
 The data types of the information must match the
As a database developer, you need to regularly insert, data types of the columns of the table.
update, or delete data. These operations ensure that the Consider an example of the EmpData table that is used to
data is up-to-date. For example, you need to insert new store the details of the employees.
records in the Employee table whenever a new employee The following table describes the structure of the
joins the organization. EmpData table.
Similarly, if the details of an employee change, you need
to update the existing records. For example, if the salary of
Column Name Data Type Checks
any employee increases, you need to update the existing
records to reflect this change. EmpName varchar(20) NULL
You can use the DML statements to manipulate the data in EmpNo Int NOT NULL
any table. EmpAddress varchar(60) NULL
Salary Int NULL

Storing Data in a Table The Structure of the EmpData Table


The smallest unit of data that you can add in a table is a
To insert a row into the EmpData table with all the column
row. You can add a row by using the INSERT statement.
values, you can use any one of the following statements:
The syntax of the INSERT statement is:
INSERT EmpData
INSERT [INTO]{table_name}
VALUES ('Yang Kan', 101, '123 Nanjing
[(column_list)]
Lu', 2500)
VALUES {DEFAULT | values_list |
select_statement} Or
INSERT EmpData (EmpName, EmpAddress,
where,
EmpNo, Salary)
table_name specifies the name of the table into which
VALUES ('Yang Kan', '123 Nanjing Lu', HumanResources.EmployeePayHistory tables. To save the
101, 2500) details for a new employee, you need to insert data in all
Or these tables.
INSERT EmpData (EmpName, EmpAddress, The following statements insert data of a new employee
Salary, EmpNo) into the database:
VALUES ('Yang Kan', '123 Nanjing Lu', -- inserting records in the
2500, 101) Person.Contact table
You need to execute an INSERT statement for each row INSERT INTO Person.Contact VALUES (0,
being inserted into a table. However, you can insert 'Mr.', 'Steven', NULL, 'Fleming',
multiple rows into a table by using the T-SQL row NULL, 'stevenfleming@adventure-
constructor. The row constructor allows multiple rows of works.com', 1,
data to be specified in a single INSERT statement. '951-667-2401',
For example, the following statement inserts three rows in 'B4802B37F8F077A6C1F2C3F50F6CD6C5379E9
the EmpData table by using the row constructor: C79', '3sa+edf=', NULL, DEFAULT,
INSERT EmpData (EmpName, EmpAddress, DEFAULT)
Salary, EmpNo) -- inserting records in the
VALUES ('John', '123 Nanjing Lu', HumanResources.Employee table
3500, 102), INSERT INTO HumanResources.Employee
('Michel', '124 Nanjing Lu', 2200, VALUES ('45879632', 19978,
103), 'adventure-works\steven', 185, 'Tool
('Shelda', '693 Park Street', 3500, Designer', '1967-06-03
104) 00:00:00.000','M', 'M', '2006-08-01
00:00:00.000', 1, 0, 0, 1, DEFAULT,
Inserting Partial Data DEFAULT)
Depending on the constraints applied to the columns of the
-- inserting records in the
tables, you can insert partial data into the database tables. HumanResources.EmployeeDepartmentHisto
This means that while performing an insert operation it is ry table
not necessary to insert values for all the columns in the INSERT INTO
table. HumanResources.EmployeeDepartmentHisto
SQL server allows you to insert data in selected columns, ry VALUES (291, 2, 1, '2006-08-01
leaving those columns that allow NULL or have a default 00:00:00.000', NULL, DEFAULT)
constraint assigned to them. While inserting data, you -- inserting records in the
need to specify the column names for which data is to be HumanResources.EmployeePayHistory
inserted by using the INSERT statement. The VALUES table
clause provides values for the specified columns only. INSERT INTO
In EmpData table, the EmpAddress column allows you to HumanResources.EmployeePayHistory
enter a NULL value in a row. Therefore, you can use the VALUES (291,
following statements to insert partial data into the table: '2006-08-01 00:00:00.000', 23.0769, 2,
INSERT EmpData DEFAULT)
VALUES ('Yang Kan', 101, NULL, 2500) In the preceding statements, the Person.Contact table
Or contains the ContactID column, which is a foreign key in
INSERT EmpData (EmpName, EmpNo, the HumanResources.Employee table. Once you have
Salary) inserted a record in the Person.Contact table, you can
VALUES ('Yang Kan', 101, 2500) insert a record in the HumanResources.Employee table to
Inserting Data in Related Tables generate the employee ID for that person. This employee
Data related to an entity can be stored in more than one ID will be used to insert rows in the
table. Therefore, while adding information for a new HumanResources.EmployeeDepartmentHistory and
entity, you need to insert new rows in all the related tables. HumanResources.EmployeePayHistory tables.
In such a case, you need to first insert a row in the table Copying Data from an Existing Table
that contains the primary key. Next, you can insert a row into a New Table
in the related table containing the foreign key. While inserting data in a table, you might need to copy
For example, in the AdventureWorks database, the rows from an existing table into a new table. You can do
employee details are stored in Person.Contact, this by using the SELECT statement.
HumanResources.Employee, For example, in the AdventureWorks database, data for the
HumanResources.EmployeeDepartmentHistory, and employees with a payment rate of 35 or above is to be
copied into a new table called PreferredEmployee from the execute the preceding INSERT statement without any
EmployeePayHistory table. error, you need to first execute the following statement:
The following query copies the values from the SET IDENTITY_INSERT Emp ON
EmployeePayHistory table into the PreferredEmployee The preceding statement sets the identity insert property of
table: the Emp table to ON. Now, you can execute the following
SELECT * INTO PreferredEmployee statement to insert a value in the identity column:
FROM HumanResources.EmployeePayHistory INSERT INTO Emp(EmpCode, EmpName,
WHERE Rate >= 35 DeptNo) VALUES (3, 'Nancy', 20)
The preceding query will create a new table named The preceding statement executes successfully and inserts
PreferredEmployee. The table will have the same structure a row in the Emp table.
as HumanResources.EmployeePayHistory.
You can also copy the values from an existing table to Inserting the FILESTREAM Data
another existing table. For example, you want to copy data You can insert the FILESTREAM data into a table as a
for the employees with a payment rate of 10 or less from value of varbinary (max) data type. For example, you can
the EmployeePayHistory table into the PreferredEmployee use the following statement to insert data into the
table. The PreferredEmployee table exists in the database. EmpDetails table:
You can perform this task by using the following USE TekSoft
statement: INSERT INTO EmpDetails(EmployeeID,
INSERT INTO PreferredEmployee EmployeeName,
SELECT * FROM EmployeeAddress,EmployeeDept,EmployeeP
HumanResources.EmployeePayHistory hoto)
WHERE Rate <=10 VALUES(NEWID(),'Mark', 'California',
'Testing',cast('D:\Emp_Photo
Whenever you copy data to another existing table, the \Emp101.jpg'as varbinary(max)))
structure of the source and the target tables must be same. In In the preceding statement, the NEWID() function is used
addition, the SELECT INTO statement only copies the data of to generate the unique values for the EmployeeID column.
the source table into the target table. However, it does not In addition, the cast() function is used to convert the string
copy the constraints, indexes, triggers, or keys of the source literal that represents the path of the employee photo to the
table in the target table. varbinary (max) data.
Inserting Data in an Identity Column
into a Table The NEWID() function is used to generate unique
A column in a table for which the values are automatically values for the columns that are declared as the
generated by the database is called an identity column. UNIQUEIDENTIFIER data type.
You are not required to specify the values for the identity Inserting Globally Unique Values
column while inserting data. For example, you can use the You can use the NEWSEQUENTIALID() function to
following statement to insert data in the Emp table: generate a unique value or GUID for a column. This
INSERT INTO Emp VALUES ('Steve', 10) function creates GUID in a sequential manner. Therefore,
In the preceding statement, the value of the ID column is GUID created by the NEWSEQUENTIALID() function is
not specified as it is set as an identity column. However, if always greater than the values that were previously created
you specify a value for the identity column while inserting by this function on the same computer since Windows was
data into the table, an error occurs. For example, try to started. However, when Windows is restarted, GUID
execute the following statement to insert the value in the created by the NEWSEQUENTIALID() function again
identity column: starts from a lower range, but still the generated GUID
INSERT INTO Emp(EmpCode, EmpName, value will be globally unique.
DeptNo) VALUES (3, 'Nancy', 20) The NEWSEQUENTIALID() function returns a value of
The preceding statement displays an error on execution the type, uniqueidentifier. The only restriction for the
because you cannot explicitly insert data in an identity NEWSEQUENTIALID() function is that the function can
column, EmpCode. To insert a value explicitly in an be used only to generate a unique identifier value of a
identity column, you need to use the column with the DEFAULT constraint. For example,
SET_IDENTITY_INSERT statement. consider the following statement to create a table:
The SET_IDENTITY_INSERT statement sets the identity CREATE TABLE UserDetails (
insert property of a database object. You need to set this UserID INT NOT NULL IDENTITY(1, 1),
property to ON to insert a value in an identity column. By UserName VARCHAR(20) NOT NULL,
default, this property is set to OFF. For example, to UserKey UNIQUEIDENTIFIER DEFAULT
( NEWSEQUENTIALID())) longitude and 39.95954 represents the latitude. Therefore,
In the preceding statement, a table named UserDetails is the location of a country is specified as a point by using
created. This table contains a column named UserKey the Geography data type. When the preceding statement is
whose value will be generated by the executed, the data in the CountryLocation column will be
NEWSEQUENTIALID() function. in the hexadecimal format.
You can use the following statement to insert values in the The following figure shows the data inserted in the
UserDetails table: Country_Location table.
INSERT INTO UserDetails (UserName)
VALUES ('John')
Once executed, the preceding statement inserts a row in
the UserDetails table, as shown in the following figure.
The Data Inserted in the Country_Location Table
To retrieve the data in the form of a point value, you need
to use the ToString() function, as shown in the following
query:
The Ouput Derived After Using the NEWSEQUENTIALID() SELECT CountryID,
Function CountryLocation.ToString() AS Location
The NEWSEQUENTIALID() function cannot be used to FROM Country_Location
generate a value in a query statement. If the The preceding query displays the output, as shown in the
NEWSEQUENTIALID() function is used in a query, an following figure.
error message is dispalyed. For example, consider the
following query:
SELECT NEWSEQUENTIALID();
When the preceding query is executed, the following error
message is displayed: The Ouput Derived After Using the ToString() Function
Msg 302, Level 16, State 0, Line 1
The newsequentialid() built-in
function can only be used in a DEFAULT
expression for a column of type
'uniqueidentifier' in a CREATE TABLE
or ALTER TABLE statement. It cannot be
combined with other operators to form
a complex scalar expression.
Inserting the Spatial Data
Geographic locations such as bank branches, restaurants,
and company locations are usually defined in terms of
latitude and longitude. SQL server provides you with the
GEOGRAPHY data type to store geographic locations as
points. A point is represented in terms of X and Y
coordinates. For geographic locations, X-coordinate is the
longitude, while the Y-coordinate is the latitude. You can
use the Geography::Parse static method to convert the
latitude and longitude into a geographic point.
The Geography::Parse method takes a point type value as
a parameter. The X and Y coordinates in the point type
value are separated by a space. For example, you can use
the following statement to insert a row in the
Country_Location table:
USE AdventureWorks
INSERT INTO Country_Location
(CountryID, CountryLocation)
VALUES(1001, Geography::Parse('POINT
(-83.0086 39.95954)'))
In the preceding statement, -83.0086 represents the
 An update can be done on only one table at a
time.
 If an update violates integrity constraints, then the
entire update is rolled back.
 If you do not specify a condition by using the
WHERE clause, all the rows will be updated with
the value specified for the column.
For example, the following table displays the sample data
from the EmpData table.

Updating Data in a Table


The Sample Data of the EmpData Table
You need to modify the data in the database when the The following statement updates the address of the
specifications of a customer, a client, a transaction, or any employee having EmpNo, 101:
other data maintained by the organization undergo a UPDATE EmpData
change. SET EmpAddress = '123 Shi Lu'
For example, if a client changes his address or if the WHERE EmpNo = 101
quantity of a product ordered is changed, the required Consider another example, where you need to update the
changes need to be made to the respective rows in the title of an employee named Lynn Tsoflias to Sales
tables. You can use the UPDATE statement to make the Executive in the Employee table. To perform this task, you
changes. Updating ensures that the latest and correct need to first refer to the Contact table to obtain the Contact
information is available at any point of time. You can ID.
update one or more than one column of a row. You can then use this ContactID to update the employee
You can update data in a table by using the UPDATE details by using the following statement:
DML statement. The syntax of the UPDATE statement is: UPDATE HumanResources.Employee SET
UPDATE table_name Title = 'Sales Executive'
SET column_name = value [, column_name FROM HumanResources.Employee e,
= value] Person.Contact c
[FROM table_name] WHERE e.contactID = c.ContactID
[WHERE condition] AND c.FirstName = 'Lynn' and
where, c.LastName = 'Tsoflias'
table_name specifies the name of the table you have to
modify.
column_name specifies the columns you have to modify
in the specified table.
value specifies the value(s) with which you have to
update the column(s) of the table. Some valid values
include an expression, a column name, and a variable
name. The DEFAULT and NULL keywords can also be
supplied.
FROM table_name specifies the table(s) that is used in
the UPDATE statement.
condition specifies the rows that you have to update.
Guidelines for Updating Data
You need to consider the following guidelines while
updating data:
HumanResources.EmployeePayHistory, and
HumanResources.JobCandidate. The EmployeeID
attribute in these tables is a foreign key to the EmployeeID
attribute of the Employee table. Therefore, the query
results in an error. You need to delete data from the related
tables before executing the preceding DELETE statement.
Deleting all the Records from a Table
As a database developer, you might need to delete all the
records from a table. You can do this by using the
following DELETE statement:
DELETE table_name
You can also use the TRUNCATE DML statement. The
syntax of the TRUNCATE statement is:
TRUNCATE TABLE table_name
where,
table_name specifies the name of the table from which
you have to delete rows.
However, the TRUNCATE DML statement is executed
Deleting Data from a Table faster.
You need to delete data from a database when it is no
longer required. The smallest unit that can be deleted from The TRUNCATE DML statement does not support the
a database is a row. WHERE clause. In addition, the TRUNCATE TABLE
You can delete a row from a table by using the DELETE statement does not fire a trigger. When truncate is used, the
DML statement. The syntax of the DELETE statement is: deleted rows are not entered in the transaction log.
DELETE [FROM] table_name For example, the following statement deletes all the
[WHERE condition] records from the EmpData table:
where, TRUNCATE TABLE EmpData
table_name specifies the name of the table from which
you have to delete rows.
condition specifies the condition that identifies the
row(s) to be deleted.
For example, the following statement deletes the address
details of AddressID 104 from the Address table:
DELETE PreferredEmployee
WHERE EmployeeID = 4
Deleting Data from Related Tables
While deleting records from related tables, you first need
to delete the records from the table that contains the
foreign key. After that, you can delete the record from the
table that contains the primary key.
Consider the example of the AdventureWorks database.
The Employee table contains data of those employees who
have retired from the company. This data is not required
anymore. This increases the size of the database. You are
required to ensure that this old data is removed from the
Employee table.
You can delete this data by using the following statement: Retrieving the Modified Data
DELETE FROM HumanResources.Employee While performing various operations, such as insert,
EmployeeID = 9 update, and delete on the tables in a database, SQL Server
The database contains tables related to the Employee displays only the number of rows affected as a result of
table. The related tables are these operations. For example, if you delete a row from a
HumanResources.EmployeeAddress, table based on specific criteria, the following statement
HumanResources.EmployeeDepartmentHistory, will be displayed as a result:
(1 row(s) affected) UPDATE statement, which updates the rows in the
Sometimes, you also need to retrieve the data affected by HumanResources.Department table where the name of the
the DML statements. For example, consider one of the department is Quality Assurance:
employees has been shifted from Production to the Quality UPDATE HumanResources.Department
Control department. For this, you would update the SET Name='Quality Control'
department ID of the employee in the Employee table. OUTPUT INSERTED.*
However, you also need to retain the historical data of all WHERE Name='Quality Assurance'
the employees. Therefore, you first need to archive the old In the preceding statement, the OUTPUT clause displays
employee data, and then update the employee data in the the rows updated in the Department table, as shown in the
Employee table. SQL Server allows you to perform these following figure.
two tasks in a single statement by using the OUTPUT
clause.
The OUTPUT clause is used to retrieve the set of rows
affected by the DML statements. You need to attach the
OUTPUT clause to an INSERT, UPDATE, or DELETE The Ouput Derived After Using the OUTPUT clause
statement to retrieve the modified data. The OUTPUT However, if you want to display only the selected values
clause is used along with the INSERTED or DELETED affected by the DML statements, you can specify the
statement to return the data of the affected rows. column names to be displayed with the OUTPUT clause.
When a row is inserted in a table, a virtual table named For example, the following statement displays only the
INSERTED is created that contains the inserted data. values of the Name column of the updated rows:
Similarly, when a row is deleted from a table, a virtual UPDATE HumanResources.Department
table named DELETED is created that contains the deleted SET Name='Quality Assurance'
data. You can reference the inserted or deleted data in a OUTPUT INSERTED.Name
table by using the INSERTED or DELETED statements WHERE Name='Quality Control'
along with the OUPUT clause, respectively. Similarly, The preceding statement displays the result, as shown in
when a row is updated in a table, both the virtual tables, the following figure.
INSERTED and DELETED, are created.
For example, the rate of an employee having ID, 4 is
changed from 8.62 to 9.50. Now, you need to update the
Rate column in the PreferredEmployee table and insert the
old rate in the PreferredEmployeeArchive table. Execute The Ouput Derived After Using the OUTPUT clause
the following statement to create the Similar to the UPDATE statement, you can also use the
PreferredEmployeeArchive table: OUTPUT clause to return the affected rows while
CREATE TABLE PreferredEmployeeArchive executing the INSERT and DELETE statements. For
( example, consider the following statement:
EmployeeID int NOT NULL, INSERT Emp
RateChangeDate datetime NOT NULL, OUTPUT INSERTED.*
Rate money NOT NULL, VALUES('Nancy', 'HR')
PayFrequency tinyint NOT NULL, The preceding statement displays the inserted row in the
ModifiedDate datetime NOT NULL Emp table, as shown in the following figure.
)
Now, execute the following statement to update the
PreferredEmployee table and insert the old data in the
PreferredEmployeeArchive table:
UPDATE PreferredEmployee The Ouput Derived After Using the OUTPUT clause
SET Rate = 9.62
OUTPUT DELETED.*
INTO PreferredEmployeeArchive
WHERE EmployeeID = 4
The preceding statement on execution inserts the old data
of the employee having ID, 4 in the
PreferredEmployeeArchive table.
The OUTPUT clause is also useful where you need to
return the modified data to the client applications for
further processing. For example, consider the following
table.
 WHEN NOT MATCHED BY SOURCE
clause: Specifies a row in the target table
that has no corresponding row in the source
table.
 OUTPUT clause: Is used to return a row for each
inserted, updated, or deleted row in the target
table.
The syntax of the MERGE statement is:
MERGE
[ TOP ( expression ) [ PERCENT ] ]
[ INTO ] <target_table> [ WITH
( <merge_hint> ) ] [ [ AS ]
table_alias ]
USING <table_source>
ON <merge_search_condition>
[ WHEN MATCHED [ AND
<clause_search_condition> ]
Comparing and Updating Data THEN <merge_matched> ] [ ...n ]
[ WHEN NOT MATCHED [ BY TARGET ]
Many business organizations keep a backup of their [ AND <clause_search_condition> ]
important data. When the data in the source table is THEN <merge_not_matched> ]
changed, the changes must reflect in the backup table to [ WHEN NOT MATCHED BY SOURCE [ AND
synchronize both the tables. For example, the employee <clause_search_condition> ]
records are maintained in an Employee table. The backup THEN <merge_matched> ] [ ...n ]
of this table is taken in the Employee_Backup table. After [ <output_clause> ]
taking the backup, one of the employees left the where,
organization and some employees got married. You have TOP ( expression ) [ PERCENT ] specifies the
to make these changes in the Employee table as well as the number or percentage of rows that are affected.
Employee_Backup table. For this, you need to first make <target_table> specifies the table or views where
the changes in the Employee table, and then reflect these the rows returned by the WHEN clause is inserted,
changes in the Employee_Backup table. SQL Server updated, or deleted.
allows you to perform this task by using a single MERGE <table_source> specifies the table, view, or
statement. expression from where the rows to be matched with the
The MERGE statement enables you to perform insert, target table are retrieved.
update, and delete operations in a single statement. The <merge_search_condition> specifies the
insert, update, or delete operations are performed in the condition used to decide whether the rows in the source
target table based on certain conditions in the source table. and destination tables match.
The MERGE statement consists of the following clauses: WHEN MATCHED THEN <merge_matched> specifies
 USING clause: Specifies the source table to be the action to be performed on the rows in the target table
matched with the target table. when a match exists between the source and the target
 ON clause: Specifies the join conditions that rows based on the specified conditions.
determine whether the target and the source tables WHEN NOT MATCHED [BY TARGET] THEN
match. <merge_not_matched> specifies a row to be inserted
 WHEN clause: Specifies the actions to be taken into the target table for every row that does not match a
based on the results of the ON clause and any row in the source table based on the specified conditions.
additional search criteria. It can be specified in WHEN NOT MATCHED BY SOURCE THEN
the following forms:
<merge_matched> specifies an update or delete action
 WHEN MATCHED clause: Specifies a
on rows that exist in the target table but not in the source
matched pair consisting of one row from
table.
the target and one row from the source
<clause_search_condition> is used to specify
table.
 WHEN NOT MATCHED BY TARGET any valid search condition.
clause: Specifies a row in the source table <output_clause> is used to return a row for every
that has no corresponding row in the target updated, inserted, or deleted row in the target table.
For example, you have been assigned the task to maintain INSERT VALUES
the backup of the Education table. Therefore, you need to (SOURCE.EmployeeEducationCode,
regularly compare the Education table with the backup SOURCE.Education)
table and perform the insert, update, or delete operations WHEN NOT MATCHED BY SOURCE THEN
on the backup table, as required. The following figure DELETE;
shows the contents of the Education table. When the preceding statement is executed, the source
table, Education and the target table, Education_Backup
are matched and the Education_Backup table is updated
accordingly. You can use the following query to verify the
result of the preceding statement:
SELECT * FROM Education_Backup
The following figure shows the output of the preceding
query.

The Contents of the Education Table


You take the backup of the Education table in the
Education_Backup table by using the following statement:
SELECT * INTO Education_Backup FROM
Education
After taking the backup, the Education table is modified
by using the following statements:
INSERT Education VALUES (5, 'B.Tech') The Modified Content of the Education_Backup Table
DELETE Education WHERE
EmployeeEducationCode = 4
Now, the Education table contains different records, as
shown in the following figure.

The Modified Content of the Education Table


Therefore, you need to reflect the changes made in the
Education table to the Education_Backup table. Here, the
Education is the source table and the Education_Backup is
the target table. You can use the following MERGE
statement to reflect the changes in the Education_Backup
table:
MERGE Education_Backup AS TARGET
USING Education AS SOURCE
ON (TARGET.EmployeeEducationCode =
SOURCE.EmployeeEducationCode)
WHEN MATCHED AND TARGET.Education <>
SOURCE.Education
THEN UPDATE SET TARGET.Education =
SOURCE.Education
WHEN NOT MATCHED THEN
tree structure in a table. The values in the columns of the
hierarchyid data type in a table are referred to as
hierarchyid. Hierarchyid is the information about the
position of a node in a hierarchy tree. This information is
in the hexadecimal format and is generated by encoding
the path from the root of the tree to that node. The
information stored in hierarchyid can be represented in the
form of a string that logically represents a sequence of
nodes visited after the root.
The following figure represents the position of nodes in a
hierarchy tree.

Managing Hierarchical Data in Tables


Consider a scenario where you need to store the
information about the employees along with their
reporting authorities in a table. In addition, you want to
store the level of each employee in the organization. For
example, you want the top-level employees who do not
report to any other employee to be kept at level 0.
However, employees who report to the employees at level
0 should be kept at level 1. Similarly, other employees
should be kept at the next level of the employees whom
they report to.
The Position of Nodes in a Hierarchy Tree
In the preceding scenario, the data that represents a level
In the preceding figure, '/' represents the root node. The
in a hierarchy is referred to as the hierarchical data.
first child of the root node is '/1/'. The second child of the
Another example of the hierarchical data may be the file
root node is '/2/'. This number gets incremented by one
system of an operating system. This file system may
with the increase in the number of children at a particular
contain a root directory, which contains other
level. For two given hierarchyid values 'a' and 'b', a<b
subdirectories. Further, the subdirectories may contain
means that 'a' comes before 'b' in the hierarchy tree.
other subdirectories.
Therefore, the second child of a node is said to be greater
To manage the hierarchical data, SQL Server provides the than its first child or first child is less than the second
hierarchyid data type. The hierarchyid data type is a child. Similarly, the third child of a node is said to be
variable length system-defined data type that can be used greater than its second child.
to represent a position in a hierarchy. You can create tables
The node at '/1/' has the first child represented by '/1/1/'
by using the hierarchyid data type that can store
and second child represented by '/1/2/'. Similarly, if there
hierarchical data.
will be third child, it will be represented as '/1/3/'. For the
Using the Hierarchyid Data Type node at '/1/1/', the first child is represented as '/1/1/1/' and
A hierarchy in general is represented as a tree structure in second child as '/1/1/2/'. Therefore, a node at a particular
which the data is represented in the form of parent and level is represented logically by a string.
child nodes. In a tree structure, the nodes at a higher level The following table lists the string representation of the
are referred to as the parents of the nodes at the next level values stored in some of the hierarchyid nodes in a
in the hierarchy. The nodes at the next level of a parent hierarchy.
node are referred to as child nodes. A node that does not
have a parent node and is placed at the top of the hierarchy String Representation Description
is referred to as the root node. A node in a hierarchy can / Represents the top level root
contain any number of child nodes. However, a node in a node of the hierarchy.
hierarchy must have only one parent node.
/1/ Represents the first child
Similarly, the hierarchical data is also stored in a logical
node one level below the parent.GetDescendant(Child1,
root node. Child2)
/2/ Represents the second child where,
node of the root node. parent represents the hierarchyid of the parent
/2/1/ Represents the first child node.
node of the second child of Child1 and Child2 represent the hierarchyids
the root node. of the child nodes of the parent node.
/1/2/ Represents the second child The following table describes the position of the
node of the first child of the child node to be inserted based on the values of
root node. the Child1 and Child2 parameters.
/n/ th
Represents the n child
Child1 Child2 Description
node of the root node.
th
NULL NULL Returns the first
/n/r/ Represents the r child node child of the
of the nth child of the root current node.
node. This should be
used when the
The String Representation of the Values Stored in the first child of a
Hierarchyid Nodes node is to be
inserted into
To store the values stored in a column of the hierarchyid the hierarchical
data type, you need to generate the hierarchy ids for the structure.
various nodes. These hierarchy ids represent the logical NOT NULL NULL Returns a child
placement of a node in the hierarchy tree. of the current
SQL Server provides the following built-in methods to node greater
generate and manage the hierarchy ids for the nodes in the than that of
hierarchy tree: Child1. For
 GetRoot(): Returns the hierarchyid for the root example, if
node in the hierarchy tree. Therefore, this method Child1 is /1/ in
is called first to insert the root node in the table the hierarchical
containing the hierarchyid column. The syntax for structure, the
using this method is: returned value
hierarchyid::GetRoot() will be /2/.
 GetAncestor (n): Returns the hierarchyid of the NULL NOT NULL Returns a child
nth parent of the current node. Here, n is an of the current
integer value that represents the number of levels node less than
to go up in the hierarchy. If you specify the value Child2. For
of n as 1, then the hierarchyid of the immediate example, if
parent of the current node will be returned. For Child2 is /1/,
example, if you invoke the GetAncestor(1) then the
method on a node one level below the root, the inserted child
hierarchyid of the root node will be returned. The node will be /0/.
syntax for using this method is: NOT NULL NOT NULL Returns a child
child.GetAncestor(n) of the current
where, node greater
child represents the hierarchyid of the node for than Child1 but
which the nth parent is to be determined. less than
 GetDescendant (Child1, Child2): Returns a Child2.The
child node of the current node based on the values child node will
specified for the Child1 and Child2 parameters. be inserted
The values of these parameters are used to place between Child1
the child node at a certain position among the and Child2. For
other child nodes. The syntax for using this example, if
method is: Child1 is /1/
and Child2 data along with the reporting hierarchy of the employees.
is /2/, then the The following figure shows the reporting hierarchy of the
inserted child employees.
node will
be /1.1/.

The Position of the Child Node to be Inserted


For example, if you need to create the first child
node of a node, you should pass NULL as the
values of the Child1 and Child2 parameters of the
GetDescendant() method. However, if you need
to create a child node after an already inserted
child node, you should pass the hierarchyid of the
existing child node as the value of Child1 and The Reporting Hierarchy of the Employees
NULL as the value of Child2 in the In the preceding figure, the name, employee ID, and
GetDescendant() method. designation of the employees are displayed to represent
 GetLevel(): Returns an integer that represents the their respective position in the hierarchy.
depth of the current node in the hierarchy. The You can use the following statement to create a table
syntax for using this method is: named EmployeeHierarchy in the AdventureWorks
node.GetLevel() database:
where, CREATE TABLE EmployeeHierarchy
node represents the hierarchyid of the node for (
which the level is to be determined. HierarchyNode hierarchyid PRIMARY
For the root node, this method returns 0. This KEY,
number is incremented by one for each level as HierarchyLevel AS
you traverse down the hierarchy tree. All the child HierarchyNode.GetLevel(),
nodes of a parent node are said to be at the same EmployeeID int UNIQUE NOT NULL,
level. Therefore, all the child nodes of the root EmpName varchar(20) NOT NULL,
node will be at level 1. Designation varchar(20) NULL
 IsDescendantOf (node): Returns true if the )
specified hierarchyid node is the parent of the In the preceding statement, the HierarchyNode column
current node. Otherwise, returns false. The syntax will be used to store the hierarchyids of the different nodes
for using this method is: in the hierarchy. HierarchyLevel is a computed column
child.IsDescendantOf(parent) that stores the hierarchy levels of the hierarchy nodes. The
where, GetLevel() method retrieves the level of nodes and stores
child and parent are the hierarchyids of the it in the HierarchyLevel column. This column will
nodes in the hierarchy tree. automatically insert the value based on the value of
 Parse(string): Converts the specified hierarchy hierarchyid in the HierarchyNode column.
represented as string into a hierarchyid value. The After creating the table with a column of the hierarchyid
syntax for using this method is: data type, you can insert the hierarchical data in this table
hierarchyid::Parse(string) by using the INSERT statement. For example, you can use
 ToString(): Returns a string that contains the the following INSERT statement to insert the root node
logical string representation of the current (Sam, 101, CEO) in the hierarchy:
hierarchyid node. The syntax for using this INSERT INTO EmployeeHierarchy
method is: (HierarchyNode, EmployeeID, EmpName,
node.ToString() Designation)
where, VALUES (hierarchyid::GetRoot(), 101,
node represents the hierarchyid of the node for 'Sam', 'CEO') ;
which the equivalent string representation is to be The preceding statement inserts Sam as the root node in
determined. the table.
Storing the Hierarchical Data After inserting the root node, you can use the
To store the hierarchical data, you first need to create a GetDescendant() method to create and insert the child
table with a column of the hierarchyid data type. For nodes in the hierarchy. To insert the first child of the root
example, you can create a table that stores the employee node, you need to pass the NULL values as the Child1 and
Child2 parameters of the GetDescendant() method. Designation)
Before you insert the child of a node, you need to reach VALUES
that node. To traverse the nodes in the hierarchy, you can (@parent.GetDescendant(NULL, NULL),
use the logical string representation of the nodes. For 104, 'Mary', 'Team Leader')
example, the root node is represented as / in string In the preceding statements, '/1/' represents the string
representation. Therefore, you can use the following representation of the position of Sandy in the hierarchy.
statements to insert the first child node (Sandy, 102, Similarly, you can insert other nodes in the
Manager) of the root node: EmployeeHierarchy table. The HierarchyNode column of
DECLARE @CEO hierarchyid this table stores the hierarchyids of each node in a
SELECT @CEO = CAST('/' AS hierarchyid) hexadecimal format. However, you can use the ToString()
FROM EmployeeHierarchy; method to convert the hierarchyid into a string. For
INSERT INTO EmployeeHierarchy example, you can use the following query to view the
(HierarchyNode, EmployeeID, EmpName, records of the EmployeeHierarchy table:
Designation) SELECT HierarchyNode.ToString() AS
VALUES Text_HierarchyNode,
(@CEO.GetDescendant(NULL, NULL), 102, HierarchyNode, HierarchyLevel,
'Sandy', 'Manager') EmployeeID, EmpName, Designation
In the preceding statement, the CAST() method is used to FROM EmployeeHierarchy
get the hierarchyid of the root node from the equivalent The following figure displays the output of the preceding
string representation. Further, the GetDescendant() method query.
is used to create the first child node of the root node.
Similarly, you can create and insert a child of a node after
an existing child by using the GetDescendant() method.
However, to create a child node after an existing child of a
node, you need to pass the hierarchyid of the existing child
node and NULL as the values of the Child1 and Child2
parameters of the GetDescendant() method, respectively. The Output Showing the Records of the EmployeeHierarchy
Table
For example, to insert a child node after the first child of
the root node, you can use the following statements:
DECLARE @CEO hierarchyid Activity 5.1: Manipulating Data
SELECT @CEO = CAST('/' AS hierarchyid)
FROM EmployeeHierarchy in Tables
DECLARE @FirstChild hierarchyid
SELECT @FirstChild = CAST('/1/' AS
hierarchyid) Activity 5.2: Using the MERGE
FROM EmployeeHierarchy
INSERT INTO EmployeeHierarchy Statement
(HierarchyNode, EmployeeID, EmpName,
Designation)
VALUES Manipulating XML Data
(@CEO.GetDescendant(@FirstChild,
NULL), 103, 'Jack', 'Manager') With a growth in clients accessing data through
In the preceding statements, hierarchyid of the root and the heterogeneous hardware and software platforms, we
first child node is retrieved from their string representation needed a language that could be interpreted by any
by using the CAST() method. Further, the GetDescendant environment. This resulted in the evolution of a language
() method is used to create the second child node of the called eXtensible Markup Language (XML). XML is a
root node. markup language that is used to describe the structure of
Now, to insert Mary as a child of Sandy, you need to use data in a standard hierarchical manner. The structure of the
the following statements: documents containing the data is described with the help
DECLARE @parent hierarchyid of tags contained in the document. Therefore, various
SELECT @parent = CAST('/1/' AS business applications store their data in XML documents.
hierarchyid) SQL Server allows you to save or retrieve data in the
FROM EmployeeHierarchy; XML format. This enables SQL Server to provide database
INSERT INTO EmployeeHierarchy support to various applications. As a database developer, it
(HierarchyNode, EmployeeID, EmpName, is important for you to learn to manipulate XML data by
using SQL Server. Consider an example. You have received order details
from a vendor. The order details are generated by the
application used by the vendor in an XML document. You
The structure of XML data can be defined in the form
need to store this data in a database table. For this, you
of a supporting Document Type Definition (DTD) or schema.
need to shred the XML data. SQL Server allows you to
You can read more about XML in the Appendix.
shred the XML data by using the OPENXML function and
its related stored procedures.
Shredding an XML document involves the following
tasks:
1. Parse the XML document.
2. Retrieve a rowset from the tree.
3. Store the data from the rowset.
4. Clear the memory.
The following figure represents the shredding of an XML
document.

Storing XML Data in a Table


XML data is available in the form of XML fragments or
complete XML documents. An XML fragment contains
XML data without a top-level element.
The following example displays a complete XML
document:
<customerdata>
<customer ID=C001>
<custname>John</custname>
</customer>
<customer ID=C002>
<custname>Peter</custname>
</customer> Shredding an XML Document
</customerdata> In the preceding figure, you must first call the
The following example displays XML data in the form of sp_xml_preparedocument procedure to parse the XML
XML fragment: document. This procedure returns a handle to the parsed
<customer ID=C001><custname>John</ document that is ready for consumption. The parsed
custname></customer> document is a Document Object Model (DOM) tree
SQL Server uses XML as a data type to save XML data in representation of various nodes in the XML document.
its original state. You can create tables or variables by The document handle is passed to OPENXML.
using this data type to store XML data. However, you can OPENXML then provides a rowset view of the document
also shred XML data and store the values in different based on the parameters passed to it. The internal
columns in a rowset. This process of transforming XML representation of an XML document must be removed
data into a rowset is called shredding. from memory by calling the sp_xml_removedocument
In SQL Server, you can store XML data in the following system stored procedure.
ways: Parsing the XML Document
 A rowset SQL Server provides the sp_xml_preparedocument stored
 An XML column procedure to parse the XML document. This stored
Storing XML Data in a Rowset procedure reads the XML document and parses it with the
MSXML parser. Parsing an XML document involves need to release the memory where you stored the rowset.
validating the XML data with the structure defined in the For this, you can use the sp_xml_removedocument stored
DTD or schema. The parsed document is an internal tree procedure.
representation of various nodes in the XML document, Consider an example, where customers shop online and
such as elements, attributes, text, and comments. the orders given by the customers are transferred to the
sp_xml_preparedocument returns a handle or pointer that supplier in the form of an XML document. The following
can be used to access the newly created internal data is available in the XML document:
representation of the XML document. This handle is valid DECLARE @Doc int
for the duration of the session or until the handle is DECLARE @XMLDoc nvarchar(1000)
destroyed by executing the sp_xml_removedocument SET @XMLDoc = N'<ROOT>
stored procedure. <Customer CustomerID="JH01"
Retrieving a Rowset from the Tree ContactName="John Henriot">
After verifying the accuracy of the structure and <Order OrderID="1001"
completeness of data, you need to extract the data from the CustomerID="JH01">
available XML data. For this, you can use the OPENXML <OrderDate="2006-07-04T00:00:00"
function to generate an in-memory rowset from the parsed >
data. <OrderDetail ProductID="11"
The syntax of the OPENXML function is: Quantity="12"/>
OPENXML( idoc int [ in], rowpattern <OrderDetail ProductID="22"
nvarchar [ in ], [ flags byte Quantity="10"/>
[ in ] ] ) </Order>
[ WITH ( SchemaDeclaration | </Customer>
TableName ) ] <Customer CustomerID="SG01"
ContactName="Steve Gonzlez">
where,
<Order OrderID="1002"
idoc specifies the document handle of the internal tree
CustomerID="SG01">
representation of an XML document. OrderDate="2006-08-16T00:00:00">
rowpattern specifies the XPath pattern used to identify <OrderDetail ProductID="32"
the nodes (in the XML document whose handle is passed Quantity="3"/>
in the idoc parameter) to be processed as rows. The row </Order>
pattern parameter of OPENXML allows you to traverse </Customer>
the XML hierarchy. </ROOT>'
flags indicate the mapping that should be used between To view the preceding XML data in a rowset, you need to
the XML data and the relational rowset. It is an optional perform the following steps:
parameter and can have the following values: 1. Create an internal representation of the XML
 0: To use the default mapping (attributes). document by executing the following statement:
 1: To retrieve attribute values. EXEC sp_xml_preparedocument @Doc
 2: To retrieve element values. OUTPUT, @XMLDoc
 3: To retrieve both attribute and element values. 2. Execute the following statement to store the data
SchemaDeclaration specifies the rowset schema in a table, CustomerDetails by using the
declaration for the columns to be returned by using a OPENXML function:
combination of column names, data types, and patterns. SELECT * INTO CustomerDetails
TableName specifies the table name that can be given FROM OPENXML (@Doc, '/ROOT/
instead of SchemaDeclaration if a table with the desired Customer', 1)
schema already exists and no column patterns are WITH (CustomerID varchar(10),
required. ContactName varchar(20))
Storing Data from the Rowset In the preceding statement, the OPENXML
You can use the rowset created by OPENXML to store function takes three parameters. The first
data in the same way that you would use any other rowset. parameter, @Doc is the document handle, which
You can insert the rowset data into permanent tables in a stores the internal representation of the XML
database. For example, you can insert the data received by document. The second parameter specifies that
a supplier in the XML format into the SalesOrderHeader the Customer element is to be processed. The
and SalesOrderDetail tables. third parameter, 1 allows you to retrieve the
attribute values of the Customer element. The
Clearing the Memory
WITH clause specifies the column names along
After saving the data permanently in the database, you
with the data types where attribute values will be Quantity int)
stored. When the preceding query is executed, the EXEC sp_xml_removedocument @Doc
details of the customers are stored in the In the preceding statements, the second parameter (/
CustomerDetails table, as shown in the following ROOT/Customer/Order/OrderDetail) of the OPENXML
table. function specifies that the current node is OrderDetail,
which needs to be processed. The WITH clause specifies
CustomerID ContactName the column names, data types, and patterns. Here, the '@'
JH01 John Henriot symbol specifies the attribute, and the double dot (..)
SG01 Steve Gonzlez symbol represents the parent node of the current node.
Therefore, the expression, ../../@CustomerID, in the
WITH clause represents the CustomerID attribute of the
Representation of the XML Data in a Tabular Customer element.
Format
The output of the preceding statements is displayed in the
3. Remove the internal tree from the memory by
following figure.
executing the following statement:
EXEC sp_xml_removedocument @Doc
You can also specify the column pattern to map the rowset
columns and the XML attributes and elements. For
example, consider the following statements:
DECLARE @Doc int
DECLARE @XMLDoc nvarchar(1000) The Ouput Derived After Shredding an XML Document
SET @XMLDoc = N'<ROOT>
<Customer CustomerID="JH01"
ContactName="John Henriot">
<Order OrderID="1001"
CustomerID="JH01">
<OrderDate="2006-07-04T00:00:00">
<OrderDetail ProductID="11"
Quantity="12"/>
<OrderDetail ProductID="22"
Quantity="10"/>
</Order>
</Customer>
<Customer CustomerID="SG01"
ContactName="Steve Gonzlez">
<Order OrderID="1002"
CustomerID="SG01">
OrderDate="2006-08-16T00:00:00">
<OrderDetail ProductID="32"
Quantity="3"/> Importing XML data into SQL Server
</Order> At times, you need to import the entire data contained in
</Customer> an XML file into a table in SQL Server. For example, the
</ROOT>' details of the students are stored in a file named
EXEC sp_xml_preparedocument @Doc Students.xml. The OPENROWSET() function can be used
OUTPUT, @XMLDoc to connect with and access remote data stored in the XML
SELECT * document. It can be used in the FROM clause of the
FROM OPENXML (@Doc, '/ROOT/Customer/ SELECT statement.
Order/OrderDetail',1) The following syntax is used for the OPENROWSET()
WITH (CustomerID varchar(10) '../../ function to perform a bulk import operation:
@CustomerID', OPENROWSET( BULK,'file-name',Encoding-
ContactName varchar(20) '../../ Scheme)
@ContactName', where,
OrderID int '../@OrderID', BULK is a keyword to be used for bulk import.
OrderDate datetime '../ file-name is the name of the XML file to be imported.
@OrderDate', Encoding-Scheme is the scheme to be used.
ProdID int '@ProductID', SINGLE_BLOB, if provided as the encoding scheme,
ensures that the XML parser in SQL Server imports the The Output Derived After Using the Select Statement
data according to the encoding scheme specified in the Storing XML Data in XML Columns
XML declaration. At times, you need to store XML data in its original state
Further, XQuery can be used to parse XML into a tabular in a column of a database table. For example, you need to
format. save the details of customers in the database. The details
Consider the following Students.xml file, which is stored of individual customers are maintained by a website. The
on the C drive of your local machine: website saves the details of each customer in an XML file.
<Students> As a database developer, you need to save this data in SQL
<Student> Server. For this, you can create the CustDetails table to
<SID>1</SID> store the customer details, as shown in the following
<Marks>70</Marks> statement:
<Grade>B</Grade> CREATE TABLE CustDetails
</Student> (
<Student> CUST_ID int,
<SID>2</SID> CUST_DETAILS XML
<Marks>80</Marks> )
<Grade>A</Grade> You can save the following types of data in the columns
</Student> with the XML data types:
</Students>  Untyped XML data: Is also a well-formed data,
You need to import this XML file into a table named but is not associated with a schema. SQL Server
STUDENTS, which has been created by using the does not validate this data but ensures that the
following statement: data being saved with the XML data type is well-
CREATE TABLE STUDENTS(SID int PRIMARY formed.
KEY, Marks int, Grade varchar(5))  Typed XML data: Is a well-formed data that is
Use the following statement to insert the data into the associated with a schema defining the elements
table, STUDENTS, from the document, STUDENTS.xml: and their attributes. It also specifies a namespace
INSERT INTO STUDENTS(SID,Marks,Grade) for the data. When you save the typed XML data
SELECT x.Stud.QUERY('SID').VALUE('.', in a table, SQL Server validates the data against
'INT'), the schema. Then, SQL Server assigns the
x.Stud.QUERY('Marks').VALUE('.', appropriate data type to the data based on the data
'INT'), types defined in the schema. This helps in saving
x.Stud.QUERY('Grade').VALUE('.', the storage space.
'VARCHAR(5)') As a database developer, you should know how to store
FROM both types of data on SQL Server.
(SELECT CAST(x AS XML)FROM OPENROWSET
(BULK 'd:\Students.xml',SINGLE_BLOB)AS Storing Untyped XML Data
T(x)) To store untyped XML data, you can use columns or
AS T(x)CROSS APPLY x.nodes('Students/ variables with the XML data type. For example, to store
Student') AS X(Stud); customer data in the CustDetails table, you can use the
In the preceding statement, the QUERY() method is used following INSERT INTO statement:
to retrieve XML data from an XML instance. INSERT INTO CustDetails VALUES (2,
'<Customer Name="Abrahim Jones"
The VALUE() method is used to retrieve the value of the
City="Selina" />')
XML type into the SQL type that has been specified. The
In the preceding statement, the string value that contains
single dot (.) used inside the VALUE() method represents
an XML fragment is implicitly converted to XML.
the current element.
However, you can also convert a string value to XML by
The following statement is used to display the data from using the CONVERT or CAST functions. In this example,
the table Students: you can use the following statement to convert the data
SELECT * FROM Students type of the string value to XML before inserting the record
The output of the preceding statement is displayed in the into the table:
following figure. INSERT INTO CustDetails VALUES(2,
convert(XML,'<Customer Name="Abrahim
Jones" City="Selina" />'))
Similarly, you can also use the CAST function, as shown
in the following statement:
INSERT INTO CustDetails VALUES(4, cast creating a table that will store the XML data. In the
('<Customer Name="Abrahim Jones" preceding example, if you need to validate the customer
City="Selina" />' as XML)) details with the CustomerSchemaCollection schema, you
Storing Typed XML Data need to create the Customer_Details table by using the
To store typed XML data, you need to first register an following statement:
XML schema in the XML schema collection objects in the CREATE TABLE Customer_Details
database. The XML schema collection is an object on SQL (
Server that is used to save one or more XML schemas. CustID int,
You can create an XML schema collection object by using CustDetail XML
the following statement: (CustomerSchemaCollection)
CREATE XML SCHEMA COLLECTION <Name> as )
Expression You can insert the data in the Customer_Details table by
where, using the following statement:
Name specifies an identifier name with which SQL Server INSERT INTO Customer_Details
will identify the schema collection. VALUES(2,'<CustomerName>Abrahim
Expression specifies an XML value that contains one Jones</CustomerName><City>Selina</
City>')
or more XML schema documents.
While executing the preceding statement, SQL Server will
For example, the customer details are associated with the
validate the values for the CustDetails column against the
following schema:
CustomerSchemaCollection schema.
<schema xmlns="http://www.w3.org/2001/
XMLSchema"> Insert another record using the following statement:
<element name="CustomerName" INSERT INTO Customer_Details
type="string"/> VALUES(2,'<Name>John</Name><City>New
<element name="City" type="string"/ York</City>')
> In the preceding statement, the value of CustDetail column
</schema>' is not following the schema definition. The execution of
You can use the following statement to register the the preceding statement will produce the following error:
preceding schema with the database: Msg 6913, Level 16, State 1, Line 1
CREATE XML SCHEMA COLLECTION XML Validation: Declaration not found
CustomerSchemaCollection AS for element 'Name'. Location: /*:Name
'<schema xmlns="http:// [1]
www.w3.org/2001/XMLSchema">
<element name="CustomerName"
type="string"/>
Retrieving Table Data into XML
<element name="City" type="string"/ Format
>
</schema>' At times, you need to retrieve the relational data from a
The preceding statement creates a XML schema collection table into the XML format for reporting purposes or to
object named CustomerSchemaCollection. share the data across different applications. This involves
extracting data from a table in the form of well-formed
XML fragments. You can retrieve the data in XML format
You can view information about the registered by using:
schemas in a database by querying the  The FOR XML clause in the SELECT statement.
sys.XML_schema_collections catalog view, as shown in the  XQuery.
following query: SELECT * FROM
sys.XML_schema_collections Using the FOR XML Clause in the
SELECT Statement
SQL Server allows you to extract data from relational
To drop an XML Schema Collection from the tables into an XML format by using the SELECT
database, you can use the following statement: DROP XML statement with the FOR XML clause. You can use the
SCHEMA COLLECTION FOR XML clause to retrieve the XML data by using the
CustomerSchemaCollection following modes:
After registering the XML schema, you can use the  RAW
schemas to validate typed XML values while inserting  AUTO
records into the tables. You need to specify this while  PATH
 EXPLICIT RAW, and PATH mode queries. For example, the
Using the RAW Mode following query displays the product details:
The RAW mode is used to return an XML file with each SELECT ProductID, Name, Color
row representing an XML element. The RAW mode FROM Production.Product Product
transforms each row in the query result set into an XML WHERE ProductID = 1 OR ProductID = 317
element with the element name, row. Each column value FOR XML RAW, ELEMENTS XSINIL
that is not NULL is mapped to an attribute with the same In the preceding query, the value of Color column for
name as the column name. ProductID 1 is NULL. When you execute the preceding
The following query displays the details of employees query, the output will be displayed in the following
with employee ID as 1 or 2: format:
SELECT EmployeeID, ContactID, LoginID, <row xmlns:xsi="http://
Title www.w3.org/2001/XMLSchema-instance">
FROM HumanResources.Employee <ProductID>1</ProductID>
WHERE EmployeeID=1 OR EmployeeID=2 <Name>Adjustable Race</Name>
FOR XML RAW <Color xsi:nil="true" />
The preceding query displays the employee details in the </row>
following format: <row xmlns:xsi="http://
<row EmployeeID="1" ContactID="1209" www.w3.org/2001/XMLSchema-instance">
Loginid="adventure-works\guy1" <ProductID>317</ProductID>
Title="Production Technician - WC60" / <Name>LL Crankarm</Name>
> <Color>Black</Color>
<row EmployeeID="2" ContactID="1030" </row>
Loginid="adventure-works\kevin0" In the preceding format, for ProductID 1, the xsi:nil
Title="Marketing Assistant" /> attribute is added for the NULL value in the Color column.
If the ELEMENTS directive is specified with the FOR In EXPLICIT mode queries, you can use the elementxsinil
XML clause, each column value is mapped to a column mode to yield empty elements for the columns
subelement of the <row> element, as shown in the having NULL.
following query: Using the AUTO Mode
SELECT EmployeeID, ContactID, LoginID, The AUTO mode is used to return query results as nested
Title XML elements. Similar to the RAW mode, each column
FROM HumanResources.Employee value that is not NULL is mapped to an attribute that is
WHERE EmployeeID=1 OR EmployeeID=2 named after either the column name or the column alias.
FOR XML RAW, ELEMENTS The element that these attributes belong to is named to the
The preceding query displays the employee details in the table that they belong to or to the table alias that is used in
following format: the SELECT statement, as shown in the following query:
<row> SELECT EmployeeID, ContactID, LoginID,
<EmployeeID>1</EmployeeID> Title
<ContactID>1209</ContactID> FROM HumanResources.Employee Employee
<LoginID>adventure-works\guy1</ WHERE EmployeeID=1 OR EmployeeID=2
LoginID> FOR XML AUTO
<Title>Production Technician - The preceding query displays employee details in the
WC60</Title> following format:
</row> <Employee EmployeeID="1"
<row> ContactID="1209" Loginid="adventure
<EmployeeID>2</EmployeeID> works\guy1" Title="Production
<ContactID>1030</ContactID> Technician - WC60" />
<LoginID>adventure-works\kevin0</ <Employee EmployeeID="2"
LoginID> ContactID="1030" Loginid="adventure-
<Title>Marketing Assistant</Title> works\kevin0" Title="Marketing
</row> Assistant" />
When element-centric XML is returned, null columns are If the optional ELEMENTS directive is specified in the
omitted in the results. However, you can specify that null FOR XML clause, the columns listed in the SELECT
columns should yield empty elements with the xsi:nil clause are mapped to subelements, as shown in the
attribute instead of being omitted. For this, you can use the following query:
XSINIL option with the ELEMENTS directive in AUTO, SELECT EmployeeID, ContactID, LoginID,
Title LastName "EmpName/Last"
FROM HumanResources.Employee Employee FROM HumanResources.Employee e JOIN
WHERE EmployeeID=1 OR EmployeeID=2 Person.Contact c
FOR XML AUTO, ELEMENTS ON e.ContactID = c.ContactID
The output of the preceding query is displayed in the AND e.EmployeeID=1
following format: FOR XML PATH('Employee')
<Employee> The preceding query displays the output in the following
<EmployeeID>1</EmployeeID> format:
<ContactID>1209</ContactID> <Employee EmpID="1">
<LoginID>adventure-works\guy1</ <EmpName>
LoginID> <First>Guy</First>
<Title>Production Technician - <Middle>R</Middle>
WC60</Title> <Last>Gilbert</Last>
</Employee> </EmpName>
<Employee> </Employee>
<EmployeeID>2</EmployeeID> In the preceding format, the Employee element becomes
<ContactID>1030</ContactID> the root element.
<LoginID>adventure-works\kevin0</ Using the EXPLICIT Mode
LoginID> The EXPLICIT mode is used to return an XML file that
<Title>Marketing Assistant</Title> obtains the format as specified in the SELECT statement.
</Employee> Separate SELECT statements can be combined with the
Using the PATH Mode UNION ALL statement to generate each level/element in
The PATH mode is used to return specific values by the resulting XML output. Each of these SELECT
indicating the column names for which you need to statements requires the first two tags to be called Tag and
retrieve the data, as shown in the following query: Parent. The Parent element is used to control the nesting
SELECT EmployeeID "@EmpID", of elements. It contains the tag number of the parent
FirstName "EmpName/First", element of the current element. The top-level element in
MiddleName "EmpName/Middle", the document should have the Parent value set to 0 or
LastName "EmpName/Last" NULL.
FROM HumanResources.Employee e JOIN While writing EXPLICIT mode queries, column names in
Person.Contact c the resulting rowset must be specified in the following
ON e.ContactID = c.ContactID format:
AND e.EmployeeID=1 ElementName!TagNumber!AttributeName!
FOR XML PATH Directive
The preceding query displays the output in the following where,
format: ElementName specifies the name of the element.
<row EmpID="1"> TagNumber specifies the unique tag value assigned to an
<EmpName>
element. It, along with the value in the Parent tag,
<First>Guy</First>
determines the nesting of the elements in the resulting
<Middle>R</Middle>
XML.
<Last>Gilbert</Last>
</EmpName> AttributeName specifies the name of the attribute.
</row> This attribute will be created in the element specified by
In the preceding format, the EmployeeID column is the ElementName, if the directive is not specified.
mapped to the EmpID attribute, and FirstName, Directive specifies the type of AttributeName. It is
MiddleName, and LastName columns are mapped as used to provide additional information for construction of
subelements of the EmpName element. A node preceded the XML. It is optional and can have values, such as xml,
by '@' symbol represents an attribute. Subelements are cdata, or element. If you specify the element, it will
preceded by the parent element name followed by the /. generate a subelement instead of an attribute.
You can also use the optional ElementName argument For example, the managers of AdventureWorks want to
with the PATH mode query to modify the name of the access the information regarding products through their
default row element, as shown in the following query: mobile devices. These devices cannot directly connect to
SELECT EmployeeID "@EmpID", SQL Server but can read the data provided in the XML
FirstName "EmpName/First", format. Therefore, you need to convert the details of the
MiddleName "EmpName/Middle", products from the Product table into the XML document.
To perform this task, you need to create an XML
document with <Product> as the parent tag. The
<Product> tag will contain ProductID as an attribute, and
<ProductName> and <Color> as child elements.
To perform this task, you can create the following query:
SELECT 1 AS Tag,
NULL AS Parent,
ProductID AS [Product!1!ProductID],
Name AS [Product!1!ProductName!
element],
Color AS [Product!1!Color!
elementxsinil]
FROM Production.Product
Where ProductID = 1 OR ProductID = 317
FOR XML EXPLICIT
The preceding query assigns 1 as Tag value for the
<Product> element and NULL as Parent because
<Product> is the top-level element. Including XML Namespaces
The Product!1!ProductID column specifies that the An XML namespace is a collection of elements and
ProductId will be the attribute of the Product element. If attributes. It is used to resolve naming conflicts among the
the type of the node is not specified, it will be an attribute elements. The elements belonging to a particular
by default. namespace cannot have similar names. The name of the
The Product!1!ProductName!element column specifies XML namespace is in the form of Uniform Resource
that the ProductName will be the child element of Product Identifier (URI). If needed, it can also be given an alias
as the type is specified as element. name.
The Product!1!Color!elementxsinil column specifies that You can add a namespace to the XML data retrived from
the Color element will be the child element of Product. It the database tables. The WITH NAMESPACES clause can
also generates the element for null values as the type is be used with the FOR XML clause to specify the
specified as elementxsinil. namespace and the alias.
The execution of the preceding query generates the output Consider the following statement:
in the following format: WITH XMLNAMESPACES ('http://
<Product xmlns:xsi="http:// www.adventureWorks.com' AS ad)
www.w3.org/2001/XMLSchema-instance" SELECT EmployeeID AS 'ad:EMPID',
ProductID="1"> ContactID AS 'ad:ContactID',
<ProductName>Adjustable Race</ Title AS 'ad:Title'
ProductName> FROM HumanResources.Employee Employee
<Color xsi:nil="true" /> FOR XML RAW ('ad:Employee'), ELEMENTS
</Product> In the preceding statement, the data is retrieved in an XML
<Product xmlns:xsi="http:// format from the table, Employee. The WITH
www.w3.org/2001/XMLSchema-instance" XMLNAMESPACES clause accepts two arguments. The
ProductID="317"> first argument is the name of the namespace in URI
<ProductName>LL Crankarm</ format, and the second argument is the alias given to the
ProductName> namespace.
<Color>Black</Color> Once executed, the preceding statement gives the
</Product> following output:
ad:Employee xmlns:ad="http://
www.adventureWorks.com">
<ad:EMPID>1</ad:EMPID>
<ad:ContactID>1209</ad:ContactID>
<ad:Title>Production Technician -
WC60</ad:Title>
</ad:Employee>
<ad:Employee xmlns:ad="http://
www.adventureWorks.com">
<ad:EMPID>2</ad:EMPID>
<ad:ContactID>1030</ad:ContactID> '<?xml version="1.0" ?>
<ad:Title>Marketing Assistant</ <DeliveryList xmlns="http://
ad:Title> schemas.adventure works.com/
</ad:Employee> DeliverySchedule">
Using XQuery <Delivery SalesOrderID="43659">
<CustomerName>Steve Schmidt</
In addition to FOR XML, SQL Server allows you to
CustomerName>
extract data stored in variables or columns with the XML
<Address>6126 North Sixth
data type by using XQuery. XQuery is a language that
Street, Rockhampton</Address>
uses a set of statements and functions provided by the
</Delivery>
XML data type to extract data. As compared to the FOR
<Delivery SalesOrderID="43660">
XML clause of the SELECT statement, the XQuery
<CustomerName>Tony Lopez</
statements allow you to extract specific parts of the XML
CustomerName>
data.
<Address>6445 Cashew Street,
Each XQuery statement consists of two parts, prolog and Rockhampton</Address>
body. In the prolog section, you declare the namespaces. </Delivery>
In addition, schemas can be imported in the prolog. The </DeliveryList>')
body part specifies the XML nodes to be retrieved. It
contains query expressions that define the result of the
The following query retrieves the delivery driver
query. The XQuery language supports the following
and the name of the customers from the
expressions:
DeliverySchedule table:
 for: Used to iterate through a set of nodes at the SELECT DeliveryDriver,
same level as in an XML document. DeliveryList.query
 let: Used to declare variables and assign values. ('declare namespace ns="http://
 order by: Used to specify a sequence. schemas.adventure works.com/
 where: Used to specify criteria for the data to be DeliverySchedule";
extracted. ns:DeliveryList/ns:Delivery/
 return: Used to specify the XML returned from a ns:CustomerName') as 'Customer
statement. Names'
The preceding expressions are defined by the acronym FROM Sales.DeliverySchedule
FLOWR (pronounced "flower"). The XQuery statements In the preceding query, the query() function is
also use the following functions provided by the XML used to retrieve the customer names. This
data type: function is taking the path of the CustomerName
 Query: Used to extract XML from an XML data element as a parameter. Here, ns is the prefix of
type. The XML to be retrieved is specified by the the namespace used in the XML document.
XQuery expression passed as a parameter.  Value: Used to return a single value from an
For example, the following DeliverySchedule XML document. To extract a single value, you
table in the Sales schema stores the delivery need to specify an XQuery expression that
details of the sales orders. identifies a single node and a data type of the
value to be retrieved.
Column Name Data Type For example, the following query retrieves the
ScheduleID int IDENTITY address of the first delivery:
PRIMARY KEY SELECT DeliveryList.value
ScheduleDate DateTime ('declare namespace ns="http://
DeliveryRoute int schemas.adventure works.com/
DeliveryDriver nvarchar(20) DeliverySchedule";
(ns:DeliveryList/ns:Delivery/
DeliveryList Xml
ns:Address)[1]', 'nvarchar(100)')
DeliveryAddress
The DeliverySchedule Table FROM Sales.DeliverySchedule
A record is inserted into the DeliverySchedule In the preceding query, the value() function takes
table by using the following statement: two parameters, the path of Address element and
INSERT INTO its data type. Here, '(ns:DeliveryList/ns:Delivery/
Sales.DeliverySchedule ns:Address)[1]' represents the index of the first
VALUES address. The preceding query will display the
(GetDate(), 3, 'Bill',
result, as shown in the following figure.

The Ouput Derived After Using the value() function


 Exist: Used to check the existence of a node in an
XML data. The function returns 1 if the specified
node exists, else it returns 0. The following query
finds the driver for a specific order:
SELECT DeliveryDriver
FROM Sales.DeliverySchedule
WHERE DeliveryList.exist
('declare namespace ns="http://
schemas.adventure works.com/
DeliverySchedule";
/ns:DeliveryList/ns:Delivery
[@SalesOrderID=43659]') = 1
The preceding query returns the driver for the
order whose sales order ID is 1, as shown in the
following figure. Modifying XML Data
Similar to any other type of data, you might also need to
modify XML data. For this, you can use the modify
function provided by the XML data type of SQL Server.
The Ouput Derived After Using the SELECT statement The modify function specifies an XQuery expression and a
statement that specifies the kind of modification that needs
to be done. This function allows you to perform the
following modifications:
 Insert: Used to add nodes to XML in an XML
column or variable. For example, in the
Adventureworks database, the customer details
are stored in the following CustomDetails table.

The CustomDetails Table


In the preceding table, the customer details are
stored in an XML format in the Cust_Details
column. The management of AdventureWorks
wants to store the type of the customer in the
CustomDetails table. This can be done by adding
an attribute, Type in the XML data of the
Cust_Details column. The default value of the
Type attribute should be 'Credit'. To perform the
required task, you can create the following
statement:
UPDATE CustomDetails SET
Cust_Details.modify('
insert attribute Type{"Credit"}
as first
into (/Customer)[1]')
The execution of the preceding statement adds the
Type attribute with a default value, Credit. The 'as
first' clause specifies that the attribute will be
inserted in the beginning of all attributes. After
the addition of the attribute, the CustomDetails
table will contain the data, as shown in the
following figure.

The CustomDetails Table After Deleting the Attribute

Activity 5.3: Working with XML


The CustomDetails Table After Adding a New Data
Attribute
 Replace: Used to update XML data. For example,
James Stephen, one of the customers of
AdventureWorks, has decided to change his Summary
customer type from Credit to Cash. As a database In this chapter, you learned that:
developer, you can create the following statement  The INSERT statement is used to insert data into
to reflect this change: a table.
UPDATE CustomDetails SET  While inserting data into a table, the data type of
Cust_Details.modify (' the information must match the data types of the
replace value of(Customer/@Type) columns of the table.
[1] with "Cash"') WHERE Cust_ID =  If a default value is not specified for a column,
3 and the column property is specified as NULL,
In the preceding statement, the value of the Type NULL is inserted into the column.
attribute will be replaced as cash for the customer  A column in a table for which the values are
whose customer ID is 3. After replacing the automatically generated by the database is called
attribute, the CustomDetails table will contain the an identity column.
data, as shown in the following figure.  You can copy contents from one table into
another table by using the SELECT INTO
statement.
 You can insert the FILESTREAM data into a
table as a value of the varbinary (max) data type.
 SQL server provides you with the GEOGRAPHY
The CustomDetails Table After Replacing the data type to store geographic locations as points.
Attribute Value  You can use the UPDATE statement to make
 Delete: Used to remove a node from XML data. changes in a table.
For example, the management of  You can delete a row from a table by using the
AdventureWorks has decided to remove the DELETE DML statement.
details of the city from the customer details. You  You use the TRUNCATE TABLE statement to
can write the following statement to remove the remove all the rows from a table.
City attribute:  The OUTPUT clause is used to retrieve the set of
UPDATE CustomDetails SET rows affected by the DML statements.
Cust_Details.modify (  The MERGE statement enables you to perform
'delete(/Customer/@City)[1]') insert, update, and delete operations in a single
The preceding statement deletes the City attribute statement.
from the Cust_Details column in the  SQL Server uses XML as a data type to save
CustomDetails table. XML data in its original state.
After deleting the attribute, the CustomDetails  SQL Server allows you to shred XML data by
table will contain the data, as shown in the using the OPENXML function and its related
following figure. stored procedures.
 Untyped XML data is a well-formed data, but is
not associated with a schema.
 Typed XML data is a well-formed data that is
associated with a schema.
 You can create an XML schema collection object
by using the CREATE XML SCHEMA
COLLECTION statement.
 You can use the FOR XML clause of the
SELECT statement to retrieve the XML data in
different ways by using the RAW, AUTO, PATH,
and EXPLICIT modes.
 You can use the XQuery functions to extract
XML data stored in a column with the XML data
type.
 The XQuery statement uses the Query, Value, and
Exist functions to query XML data in a table.
 You can modify XML data by using the modify
function provided by the XML data type.
 Using the modify function, you can insert,
update, or remove a node from XML data.

Reference Reading
Manipulating Data by Using DML
Statements

Reference Reading: Books Reference Reading: URLs


Microsoft SQL Server 2012 http://msdn.microsoft.com/
Bible by Adam Jorgensen, en-us/library/ff848766.aspx
Jorge Segarra, and Patrick
LeBlanc

Manipulating XML Data

Reference Reading: Books Reference Reading: URLs


SQL Server 2012 T-SQL http://
Recipes: A Problem- www.pearsonitcertification.c
Solution Approach by Jason om/articles/article.aspx?
Brimhall, David Dye, and p=101369&#38;seqNum=5
Andy Roberts
understand the need to implement an index.
The data in the database tables is stored in the form of data
pages. Each data page is 8 KB in size. Therefore, the
Chapter 6 entire data of the table is stored in multiple data pages.
When a user queries a data value from the table, the query
Implementing Indexes, Views, and processor searches for the data value in all the data pages.
When it finds the value, it returns the result set. As the
Full-Text Search data in the table increases, this process of querying data
A database developer is often required to improve the takes time.
performance of queries. SQL Server allows you to reduce To reduce the data query time, SQL Server allows you to
the execution time of queries by implementing indexes. In implement indexes on tables. An index is a data structure
addition, you can restrict the view of data to different associated with a table that enables fast searching of data.
users by implementing views. Indexes in SQL Server are like the indexes at the back of a
SQL Server also provides an in-built full-text search book that you can use to locate text in the book.
capability to allow fast searching of data. Indexes provide the following benefits:
This chapter discusses how to create and manage indexes  Accelerate queries that join tables, and perform
and views. In addition, it discusses about implementing sorting and grouping
the full-text search capability.  Enforce uniqueness of rows, (if configured for
that)
Objectives An index contains a collection of keys and pointers. Keys
are the values built from one or more columns in the table.
In this chapter, you will learn to: The column on which the key is built is the one on which
 Create and manage indexes the data is frequently searched. Pointers store the address
 Create and manage views of the location where a data page is stored in the memory.
 Implement a full-text search The following figure depicts the structure of an index.

Creating and Managing Indexes


When a user queries data from a table based on conditions,
the server scans all the data stored in the database table.
With an increasing volume of data, the execution time for
queries also increases. As a database developer, you need
to ensure that the users are able to access data in the least
possible time. SQL Server allows you to create indexes on
tables to enable quick access to data. In addition, SQL
Server allows you to create XML indexes for columns that
store XML data.
At times, the table that you need to search contains huge
amount of data. In such cases, it is advisable to create
partitioned indexes. A partitioned index makes the index
more manageable and scaleable as they store data of a The Structure of an Index
particular partition only. When the users query data with conditions based on the
As a database developer, you need to create and manage key columns, the query processor scans the indexes,
indexes. Before creating an index, it is important to retrieves the address of the data page where the required
identify different types of indexes. data is stored, and accesses the information. The query
Sometimes, you need to view and control the execution processor does not need to search for data in all the data
plan of a query. SQL Server provides the facility to view pages. Therefore, the query execution time is reduced.
the execution plan of a query. In addition, you can control The keys in the indexes are stored in a B-Tree structure in
the execution plan of an query by using various types of the memory. A B-Tree is a data-indexing method that
hints. organizes the index into a multilevel set of nodes. Each
page in an index B-Tree is called an index node. Each
index contains a single root page at the top of the tree.
Identifying the Types of Indexes This root page, or root node, branches out into n number
of pages at each intermediate level until it reaches the
Before identifying the types of indexes, it is important to
bottom, or leaf level of the index. The index tree is
traversed by following pointers from the upper-level pages
down through the lower-level pages.
The key values in the root page and the intermediate pages
are sorted in the ascending order. Therefore, in the B-Tree
structure, the set of nodes on which the server will search
for data values is reduced. This enables SQL Server to find
the records associated with the key values quickly and
efficiently. When you modify the data of an indexed
column, the associated indexes are updated automatically.
SQL Server allows you to create the following types of
indexes:
 Clustered index
 Nonclustered index
Clustered Index
A clustered index is an index that sorts and stores the data The Working of a Clustered Index
rows in the table based on their key values. Therefore, the The preceding figure displays a clustered index on the
data is physically sorted in the table when a clustered Employee table. To search for any record, SQL Server
index is defined on it. Only one clustered index can be would start at the root page. It would then move down the
created per table. Therefore, you should build the clustered B-Tree and the data values would be found on the leaf
index on attributes that have a high percentage of unique pages of the B-Tree. For example, if the row containing
values and are not modified often. Eid E006 was to be searched by using a clustered index
In a clustered index, data is stored at the leaf level of the (refer to the preceding figure), SQL Server performs the
B-Tree. SQL Server performs the following steps when it following steps:
uses a clustered index to search for a value: 1. SQL Server starts from page 603, the root page.
1. SQL Server obtains the address of the root page 2. SQL Server searches for the highest key value on
from the sysindexes table, which is a system table the page, which is less than or equal to the search
containing the details of all the indexes in the value. The result of this search is the page
database. containing the pointer to Eid, E005.
2. The search value is compared with the key values 3. The search continues from page 602. There, Eid
on the root page. E005 is found and the search continues to page
3. The page with the highest key value less than or 203.
equal to the search value is found. 4. Page 203 is searched to find the required row.
4. The page pointer is followed to the next lower
level in the index.
A clustered index determines the order in which the
5. Steps 3 and 4 are repeated until the data page is
rows are actually stored. Therefore, you can define only one
reached.
clustered index on a table.
6. The rows of data are searched on the data page
until the search value is found. If the search value Nonclustered Index
is not found on the data page, no rows are Similar to the clustered index, a nonclustered index also
returned by the query. contains the index key values and the row locators that
For example, the rows of the Employee table are sorted point to the storage location of the data in a table.
according to the Eid attribute. The following figure shows However, in a nonclustered index, the physical order of
the working of a clustered index for the Employee table. the rows is not the same as the index order.
Nonclustered indexes are typically created on columns
used in joins and the WHERE clause. These indexes can
also be created on columns where the values are modified
frequently. SQL Server creates nonclustered indexes by
default when the CREATE INDEX command is given.
There can be as many as 999 nonclustered indexes per
table.
The data in a nonclustered index is present in a random
order, but the logical ordering is specified by the index.
The data rows may be randomly spread throughout the
table. The nonclustered index tree contains the index keys actual row. Page 203 is the last page, or the leaf
in a sorted order, with the leaf level of the index page of the index.
containing a pointer to the data page. 6. The search then moves to page 302 of the table to
SQL Server performs the following steps when it uses a find the actual row.
nonclustered index to search for a value:
1. SQL Server obtains the address of the root page In an index, more than one row can contain duplicate
from the sysindexes table. values. However, if you configure an index to contain unique
2. The search value is compared with the key values values, the index will also contain unique values. Such an
on the root page. index is called a unique index. You can create a unique index
3. The page with the highest key value less than or on columns that contain unique values, such as the primary
equal to the search value is found. key columns.
4. The page pointer is followed to the next lower A unique index can be clustered or nonclustered depending
level in the index. on the nature of the column on which it is built.
5. Steps 3 and 4 are repeated until the data page is
reached.
6. The rows are searched on the leaf page for the Creating Indexes
specified value. If a match is not found, the table
contains no matching rows. If a match is found, You should create indexes on the most frequently queried
the pointer is followed to the data page and the columns in a table. However, at times, you might need to
requested row is retrieved. create an index based on the combination of one or more
The following figure represents the working of a columns. An index based on one or more columns is called
nonclustered index. a composite index. A composite index can be based on a
maximum of 16 columns. The maximum allowable size of
the combined index values is 900 bytes. Columns that are
of the Large Object (LOB) data types, such as ntext, text,
varchar(max), nvarchar(max), varbinary(max), xml, or
image cannot be specified as key columns for an index.
However, indexes with less number of columns use less
disk space and involve fewer resources when compared to
indexes based on more columns.
To create an index, you can use the CREATE INDEX
statement. The syntax of the CREATE INDEX statement
is:
CREATE [UNIQUE][CLUSTERED |
NONCLUSTERED] INDEX index_name
ON [{database_name.[schema_name]. |
The Working of a Nonclustered Index schema_name.}]
The preceding figure displays a nonclustered index present {table_or_view_name}(column [ASC |
DESC][,...n])
on the Eid attribute of the Employee table. To search for
[INCLUDE (column_name [,...n])]
any value, SQL Server would start from the root page and
[WITH(<relational_index_option>
move down the B-Tree until it reaches a leaf page that
[,...n])]
contains a pointer to the required record. It would then use
[ON {partition_scheme_name
this pointer to access the record in the table. For example,
(column_name)
to search for the record containing Eid, E006 by using the
| filegroup_name | DEFAULT}]
nonclustered index, SQL Server performs the following
<relation_index_option>::=
steps:
{PAD_INDEX = {ON | OFF}
1. SQL Server starts from page 603, which is the | FILLFACTOR = fillfactor
root page. | SORT_IN_TEMPDB = {ON | OFF}
2. It searches for the highest key value less than or | IGNORE_DUP_KEY = {ON | OFF}
equal to the search value, that is, the page | STATISTICS_NO_RECOMPUTE = {ON | OFF}
containing the pointer to Eid, E005. | DROP_EXISTING = {ON | OFF}
3. The search continues from page 602. | ONLINE = {ON | OFF}
4. Eid, E005 is found and the search continues to where,
page 203. UNIQUE creates an index where each row should contain
5. Page 203 is searched to find a pointer to the
a different index value. WITH FILLFACTOR = 10
CLUSTERED specifies a clustered index where data is In the preceding code, the FILLFACTOR value of 10 has
sorted on the index attribute. been specified to reserve a percentage of free space on
NONCLUSTERED specifies a nonclustered index that each data page of the index to accommodate future
organizes data logically. The data is not sorted physically. expansion.
index_name specifies the name of the index. The following example creates a nonclustered index on the
table_or_view_name specifies the name of the table ManagerID attribute of the Employee table:
or view that contains the attributes on which the index is CREATE NONCLUSTERED INDEX
to be created. IDX_Employee_ManagerID
ON Employee (ManagerID)
column specifies the column or columns on which the
index will be created.
INCLUDE (column_name [,...n])] specifies the When a PRIMARY KEY or UNIQUE constraint is
columns as non-key members of a - index to covermore created on a table, an index is created automatically with the
queries. It improves the query performance as all the same name as the constraint.
columns in the query are included in the index either as Consider another example, where users frequently query
key or non-key columns. the Document table that contains the following three
ON partition_scheme_name (column_name) columns:
specifies the partition scheme along with the column  Title nvarchar(50)
name. The partition scheme defines the filegroups onto  FileName nvarchar(400)
which the partitions of the partitioned index will be  FileExtension nvarchar(8)
mapped. The column name specifies the column against To enhance the performance of such queries, you need to
which a partitioned index will be partitioned. create a nonclustered index that includes all the three
ON filegroup_name specifies the filegroup on which columns. However, while creating an index, you need to
index is created. consider that the size of the index key columns should not
ON DEFAULT specifies that the specified index will be exceed 900 bytes. In the preceding example, size of all the
created on the default filegroup. three columns would be 916 bytes (458 * 2) as both the
PAD_INDEX = { ON | OFF } specifies the index nchar and nvarchar data types require two bytes for each
padding, which is OFF, by default. character. To avoid exceeding this limitation, you can
FILLFACTOR = fillfactor specifies a percentage create an index that contains the Title and FileExtension
columns, and include FileName as a non-key column. In
that indicates how full the leaf level of each index page
this way, the index size would be 114 bytes (58 * 2). You
should become during index creation or rebuild. The
can use the following statement to create such an index:
default value is 0.
CREATE INDEX IX_Doc_Title
SORT_IN_TEMPDB = { ON | OFF } specifies
ON Production.Document (Title,
about storing temporary sort results in tempdb. FileExtension)
IGNORE_DUP_KEY = { ON | OFF } specifies INCLUDE (FileName);
whether a duplicate key value can be inserted. The preceding statement creates a nonclustered index on
STATISTICS_NO_RECOMPUTE = { ON | OFF } the Document table. This index contains two key columns,
specifies about recomputing the distribution statistics. Title and FileExtension, and one non-key column,
DROP_EXISTING = { ON | OFF } specifies that FileName. Therefore, this index covers all the required
the preexisting clustered, nonclustered, or XML index is columns with index key size still under the limit. This
dropped and rebuilt. way, you can create nonclustered indexes that cover all the
ONLINE = { ON | OFF } checks whether the columns in the query. This enhances the performance of
underlying tables and associated indexes are available to the query as all the columns included in the query are
query and modify the data during the index operation. covered within the index either as key or non-key
columns.
You can create online indexes only in the SQL Server Guidelines for Creating Indexes
Enterprise Edition. You need to consider the following guidelines while
Consider an example of an organization that maintains creating indexes on a table:
employee details in the Employee table. You can create a  Create clustered indexes on columns that have
clustered index on the EmployeeID attribute of the unique or not null values.
Employee table by using the following code:  Do not create an index that is not used frequently.
CREATE CLUSTERED INDEX IX_EmployeeID You require time and resources to maintain
ON Employee (EmployeeID) indexes.
 Create a clustered index before creating a
nonclustered index. A clustered index changes the Creating XML Indexes
order of rows. A nonclustered index would need
When a query is based on an XML column, the query
to be rebuilt if it is built before a clustered index.
processor needs to parse the XML data each time the
 Create nonclustered indexes on all columns that
query is executed. In SQL Server, an XML data value can
are frequently used in predicates and join
be of a maximum of 2 GB. Therefore, the XML values can
conditions in queries.
be very large and the server might take time to generate
Creating Filtered Indexes the result set. To speed up the execution of the query based
Consider a scenario where you have created an index on a on the XML data type, SQL Server allows you to create an
particular column of a table to retrieve data. The data in index that is based on columns storing XML data values.
the table is huge. Therefore, the indexing process took a Such indexes are called XML indexes.
long time to search for an item in the table. SQL Server XML indexes are of the following types:
allows you to solve this problem by creating filtered  Primary XML index
indexes. A filtered index allows you to create an index on  Secondary XML index
the specific rows of a column rather than the entire
column. Therefore, it creates a filter to index a subset of
Primary XML Index
rows within a table. This helps in reducing the index This is a clustered B-Tree representation of the nodes in
storage space and maintainance costs as compared to full- the XML data. When an index is created on a column with
table indexes. the XML data type, an entry will be created for all the
nodes in the XML data. Therefore, the index creates
You can create a filtered index based on a condition
several rows of data for each XML value in the column.
specified by the WHERE clause. Filtered indexes do not
To create a primary XML index, the table must have a
allow the IGNORE_DUP_KEY option. Only nonclustered
clustered index on the primary key column.
filtered indexes can be created on a table. For example,
you need to create a filtered index for those records in the You can create XML indexes on XML columns by using
Employee table, where the value in the Title column is the CREATE PRIMARY XML INDEX and CREATE
Tool Manager. Execute the following statement to create XML INDEX T-SQL commands. For example, the
the specified index: ProductModel table contains the CatalogDescription
CREATE NONCLUSTERED INDEX column that stores XML values. You can create a primary
FX_EmployeeID XML index on this column by using the following
ON HumanResources.Employee(EmployeeID) statement:
WHERE Title= 'Tool Manager' CREATE PRIMARY XML INDEX
PXML_ProductModel_CatalogDescription
In the preceding statement, the FX_EmployeeID index is
ON Production.ProductModel
created on the EmployeeID column of the
(CatalogDescription)
HumanResources.Employee database based on a value in
the Title column. The preceding statement will create an index for all the
nodes in the XML data stored in the CatalogDescription
column.

The first index on an XML type column must be the


primary XML index.
Secondary XML Index
This is a nonclustered index of the primary XML index. A
primary XML index must exist before any secondary
index can be created on a table. After you have created the
primary XML index, an additional three kinds of
secondary XML indexes can be defined on the table. The
secondary XML indexes assist in the XQuery processing.
The three types of secondary XML indexes are:
 Path indexes
 Value indexes
 Property indexes
Path Indexes
The path index is built on the path id and value columns of
the primary XML indexes. This index improves the
performance of queries that use paths and values to select ROPERTY ON Production.ProductModel
data. (CatalogDescription)
For example, if you execute a query that checks for the USING XML INDEX
existence of a product model ID by using an XQuery PXML_ProductModel_CatalogDescription
expression as /PD:ProductDescription/@ProductModelID FOR PROPERTY
[.="19"], you can create a path secondary index on the The preceding statement creates a property index,
CatalogDescription column of the ProductModel table. In PIdx_ProductModel_CatalogDescription_PROPERTY, on
this path index, you can use the primary index created the CatalogDescription column of the table.
previously. You need to consider the following guidelines while
The following statement creates a Path index on the creating an XML index:
CatalogDescription column:  XML indexes can be created only on XML
CREATE XML INDEX columns.
PIdx_ProductModel_CatalogDescription_P  XML indexes only support indexing a single
ATH ON Production.ProductModel XML column.
(CatalogDescription)  XML indexes can only be added to tables, views,
USING XML INDEX table-valued variables with XML columns or
PXML_ProductModel_CatalogDescription XML variables.
FOR PATH  XML indexes created on a table do not allow you
The preceding statement creates a path index, to modify the primary key. To do so, you first
PIdx_ProductModel_CatalogDescription_PATH, on the need to drop all the XML indexes on the table.
CatalogDescription column of the table.
Value Indexes
The value indexes contain the same items as path indexes
but in the reverse order. It contains the value of the column
first and then the path id. This index improves the
performance of queries that use paths to select data.
For example, if you execute a query that checks the
existence of a node in an XQuery expression such as //
Item[@ProductID="1"], you can create a value secondary
index by using the primary index created previously.
The following statement creates a value index on the
CatalogDescription column:
CREATE XML INDEX
PIdx_ProductModel_CatalogDescription_V
ALUE ON Production.ProductModel
(CatalogDescription)
USING XML INDEX
PXML_ProductModel_CatalogDescription
FOR VALUE
The preceding statement creates a value index,
PIdx_ProductModel_CatalogDescription_VALUE, on the
CatalogDescription column of the table.
Property Indexes
The property index contains the primary key of the base
table, path id, and the clause columns of primary XML
indexes. This index improves the performance of queries
that use paths to select data.
For example, if you execute a query that returns a value of
the node in an XQuery expression, such as /ItemList/Item/
@ProductID)[1], you can create a property secondary
index on the CatalogDescription column of the
ProductModel table by using the following statement:
CREATE XML INDEX
PIdx_ProductModel_CatalogDescription_P
function, there will be five partitions. The data of each
Creating Partitioned Indexes partition is stored in a filegroup. You should have the same
number of filegroups as partitions. If there are five
In SQL Server, indexes can also be partitioned based on
partitions, you need to create five filegroups: fg1, fg2, fg3,
the value ranges. Similar to the partitioned tables, the
fg4, and fg5. Then, create at least one file in each of these
partitioned indexes also improve query performance.
filegroups.
Partitioning enables you to manage and access subsets of
data quickly and efficiently. When indexes become very The following statement create the PSOrderDate partition
large, you can partition the data into smaller, more scheme, associating it with the PFOrderDate partition
manageable sections as the data is spread across filegroups function:
CREATE PARTITION SCHEME PSOrderDate
in a database.
AS PARTITION PFOrderDate
Consider an example. In the AdventureWorks database,
TO (fg1, fg2, fg3, fg4, fg5)
the SalesOrderHeader table contains the details about the
The partition scheme, PSOrderDate, created in the
orders received by AdventureWorks, Inc. As the data in
preceding statement directs each partition to a separate
this table is large, the query takes a long time to execute.
filegroup.
To solve this problem, you can create a partitioned index
on the table. Partitioning an index will distribute the data Creating a Clustered Index
in the table into multiple filegroups, thereby partitioning After creating the partition scheme, you need to associate
the table. This will enable the database engine to read or it with a clustered index. As the clustered index is created
write data quickly. This also helps in maintaining the data on the attribute having unique and non-null values, you
efficiently. can create the index on the SalesOrderID column of the
To create a partitioned index, you need to perform the SalesOrderHeader table. To create the partitioned index,
following tasks: you need to associate the clustered index with the partition
1. Create a partition function. scheme:
2. Create a partition scheme. CREATE CLUSTERED INDEX ix_SalesOrderID
3. Create a clustered index. ON Sales.MySalesOrderHeader
(SalesOrderID)
Creating a Partition Function ON PSOrderDate (OrderDate)
Similar to creating a partitioned table, you need to create a The preceding statement will distribute the table data into
partition function to create a partitioned index. The five filegroups based on the yearly data of orders stored in
partition function will determine the boundary values for the OrderDate column.
creating partitions.
Consider an example. The queries on the
SalesOrderHeader table are mostly based on the
OrderDate column. The sales manager of AdventureWorks
requires the details of the orders received, on a yearly
basis. The table contains the details of orders for the last
five years beginning from 2001. Based on this
information, you can create a partition function:
CREATE PARTITION FUNCTION PFOrderDate
(datetime)
AS RANGE RIGHT FOR VALUES
('2002-01-01', '2003-01-01',
'2004-01-01', '2005-01-01')
The preceding statement creates a partition function,
PFOrderDate, by using the datetime data type. It specifies
four boundary values. Therefore, there will be five
partitions. As range right is specified for partitioning, the
first partition will contain data less than the first boundary
value, 2002-01-01. The second partition will contain data
greater than or equal to 2002-01-01 and less than or equal
to 2003-01-01. Similarly, other partitions will store data. Managing Indexes
Creating a Partition Scheme In addition to creating indexes, you also need to maintain
After creating the partition function, you need to create a them to ensure their continued optimal performance. The
partition scheme to associate it with the partition function. common index maintenance tasks include disabling,
Based on the boundary values defined in the partition enabling, renaming, and dropping an index. As a database
developer, you need to regularly monitor the performance DROP INDEX IDX_Employee_ManagerID
of the index and optimize it. ON Employee
Disabling Indexes Optimizing Indexes
When an index is disabled, the user is not able to access SQL Server automatically maintains indexes whenever
the index. If a clustered index is disabled then the table insert, update, or delete operations are made to the
data is not accessible to the user. However, the data still underlying data. These modifications cause the
remains in the table, but is unavailable for Data information within the index to become scattered in the
Modification Language (DML) operations until the index database. Fragmentation exists when indexes have pages
is dropped or rebuilt. where the logical ordering does not match the physical
To rebuild and enable a disabled index, use the ALTER ordering within the data file. Heavily fragmented indexes
INDEX REBUILD statement or the CREATE INDEX can degrade the query performance and cause your
WITH DROP_EXISTING statement. application to respond slowly.
The following query disables a nonclustered index, Fragmentation normally occurs when a large number of
IX_EmployeeID, on the Employee table: insert and update operations are performed on the table.
ALTER INDEX IX_EmployeeID Fragmented data can cause SQL Server to perform
ON Employee DISABLE unnecessary data reads. This affects the performance of
Enabling Indexes the query. Therefore, index defragmentation is necessary
to speed up the query performance.
After an index is disabled, it remains in the disabled state
until it is rebuilt or dropped. You can enable a disabled The first step in deciding which defragmentation method
index by rebuilding it through one of the following to use is to determine the degree of index fragmentation.
methods: You can detect index fragmentation by using the
sys.dm_db_index_physical_stats system function.
 Using the ALTER INDEX statement with the
REBUILD clause In SQL Server, index defragmentation can be done by
 Using the CREATE INDEX statement with the either reorganizing or rebuilding an index.
DROP_EXISTING clause The following statement displays a list of all the indexes
By using one of the preceding statements, the index is on the HumanResources.Employee table with their
rebuilt and the index status is set to enable. You can fragmentation level:
rebuild a disabled clustered index, when the ONLINE SELECT a.index_id AS IndexID, name AS
option is set to ON. The DROP_EXISTING clause is used IndexName,
to rebuild the index after dropping the existing clustered avg_fragmentation_in_percent AS
and nonclustered indexes. The new index must have the Fragmentation
FROM sys.dm_db_index_physical_stats
same name as that of an existing index. However, you can
(DB_ID (N'AdventureWorks'),
modify the index definition by specifying different
OBJECT_ID ('HumanResources.Employee'),
columns, sorting order, or partitioning scheme while
NULL, NULL, NULL) AS a
creating a new index.The default value of the
JOIN sys.indexes AS b ON a.object_id =
DROP_EXISTING index is set to OFF.
b.object_id AND a.index_id =
Renaming Indexes b.index_id ORDER BY Fragmentation desc
You can rename the current index with the help of the The following figure displays the output of the preceding
sp_rename system stored procedure. statement.
The following statement renames the
IX_JobCandidate_EmployeeID index on the JobCandidate
table to IX_EmployeeID:
EXEC sp_rename
'HumanResources.JobCandidate.IX_JobCan
didate_EmployeeID',
'IX_EmployeeID','index'
Dropping Indexes
When you no longer need an index, you can remove it
from a database. You cannot drop an index used by either The Output Derived by Using Fragmentation
a PRIMARY KEY or UNIQUE constraint, except by
dropping the constraint.
The following statement drops the The fragmentation shown in the preceding figure may
IDX_Employee_ManagerID index on the Employee table: differ based on the DML operations performed on the
HumanResources.Employee table in the AdventureWorks
database of your SQL Server instance. for executing a particular query. Once, the optimized
In the preceding output, you can notice that the execution plan is generated, the query is executed and
AK_Employee_LoginID index shows a high level of results are generated.
fragmentation. SQL Server provides the following types of formats to
After the degree of fragmentation is known, the view the execution plan:
fragmentation needs to be corrected. The following table  Graphical plan
lists the actions to be taken at different fragmentation  Text plan
levels to defragment the index.  XML plan
Graphical Plan
Fragmentation Level Action to be Taken Sometimes, as a database developer, you need to have
> 5% and < = 30% ALTER INDEX detailed analysis of execution plans. You also need to have
REORGANIZE query execution plan with information, such as data
> 30% ALTER INDEX REBUILD retrival method applied by the query optimizer, estimated
WITH (ONLINE = ON) row size, and estimated I/O cost. To accomplish this task,
you need to use the graphical execution plan.The graphical
Actions to be Taken at Different Fragmentation Levels execution plan provides the execution details of a query in
You can execute the following statement to defragment the the form of a tree structure. Each node in the tree structure
AK_Employee_LoginID index: is represented as an icon. Each icon specifies the logical
ALTER INDEX AK_Employee_LoginID ON and physical operator being used to execute that part of the
HumanResources.Employee query or statement.
REBUILD You can display either the estimated or the actual
After executing the preceding statement, the degree of execution plan. The estimated execution plan is displayed
fragmentation is reduced. The following figure displays before the execution of the query while the actual
the output of the preceding statement. execution plan is displayed after the execution of the
query.
You can view the estimated execution plan by selecting
the query in Query Editor. window and clicking the
Display Estimated Execution Plan button on the SQL
Editor toolbar.
You can view the execution plan by either of the following
ways:
 Clicking the Include Action Execution Plan
The Output button on the SQL Editor toolbar
 Right-clicking the query and selecting the Include
Action Execution Plan option
Displaying Execution Plan  Selecting the Include Action Execution Plan
option from the query menu
In the real-time environment, the faster excution of a For example, consider the following query:
query along with timely display of data is essential. If a SELECT e.EmployeeID,e.Title,
query is taking too much time to execute, you need to eph.Rate,eph.PayFrequency
analyse its performance. SQL Server provides the FROM HumanResources.Employee e
execution plan to view the details of execution of a SQL JOIN HumanResources.EmployeePayHistory
query. The execution plan of a query enables you to eph
identify how the SQL Server query optimizer executes that ON e.EmployeeID = eph.EmployeeID
query. In other words, the execution plan provides the The following figure displays the estimated execution plan
troubleshooting method to analyze a slow executing query. of the preceding query.
When a query is submitted to the database server, it is
parsed to generate a parse tree that represents the logical
steps to execute the query. The query optimizer processes
the parse tree to generate the best possible execution plan
for the query. This execution plan includes various factors,
such as the cost of the execution plan and the required
CPU time. In addition, it also decides the use of the index
Displaying the Estimated Execution Plan
In the preceding figure, the two clustered index scan icons
on the right side represents that the clustered indexes of
the HumanResources.Employee and
HumanResources.EmployeePayHistory tables are scanned
to execute the query. The result set produced after
scanning the index is merged by the Merge Join operator.
This merged result set is passed to the SELECT icon that The SELECT Page
is on the left side of the figure. The arrows in the figure In the preceding figure, the cached plan size represents the
show that the data is passed between the operators, as amount of memory the plan generated by this query will
represented by icons, such as SELECT, merge join, and take up in cache. The estimated operator cost represents
clustered index scan. the estimated cost incurred in executing that operation.
A number in the form of a percentage is displayed below Here, it is represented as 0% because the data is just
each icon. This number represents the relative cost to the passing to the SELECT operator. Therefore, there is
query for that operator. This cost represents the estimated approximately no cost associated with this operator.
execution time for that operation. The graphical execution Though, a 0% cost still amounts to a small cost associated
plan is read from right to left and top to bottom. A pop-up with the operator.
window called ToolTip is associated with each of the icons The estimated subtree cost is used by the query optimizer
and the arrow. You can access this TootTip by hovering the to determine the total cost incurred in executing the
mouse pointer over the icon. current operation as well as the operations preceding it in
If you hover the mouse over the arrow between the the query. Here, before the SELECT operation, two
SELECT and merge join operators, a ToolTip displaying clustered index scans and a join operation is performed.
data, such as estimated number of rows, row size, and data Therefore, it is the sum of the estimated operator costs of
size is displayed, as shown in the following figure. the merge join and two clustered index scan operators.
You can check the costs of each of these operators by
hovering the mouse over them. The estimated number of
rows represents the number of rows expected to be
returned in the result set.
A ToolTip Displaying Data Similarly, you can view the details of the clustered index
scan performed on the HumanResources.Employee table
by hovering the mouse on the clustered index scan icon.
The details shown in the preceding figure may differ The details of the clustered index scan are displayed, as
based on the DML operations performed on the shown in the following figure.
HumanResources.Employee and
HumanResources.EmployeePayHistory tables in the
AdventureWorks database of your SQL Server instance.
When you hover the mouse over the SELECT icon, the
SELECT page is displayed, as shown in the following
figure.
node. Nodes in the execution plan are numbered
from left to right.
The ToolTip window displays limited information. You
can view the detailed information by right-click any icon
in the graphical execution plan and selecting the Properties
option from the pop-up menu. This will display the
detailed list of information about that operation.
Sometimes, index scan is not beneficial in terms of
performance when the table contains a large number of
records and the result set contains comparatively lesser
number of records. For example, consider the following
query:
SELECT * FROM Person.contact
When you execute the preceding query, the execution plan
is generated, as shown in the following figure.

The Details of the Clustered Index Scan


In the preceding figure, the details of the clustered index The Execution Plan Showing Index Scan
scan is represented in the form of following options: In the preceding figure, a complete index scan is
 Physical Operation: Represents the operator performed as all the data from the table is required. Now,
used in the query execution. execute the following query:
 Logical Operation: Matches the physical SELECT FirstName, LastName FROM
operator included in the execution plan. Person.Contact WHERE LastName =
 Estimated I/O Cost: Specifies the estimated cost 'Russell'
of all I/O activities for the operation. This value The following figure shows the execution plan generated
should be as low as possible. by executing the preceding query.
 Estimated CPU Cost: Specifies the estimated
cost of all CPU activities for the operation.
 Estimated Number of Executions: Specifies the
estimated number of times the operator will be
executed while running the current query.
 Estimated Operator Cost: Specifies the cost
incurred in executing the operations included in
the query. The cost of the operation is displayed The Execution Plan Showing Missing Index Details
as a percentage of the total cost of the query
In the preceding figure, the complete index scan is
inside the parentheses. Since there is only one
performed. However, the execution plan informs you that
operation involved in the execution of the query,
there is a missing index that can enhance the performance
the cost of the operation is displayed as 100%.
of the query. Right-click on the query execution plan, and
 Estimated Subtree Cost: Represents the cost
then select the Missing Index Details options. A new query
incurred in executing the specified operation and
window opens containing the script to create a
all the operations preceding it.
nonclustered index on the LastName column of the Person
 Estimated Number of Rows: Represents the
table. Execute that script to create the missing
number of rows produced by the operator
nonclustered index by the name, idx_LastName, as shown
specified in the query.
in the following statement:
 Estimated Row Size: Represents the estimated
CREATE NONCLUSTERED INDEX idx_LastName
size of the row produced by the operator in bytes. ON Person.Contact (LastName)
 Ordered: Specifies whether the data on which
After creating the nonclustered index, execute the
query is executed is ordered.
preceding query again. This generates the execution plan,
 Node ID: Represents the number assigned to that
as shown in the following figure. complete scan of the index data.
The index seek operation is also beneficial for those
tables, which contain indexes with included columns. For
example, modify the idx_LastName index, as shown in the
following statement:
DROP INDEX idx_LastName ON
Person.Contact
GO
CREATE NONCLUSTERED INDEX idx_LastName
ON Person.Contact (LastName)
INCLUDE (FirstName)
GO
The Execution Plan Showing Key Lookup Now, execute the following query:
In the preceding figure, an index seek operation is SELECT FirstName, LastName FROM
performed, instead of index scan. The index seek Person.Contact WHERE LastName =
operation is faster if the query is trying to search for 'Russell'
specfic records as specified in the WHERE clause. The The execution of the preceding query generates the
execution plan is performing the index seek operation as execution plan, as shown in the following figure.
the database engine finds the nonclustered index created
on the LastName column. Therefore, instead of
performing index scan by using the clustered index, it
directly seeks the records by searching the nonclustered
index. The execution plan is also performing key lookup
operation on the clustered index. The reason for this key
look up operation is that the the nonclustered index only The Execution Plan Showing Index Seek on Included Columns
contains the LastName column. However, the SELECT in the Index
query also requires records from the FirstName column on The preceding execution plan is only performing index
which there is no index. Therefore, to retrieve the records seek operation on the nonclustered index as this index
from the FirstName column, the clustered index is used. contains all the columns required by the query.
Now, execute the following query: Text Plan
SELECT LastName FROM Person.contact
The graphical execution plan displays the execution plan
WHERE LastName = 'Russell'
in differnt tool tip windows for each icon. However, the
The following figure shows the execution plan of the
entire information regarding the execution plan is not
preceding query.
visible at once. In this situation, you need to display the
query execution plan in a textual format. It represents the
query execution plan as a hierarchical tree containing the
text of the T-SQL statement. The text execution plan
displays all the information regarding the execution plan
in the form of a single representation. To display the text
plan, you first need to activate the text execution plan by
The Execution Plan Showing Index Seek using the following command:
In the preceding figure, only the index seek operation is SET SHOWPLAN_ALL ON
performed. This is because that query needs to search for When SHOWPLAN_ALL is set to ON, the execution
the records only in the LastName column and the information is collected for all subsequent T-SQL
nonclustered index exists on this column. Therefore, statements. Howeve, these statements are not actually
instead of performing index scan, only an index seek executed. You need to set SHOWPLAN_ALL as OFF
operation is performed and the query performance is after viewing the relevant information. Otherwise, the
improved. CREATE, UPDATE, or DELETE statements will not be
The index seek operation affects those rows that satisfy executed. To turn-off the SHOWPLAN_ALL option,
the query condition. Therefore, it searches for those pages execute the following command:
that contain the required rows. This is highly beneficial in SET SHOWPLAN_ALL OFF
terms of performance, especially when the table contains a After setting the SHOWPLAN_ALL option as ON, you
large amount of data. Index seek is faster as compared to can display the text execution plan by executing the
index scan because index seek has to search a less number following SQL query:
of records as compared to index scan, which performs SELECT * FROM HumanResources.Employee
The following figure shows the text execution plan of the
preceding query.

The Text Execution Plan


The preceding figure shows the execution plan in the text
format. The first row displays the SQL statement that was
submitted to the database server. The subsequent rows
represent the operations occurring within the execution
plan. The PhysicalOp and LogicalOp columns denote the
physical and logical operations performed on the query. In
the preceding query, a clustered index scan is performed.
XML Plan
Sometimes, you need to transfer the query execution plans
to different computers where SQL Server is not installed.
If you use graphical or text execution plans, then it would
be required to execute the queries and then only the Identifying the Logical Order of
execution plan may be displayed. To accomplish this task, Operations in SELECT Statement
you need to use the XML execution plan that ensures
better portability of query execution plan across multiple In most of the programming languages, the order of
computers. Moreover, it also exempts the user from execution of the statements is predefined. The statements
installing SQL Server on the destination machines. are executed in the order in which they are written from
An XML plan displays the execution plan in an XML top to bottom. The order of execution of statements in T-
format. Compared to the graphical and text execution SQL is little different from other programming languages.
plans, the XML execution plan can be easily moved across In T-SQL, it is not necessary that the statements will be
the computers. In addition, they can be programmed by executed in the order in which you have written your
using XML technologies, such XPath and Xquery. query. The query that you write is first optimized by the
database engine. When you submit your query to the
You need to activate the XML execution plan by using the
database server, it is parsed to generate a parse tree that
following statement:
SET SHOWPLAN_XML ON represents the logical steps to execute the query. Further,
the query optimizer processes the parse tree to generate
the best possible execution order or plan for the query.
Before executing the preceding statement, ensure that Finally, the query is executed according to the execution
the Display Estimated Execution Plan and Include Actual plan and then the result is displayed.
Execution Plan buttons are not enabled on the SQL Editor A SELECT statement is constructed with one or more
toolbar. clauses, such as FROM and WHERE. These clauses are
Now, after setting the SHOWPLAN_XML option as ON, executed in different phases. Each phase executes a clause
you can display the text execution plan by executing the and generates a virtual table that is feed as an input to the
following query: next phase. The phases and their orders are:
SELECT * FROM HumanResources.Employee 1. FROM: If more than one table is listed in the
The following figure displays the result of the execution of FROM clause, a cartesian product of the first two
the preceding query. tables listed in the FROM clause is generated.
This result is stored in a virtual table, for example
VT1. If there is only one table listed in the FROM
clause, all the records are extracted from the table
and the result is stored in a virtual table.
The Output Derived by Using the Preceding Statement 2. ON: The ON condition is applied on the virtual
You can view the XML plan in the XML editor by clicking table, VT1. This generates a new virtual table,
on the link shown in the preceding figure. VT2, containing the rows which satisfies the join
To turn-off the SHOWPLAN_XML option, execute the condition.
following statement: 3. JOIN: The rows are retrieved from the virtual
SET SHOWPLAN_XML OFF table, VT2, according to the join type and stored
in a new virtual table, VT3. (7) HAVING <search condition>
4. If more than two tables are specified in the (10)ORDER BY <order by list>
FROM clause, the step 1 to 3 is repeated between To understand the logical order of operation of SELECT
the VT3 and the next table specified in the FROM statement, consider the following query:
clause. SELECT C.CustomerID, COUNT
5. WHERE: This condition is applied on VT3. The (O.SalesOrderID) AS Numorders
rows that satisfy the WHERE condition is stored FROM AdventureWorks.Sales.Customer AS
in a new virtual table, VT4. C
6. GROUP BY: The rows of the virtual table, VT4, LEFT OUTER JOIN
are arranged according to the column listed in the AdventureWorks.Sales.SalesOrderHeader
GROUP BY clause and stored in a new virtual AS O
table, VT5. ON C.CustomerID = O.CustomerID
7. WITH CUBE or WITH ROLLUP: The WHERE C.CustomerType = 'S'
ROLLUP and CUBE operators are used to apply GROUP BY C.CustomerID
multiple levels of aggregation on the result HAVING COUNT(O.SalesOrderID) < 3
retrieved in the virtual table, VT5, using the ORDER BY Numorders;
GROUP BY clause. The result is stored in a new In the preceding query, the cartesian product of the
virtual table, VT6. Customer and the SalesOrderHeader tables is generated
8. HAVING: This clause retrieves the groups that and stored in a virtual table, VT1. Further, the rows whose
match the condition. The result is stored in a new C.CustomerID is equal to the O.CustomerID is returned
virtual table, VT7. and stored in a new virtual table, VT2. Further, the rows
9. SELECT: The columns specified in the SELECT from VT2 and rows from the Customer table for which no
list in the query is retrieved from the virtual table, match was found in previous step is returned and stored in
VT7, and stored in a new virtual table, VT8. a new virtual table, VT3. The rows from VT3 whose
10. DISTINCT: The duplicate rows from the virtual CustomerType is S is returned and stored in a new virtual
table, VT8 are removed and a new virtual table, table, VT4. The rows of VT4 are arranged in group based
VT9 is generated. on the C.CustomerID column and stored in a new virtual
11. ORDER BY: The rows of the virtual table, VT9, table, VT5. Further, those groups whose number of rows
is arranged in the order specified in the ORDER of O.SalesOrderID column is less than three is returned
BY clause and a new virtual table, VT10, is and stored in a new virtual table, VT6. Further, the
generated. CustomerID column and the SalesOrderID column as
12. TOP: The first set of rows from the top of the Numorders is retrieved and stored in a new virtual table,
virtual table, VT10, is retrieved and stored in a VT7. Further, the rows from VT7 are sorted in ascending
new virtual table, VT11. The rows of this table order based on the Numorders column and stored in a new
are returned as a result to the caller. A caller may virtual table, VT8. The virtual table, VT8, is returned as a
be a client application or the outer query. result to the user.
The Impact of Logical Processing
The actual physical execution of the clauses in the Order on Alias
SELECT statement may differ from the specified order. The alias created with the SELECT statement cannot be
used with the expression which is executed before the
SELECT statement in the logical order of operation. It
Virtual tables are temporary tables used by SQL means you cannot use an alias created with the SELECT
Server while executing the query and not available to the statement with the clauses, such as WHERE or HAVING.
user. However, you can use the aliases created with the
The logical order of operation in SELECT statement can SELECT statement with the ORDER BY clause, because
be specified using the syntax of SELECT statement as: the ORDER BY clause is executed after the execution of
(8) SELECT the SELECT clause. For example, the following query will
(9) DISTINCT run without any error:
(11)<TOP specification> <select list> SELECT OrderQty, UnitPrice, OrderQty
(1) FROM <left table> AS Order_Quantity
(3) <join type> JOIN <right table> FROM Sales.SalesOrderDetail
(2) ON <join condition> ORDER BY Order_Quantity;
(4) WHERE <search condition> However, the following query will not execute
(5) GROUP BY <group by list> successfully, because the WHERE clause is executed
(6) WITH {CUBE | ROLLUP}
before the SELECT clause: Sales.SalesOrderHeader.DueDate
SELECT OrderQty, UnitPrice, OrderQty FROM Sales.SalesOrderDetail
AS Order_Quantity JOIN Sales.SalesOrderHeader ON
FROM Sales.SalesOrderDetail SalesOrderDetail.SalesOrderID =
WHERE Order_Quantity>5; Sales.SalesOrderHeader.SalesOrderID;
When you execute the preceding statement, the SQL
Server returns the following error message: SELECT SOD.SalesOrderID,
Msg 102, Level 15, State 1, Line 3 SOD.ProductID, SOD.OrderQty,
Incorrect column name SOH.OrderDate, SOH.duedate
‘Order_Quantity’. FROM Sales.SalesOrderDetail SOD
Therefore, you need to repeat the expression in the JOIN Sales.SalesOrderHeader AS SOH ON
WHERE and HAVING clause for which you have created SOD.SalesOrderID = SOH.SalesOrderID;
alias in the SELECT clause. Consider the following query: Both the preceding queries returns the same result set.
SELECT OrderQty, UnitPrice, OrderQty However, there is a big difference in writing both the
AS Order_Quantity queries. The first query uses the fully qualified name of
FROM Sales.SalesOrderDetail the tables, but the second query uses aliases. Using aliases
WHERE OrderQty > 5; with join is very convenient to create queries. In addition,
In the preceding query, the OrderQty column is written in the table alias improves the readability of queries.
the WHERE clause instead of writing the Order_Quantity
alias created in the SELECT statement. If you uses alias to refer a table in a query, it is the
In addition, the expression aliases cannot even be used by best practice to use that alias everywhere in the query instead
other expressions within the same SELECT list. For of the table name.
example, consider the following query:
SELECT OrderQty, UnitPrice as price,
price * OrderQty AS Total Controlling Execution Plan
FROM Sales.SalesOrderDetail;
The preceding query when executed generates the The query optimizer processes the parse tree to generate
following error message: the best possible execution plan for the query. Sometimes,
Msg 207, Level 16, State 1, Line 1 the query optimizer does not provide the best execution
Invalid column name 'price'. plan when the performance of a query is not optimum and
Therefore, you need to write the names of the columns in it consumes more CPU time to execute. In such situations,
the next SELECT list instead of using aliases. Consider you need to control the query execution by providing hints
the following query: to the query optimizer. These hints override any execution
SELECT OrderQty, UnitPrice as price, plan that the query optimizer might select for a query.
UnitPrice * OrderQty AS Total They instruct the database engine on how to execute the
FROM Sales.SalesOrderDetail; query. For example, you can use a hint to instruct the
database engine to use as little memory as possible, or to
The FROM Clause and Virtual Table use or not use an index in the execution of a query.
When a SELECT statement is executed, the FROM clause
SQL Server allows you to provide the following types of
is the first clause to be processed by the database engine. A
hints:
FROM clause can have multiple tables including views,
derived tables, and joined tables. When a FROM clause is  Query hints: Is used when you need to apply a
processed, a virtual table is created by the database engine. certain kind of logic to the whole query. For
This virtual table is used by the other clauses, such as example, you can instruct the database engine to
WHERE and GROUP BY clause of the SELECT discard the execution plan generated for the query
statement. The virtual table produced by the FROM clause after it executes and recompiles the execution
can be given aliases and used in the other clauses of the plan the next time the same query is executed.
SELECT statement as the table name. However, there is  Join hints: Is used to instruct the query optimizer
an exception of this concept is selfjoin. For example, to enforce a join strategy between the tables.
consider the following queries: Consider an example. The student data of Tebisco
SELECT Ltd. is stored in the Student table and the course
Sales.SalesOrderDetail.SalesOrderID, details are stored in the Course table.
Sales.SalesOrderDetail.ProductID,
Sales.SalesOrderDetail.OrderQty, CourseId CourseName
Sales.SalesOrderHeader.OrderDate, 121 Java
140 .Net continues until the end of table is reached.
Thereafter, the scanning control goes back to the
The Course Table next record in the first table and the the scanning
of the second table starts again in search of a
StudentId CourseId matching record For merge join, both the tables
1 121 must be sorted on the common column.
Following algorithm explains the working of the
2 121
merge join:
3 140 get first row R1 from table 1
4 121 get first row R2 from table 2
5 140 while not at the end of either
table
The Student Table begin
You want to view the StudentID and the name of if R1 joins with R2
the course the student is enrolled for. Therefore, begin
you need to perform an inner join on the Student return (R1, R2)
and the Course tables. You can execute the get next row R2 from table 2
following query: end
SELECT StudentId,CourseName else
FROM Course INNER JOIN Student ON get next row R1 from table 1
Course.CourseId = To perform the merge join, you can execute the
Student.CourseId following query:
Though the preceding statement is absolutely SELECT StudentId,CourseName
correct and gives you the desired output, the FROM Course INNER MERGE JOIN
query optimizer can also be instructed to adopt a Student ON Course.CourseId =
specific joining strategy to optimize the execution Student.CourseId
plan and performance. In case of merge join, the total cost of join is
You can use the following types of join hints: proportional to the sum of the number of rows in
 Loop join:The loop join compares each row of both the tables.
the table on the left side (first table) of the JOIN  Hash join: It is used for joining very large data
operator with each row of the table on the right sets, specifically, if one of the tables is small and
side (second table). If a match is found, the rows the other is very large. This is the best case for a
from both the tables are joined. After this the hash join to be used and dramatically improves
scanning of the second table continues,for the the query performance. The query optimizer uses
next matching record. Following algorithm the smaller table to build a temporary table in the
explains the working of the loop join: memory called as the hash table. Then the larger
for each row R1 in table1 table is scanned, searching for a matching record
for each row R2 in table2 in the hash table. Use of a hash table saves
if R1 joins with R2 memory space as well as makes the query
return (R1, R2) execution fast.
To perform an inner loop join you can execute the To perform the hash join, you can execute the
following query: following query:
SELECT StudentId,CourseName SELECT StudentId,CourseName
FROM Course INNER LOOP JOIN FROM Course INNER HASH JOIN
Student ON Course.CourseId = Student ON Course.CourseId =
Student.CourseId Student.CourseId
In case of loop joins, the total cost of join is
proportional to the size of the table1 multiplied Nested loop join can not be specified with
by the size of the table2. RIGHT or FULL OUTER join.
 Merge join: The merge join compares the rows
of the table on the left side of the JOIN operator
with each row of the table on the right side. If a Hash Join is based on hash function . The
match is found, the rows from both the tables are understanding of the algorithm for the hash join is
joined. The scanning of the records in the second beyond the scope of this module.
table continues for the next matching record. This  Table hints: Are used when you need to control
the locking mechanism of tables. When you [(column_name [, column_name]...)]
execute the T-SQL statements, such as SELECT, [WITH ENCRYPTION [, SCHEMABINDING]]
UPDATE, DELETE, INSERT, or MERGE, SQL AS select_statement [WITH CHECK
Server applies the appropriate lock on tables. OPTION]
However, if you want to overwrite this default where,
behavior of locking, you can use table hints. view_name specifies the name of the view.
column_name specifies the name of the column(s) to be
used in a view.
Activity 6.1: Creating Index WITH ENCRYPTION specifies that the the text of the
view will be encrypted in the syscomments view.
SCHEMABINDING binds the view to the schema of the
Creating and Managing Views underlying table or tables.
AS specifies the actions to be performed by the view.
At times, the database administrator might want to restrict
access of data to different users. They might want some select_statement specifies the SELECT statement
users to be able to access all the columns of a table that defines a view. The view may use the data contained
whereas other users to be able to access only selected in other views and tables. When the SCHEMABINDING
columns. SQL Server allows you to create views to restrict option is used, you need to specify the two-part names
user access to the data. Views also help in simplifying (schema.object) of tables, views, or user-defined functions
query execution when the query involves retrieving data that are being referenced in the view.
from multiple tables by applying joins. WITH CHECK OPTION forces the data modification
A view is a virtual table, which provides access to a subset statements to meet the criteria given in the SELECT
of columns from one or more tables. It is a query stored as statement defining the view. The data is visible through
an object in the database, which does not have its own the view after the modifications have been made
data. A view can derive its data from one or more tables, permanent.
called the base tables or underlying tables. Depending on
the volume of data, you can create a view with or without Syscomments view is a system-defined view stored in
an index. As a database developer, it is important for you the database. It contains entries for each view, rule, default,
to learn to create and manage views. CHECK constraint, DEFAULT constraint, and stored
procedure within the database. This view contains a text
column that stores the original SQL definition statements.
Creating Views
Guidelines for Creating Views
A view is a database object that is used to view data from While creating views, you should consider the following
the tables in the database. A view has a structure similar to guidelines:
a table. It does not contain any data, but derives its data  The name of a view must follow the rules for
from the underlying tables. identifiers and must not be the same as that of the
Views ensure security of data by restricting access to: table on which it is based.
 Specific rows of a table.  A view can be created only if there is a SELECT
 Specific columns of a table. permission on its base table.
 Specific rows and columns of a table.  A view cannot derive its data from temporary
 Rows fetched by using joins. tables.
 Statistical summary of data in a given table.  In a view, ORDER BY cannot be used in the
 Subsets of another view or a subset of views and SELECT statement.
tables. For example, to provide access only to the employee ID,
Apart from restricting access, views can also be used to marital status, and department ID for all the employees
create and save queries based on multiple tables. To view you can create the following code:
data from multiple tables, you can create a query that CREATE VIEW
includes various joins. If you need to frequently execute HumanResources.vwEmployeeDepData
this query, you can create a view that executes this query. AS
You can access data from this view every time you need to SELECT e.EmployeeID, MaritalStatus,
execute the query. DepartmentID
You can create a view by using the CREATE VIEW FROM HumanResources.Employee e JOIN
statement. The syntax of the CREATE VIEW statement is: HumanResources.EmployeeDepartmentHisto
CREATE VIEW view_name ry d
ON e.EmployeeID = d.EmployeeID one underlying table. You will learn about triggers in
The preceding code creates the vwEmployeeDepData Chapter 8.
view containing selected columns from the Employee and
EmployeeDepartmentHistory tables.
Restrictions at the Time of Modifying
Data Through Views
Views do not maintain a separate copy of the data, but
only display the data present in the base tables. Therefore,
you can modify the base tables by modifying the data in
the view. However, the following restrictions exist while
inserting, updating, or deleting data through views:
 You cannot modify data in a view if the
modification affects more than one underlying
table. However, you can modify data in a view if
the modification affects only one table at a time.
 You cannot change a column that is the result of a
calculation, such as a computed column or an
aggregate function.
For example, a view displaying the employee id, manager
id, and rate of the employees has been defined by using
the following statement:
CREATE VIEW vwSal AS Managing Views
SELECT i.EmployeeID, i.ManagerID, In addition to creating views, you also need to manage
j.Rate FROM HumanResources.Employee AS them. Management of a view includes altering, dropping,
i or renaming views.
JOIN HumanResources.EmployeePayHistory
AS j ON Altering Views
i.EmployeeID = j.EmployeeID If you define a view with a SELECT * statement and then
After creating the view, try to execute the following alter the structure of the underlying tables by adding
update statement: columns, the new columns do not appear in the view.
UPDATE vwSal Similarly, when you select all the columns in a CREATE
SET ManagerID = 2, Rate = 12.45 VIEW statement, the columns list is interpreted only when
WHERE EmployeeID = 1 you first create the view. To add new columns in the view,
The execution of the preceding statement generates an you must alter the view.
error. This is because the data is being modified in two You can modify a view without dropping it. This ensures
tables through a single update statement. Therefore, that permissions on the view are not lost. You can modify
instead of a single UPDATE statement, you need to a view without affecting its dependent objects.
execute two UPDATE statements for each table. To modify a view, you need to use the ALTER VIEW
The following statement would update the EmployeeID statement. The syntax of the ALTER VIEW statement is:
attribute in the Employee base table: ALTER VIEW view_name [(column_name)]
UPDATE vwSal [WITH [ENCRYPTION][SCHEMABINDING]
SET ManagerID = 2 AS select_statement
WHERE EmployeeID = 1 [WITH CHECK OPTION]
The following statement would update the Rate attribute in where,
the EmployeePayHistory table: view_name specifies the view to be altered.
UPDATE vwSal column_name specifies the name of the column(s) to be
SET Rate = 12.45 used in a view.
WHERE EmployeeID = 1 ENCRYPTION option encrypts the text of the view in the
Therefore, to modify the data in two or more underlying syscomments view.
tables through a view, you need to execute separate SCHEMABINDING option binds the view to the schema of
UPDATE statements for each table. the underlying table or tables.
AS specifies the actions to be performed by the view.
You can create an INSTEAD OF trigger on the view to select_statement specifies the SELECT statement
modify data in a view if the modification affects more than that defines a view.
WITH CHECK OPTION forces the data modification DROP VIEW view_name
statements to follow the criteria given in the SELECT where,
statement. view_name is the name of the view to be dropped.
For example, you created a view to retrieve selected data For example, you can use the following statement to
from the Employee and EmployeeDepartmentHistory remove the vwSalary view:
tables. You need to alter the view definition by including DROP VIEW vwSalary
the LoginID attribute from the Employee table. The preceding statement will drop the vwSalary view from
To modify the definition, you can write the following the database.
statement: You can drop multiple views with a single DROP VIEW
ALTER VIEW statement. The names of the views that need to be dropped
HumanResources.vwEmployeeDepData are separated by commas in the DROP VIEW statement.
AS
SELECT e.EmployeeID, LoginID,
MaritalStatus, DepartmentID Indexing Views
FROM HumanResources.Employee e JOIN
HumanResources.EmployeeDepartmentHisto Similar to tables, you can create indexes on views. By
ry d ON e.EmployeeID = d.EmployeeID default, the views created on a table are nonindexed.
The preceding statement alters the view definition by However, you can index the views when the volume of
including the LoginID attribute from the Employee table. data in the underlying tables is large and not frequently
updated. Indexing a view helps in improving the query
Renaming Views performance.
At times, you might need to change the name of a view. Another benefit of creating an indexed view is that the
You can rename a view without dropping it. This ensures optimizer starts using the view index in queries that do not
that permissions on the view are not lost. A view can be directly name the view in the FROM clause. If the query
renamed by using the sp_rename system stored procedure. contains references to columns that are also present in the
The syntax of the sp_rename procedure is: indexed view, and the query optimizer estimates that using
sp_rename old_viewname, new_viewname the indexed view offers the lowest cost access mechanism,
where, the query optimizer selects the indexed view.
old_viewname is the view that needs to be renamed. When indexing a view, you need to first create a unique
new_viewname is the new name of the view. clustered index on a view. After you have defined a unique
For example, you can use the following statement to clustered index on a view, you can create additional
rename the vwSal view: nonclustered indexes. When a view is indexed, the rows of
sp_rename vwSal, vwSalary the view are stored in the database in the same format as a
The preceding statement renames the vwSal view as table.
vwSalary. Guidelines for Creating an Indexed
While renaming views, you must ensure the following
points:
View
You should consider the following guidelines while
 The view must be in the current database.
creating an indexed view:
 The new name for the view must follow the rules
for identifiers.  A unique clustered index must be the first index
 The view can only be renamed by its owner. to be created on a view.
 The owner of the database can also rename the  The view must not reference any other views, it
view. can reference only base tables.
 All base tables referenced by the view must be in
Dropping Views the same database and have the same owner as
You need to drop a view when it is no longer required. the view.
You can drop a view from a database by using the DROP  The view must be created with the
VIEW statement. When a view is dropped, it has no effect SCHEMABINDING option. Schema binding
on the underlying table(s). Dropping a view removes its binds the view to the schema of the underlying
definition and all the permissions assigned to it. base tables.
Further, if you query any view that references a dropped  The view must not contain the COUNT (*), MIN,
table, you receive an error message. Dropping a table that MAX, TOP, UNION, and DISTINCT keywords.
references a view does not drop the view automatically. In addition, you cannot create an index on a view
You have to use the DROP VIEW statement explicitly. that contains self join or subquery.
The syntax of the DROP VIEW statement is:  The view must not contain FULLTEXT
predicates, such as CONTAINS or FREETEXT. several servers to optimize query performance.
Creating an Indexed View by Using the Distribution of data over several servers requires
partitioning of the tables. You can distribute the data of a
CREATE INDEX Statement table over several servers. In this way, a table is divided
You can create indexes on views by using the CREATE into smaller tables containing only a few rows. The data is
INDEX statement. For example, you can use the following partitioned between these smaller tables based on a range
statement for creating a unique clustered index on the of data values in one of the columns. To retrieve data from
vwEmployeeDepData view: such a table, you need to connect with all the servers
CREATE UNIQUE CLUSTERED INDEX where the data is distributed. SQL Server allows you to
idx_vwEmployeeDepData perform this task by using distributed partitioned views.
ON HumanResources.vwEmployeeDepData
SQL Server provides the distributed partitioned view to
(EmployeeID, DepartmentID)
retrieve data distributed across different servers. Before
The execution of the preceding statement generates an
you implement a partitioned view, you must first partition
error. This is because the vwEmployeeDepData view was
a table based on a range of key values. For example, the
not bound to the schema at the time of creation. Therefore,
Sales.SalesOrderHeader table contains the details of sales
before executing the preceding statement, you need to
orders. This table contains huge volume of data.
bind the vwEmployeeDepData view to the schema by
Therefore, you decided to partition the
using the following statement:
Sales.SalesOrderHeader table on the basis of
ALTER VIEW
SalesOrderID. The records containing
HumanResources.vwEmployeeDepData WITH
SalesOrderID<50000 are stored in a table named
SCHEMABINDING
SalesOrderHeader1 on server01 and the records containing
AS
SalesOrderID>=50000 are stored in a table named
SELECT e.EmployeeID, MaritalStatus,
SalesOrderHeader2 on server02.
DepartmentID
FROM HumanResources.Employee e JOIN Execute the following statement on server01 to create the
HumanResources.EmployeeDepartmentHisto Sales.SalesOrderHeader1 table:
ry d SELECT * INTO Sales.SalesOrderHeader1
ON e.EmployeeID = d.EmployeeID FROM Sales.SalesOrderHeader where
SalesOrderID < 50000
The preceding statement alters the existing view,
vwEmployeeDepData, and binds it with the schema of the Execute the following statement on server02 to create the
underlying tables. You can then create a unique clustered Sales.SalesOrderHeader2 table:
index on the view. SELECT * INTO Sales.SalesOrderHeader2
FROM Sales.SalesOrderHeader where
SalesOrderID >= 50000
Now, after partitioning the SalesOrderHeader table, you
need to retrieve the data after combining the records in the
SalesOrderHeader1 and SalesOrderHeader2 tables located
on different servers.
Since, the partitioned tables are created on isolated
servers, thay are not able to exchange or combine data
from each other. To accomplish this task, you need to
perform the following tasks:
1. Create linked servers.
2. Create the view.
Creating Linked Servers
You need to accesss data distributed across various servers
by creating linked servers. A linked server enables you to
connect to another instance of SQL Server and access its
data. For example, if you need to access data stored in
server01 from server02, you need to create a linked server
on server02 for server01. Similarly, if you need to access
Creating Distributed Partitioned Views data stored in server02 from server01, you need to create a
linked server on server01 for server02.
Over time, the data in databases becomes huge. This leads Therefore, to access the SalesOrderHeader1 and
to performance problems while retrieving data from the SalesOrderHeader2 tables, you need to create a linked
database. Therefore, you can distribute your data over
server on server01 for server02 and vice-versa. You can SELECT * FROM Sales. SalesOrderHeader1
create a linked server by using the sp_addlinkedserver UNION ALL
system stored procedure. SELECT * FROM
The syntax of the sp_addlinkedserver system stored server2.AdventureWorks.Sales.SalesOrde
procedure is: rHeader2
sp_addlinkedserver [ @server= ] Similarly, execute the following code to create a
'server' [ , [ @srvproduct= ] distributed partitioned view on server02:
'product_name' ] USE AdventureWorks
[ , [ @provider= ] 'provider_name' ] GO
[ , [ @datasrc= ] 'data_source' ] CREATE VIEW DistPart_View
where, AS
[ @server= ] 'server' is the name of the linked SELECT * FROM Sales. SalesOrderHeader2
server. UNION ALL
[ @srvproduct= ] 'product_name' is the SELECT * FROM
server1.AdventureWorks.Sales.SalesOrde
product name of the OLE DB data source to add as a
rHeader1
linked server. For SQL Server, its value isSQLServer
OLEDB Provider. Now, execute the following query from either of the
servers to retrieve the data from both the tables,
[ @provider= ] 'provider_name' is a unique
SalesOrderHeader1 and SalesOrderHeader2:
programmatic identifier of the OLE DB provider that
SELECT * FROM DistPart_View
corresponds to this data source. For SQL Server, its value
The preceding query will display all the records from both
is SQLOLEDB.
the tables, SalesOrderHeader1 and SalesOrderHeader2.
[ @datasrc= ] 'data_source' is the name of the
server from which the data needs to be accessed.
For example, execute the following statement on server02 Understanding Catalog Views
to create a linked server named server1 for accessing the
data of server01: The system table stores information about SQL Server
USE master configuration, objects, databases, and constraints. The
GO access to these system tables is restricted due to security
EXEC sp_addlinkedserver reasons. Sometimes, you need the information stored in
@server = 'server1', these system tables to manage the database objects. For
@srvproduct = 'SQLServer OLEDB example, you need to view the database objects that have
Provider', been modified during the last three days. For this, you
@provider = 'SQLOLEDB', need to access the system tables to retrieve the required
@datasrc = 'server01 information. However, you might not have permissions to
Similarly, execute the following code on server01 to create access the system tables. Therefore, SQL Server provides
a linked server named server2 for accessing the data of you with the catalog views to view the data stored in the
server02: system tables.
USE master The catalog views represent the information stored in the
GO system tables. For example, you can use the sys.objects
EXEC sp_addlinkedserver catalog view to view the database objects that have been
@server = 'server2', modified during the last three days, as shown in the
@srvproduct = 'SQLServer OLEDB following query:
Provider', SELECT * FROM sys.objects
@provider = 'SQLOLEDB', WHERE modify_date > GETDATE() - 3
@datasrc = 'server02' ORDER BY modify_date;
Creating the View The following figure displays the output of the preceding
Now,you need to create the distributed partioned views to query.
retrieve data from the tables across different servers. To
accomplish this task, execute the following code to create
a distributed partitioned view on server01:
USE AdventureWorks
GO
CREATE VIEW DistPart_View
AS
The Output Derived by Using the sys.objects Catalog View full-text search feature helps you to search for complex
strings in the database.
In SQL Server, the full-text search is enabled by default.
The data in the preceding figure may differ depending
upon the operations performed in your database. As a database developer, you should know how to
configure the full-text search and how to search data by
The sys.objects catalog view stores information about all using full-text search.
the objects, such as tables, views, indexes, stored
procedures, and triggers, in the database. For example, you
can display all the user tables contained in the master Configuring Full-Text Search
database by executing the following query:
SELECT * FROM sys.objects The full-text query feature in SQL Server enables users to
WHERE type_desc = 'USER_TABLE' search for a wide range of text in the SQL tables. Consider
The following figure displays the output of the preceding an example. The sales management team of
query. AdventureWorks, Inc. makes frequent searches on the
ProductDescription table to develop marketing strategies.
The search is based on the data stored in the Description
column of the table.
A bike racing competition is scheduled to begin in Texas.
The sales manager of AdventureWorks wants to see the
details of all the bikes that are related to racing, so that a
The Output Derived by Using the sys.objects Catalog View to marketing strategy can be designed to increase the sale of
Display the User Tables these bikes. Specifically, he wants a list of all the bikes
Similarly, you can display all the system tables in the that have the keyword 'race winners' in the description.
master database by executing the following query: As the data is large, the search query takes a long time to
SELECT * FROM sys.objects retrieve data from the table. In this scenario, you can apply
WHERE type_desc = 'SYSTEM_TABLE' a full-text index on the Description column of the
The following figure displays the output of the preceding ProductDescription table to improve the speed of
query. searching.
To retrieve the required details by using full-text search,
you need to configure full-text search on the database. For
this, you need to perform the following tasks:
1. Create a full-text catalog.
2. Create a unique index.
3. Create a full-text index.
4. Populate the full-text index.

You need to be a member of the sysadmin role to


The Output Derived by Using the sys.objects Catalog View to create a full-text catalog and full-text index.
Display the System Tables
To display all the views in the database, you need to Creating a Full-Text Catalog
execute the following query: A full-text catalog serves as a container to store full-text
SELECT * FROM sys.views indexes. After enabling the full-text search, you need to
create a full-text catalog. A full-text catalog is a container
that contains full-text indexes. A full-text catalog may
Activity 6.2: Creating Views have multiple full-text indexes. You can create a full-text
catalog by using the following statement:
CREATE FULLTEXT CATALOG Cat1 AS
DEFAULT
Implementing a Full-Text Search
Creating a Unique Index
While querying data, you can use the LIKE operator to After creating the full-text catalog, you need to identify a
search for a text value in a column. However, at times, you unique index on the table. This unique index will be
might need to perform a complex search on the data. For mapped to the values in the full-text index. You can use an
example, you need to search for synonyms or antonyms of existing unique index defined on the table or create a new
a particular word. SQL Server allows you to improve the one. For example, you can create a unique index on the
data search by configuring the full-text search feature. The Production.ProductDescription table, as shown in the
following statement:  AUTO: Specifies that the tracked changes will be
CREATE UNIQUE INDEX Ix_Desc ON propagated automatically as data is modified in
Production.ProductDescription the base table.
(ProductDescriptionID)  OFF [ , NO POPULATION]: Specifies that
Creating a Full-Text Index SQL Server does not keep a list of changes to the
After you have created the full-text catalog and a unique indexed data.
index, you can create a full-text index on the table. A full- STOPLIST associates a full-text stoplist with the index. It
text index stores information about significant words and can contain the following values:
their location within a given column. You can use this  OFF: Specifies that no stoplist be associated with
information to compute full-text queries that search for the full-text index.
rows with particular words or combinations of words.  SYSTEM: Specifies that the default full-text
Full-text indexes can be created on the base tables but not system stoplist should be used for this full-text
on the views or the system tables. index.
There are certain words that are used often and may hinder  stoplist_name: Specifies the user-defined
a query. These words are called stopwords and are stoplist should be used for this full-text index.
excluded from the search string. A database object is used Based on the preceding scenario, you can create a full-text
to manage these stopwords. This object is known as index on the Description column, as shown in the
stoplist. A stoplist is a list of stopwords. Some of the following statement:
stopwords are a, an, the, and are.The stoplist, when CREATE FULLTEXT INDEX ON
associated with a full-text index, is applied to full-text Production.ProductDescription
queries on that index You can use either the system- (Description) KEY INDEX Ix_Desc
defined stoplist or create your own. The preceding statement will create a full-text index on
For example, if your search string is 'Who is the governor the ProductionDescription table. This index is based on
of California', a full-text search will not look for words, the Ix_Desc index created earlier on the Description
such as 'is' and 'the'. column of the table. If you do not define the stoplist while
You can create a full-text index by using the CREATE creating the full-text index, the system-defined full-text
FULLTEXT INDEX statement. The syntax of using the stoplist is associated with the index.
CREATE FULLTEXT INDEX statement is:
CREATE FULLTEXT INDEX ON Table_name
You can also create a full-text index in the Object
( Column_name ) Explorer window by right-click the table on which you need
KEY INDEX index_name to create the full-text index, and select Full-Text
[ON fulltext_catalog_name] index→Define Full-Text Index.
[WITH [CHANGE_TRACKING = { MANUAL |
AUTO | OFF [, NO POPULATION ] Populating the Full-Text Index
[STOPLIST = { OFF | SYSTEM | After creating the full-text index, you need to populate it
stoplist_name }] ] with the data in the columns enabled for full-text support.
where, SQL Server full-text search engine populates the full-text
Table_name is the name of the table on which the index through a process called population. Population
FULLTEXT index is created. involves filling the index with words and their location in
Column_name is the name of the column included in the the data page. When a full-text index is created, it is
full-text index. Only columns of type char, varchar, nchar, populated by default. In addition, SQL Server
nvarchar, text, ntext, image, xml, varbinary, and varbinary automatically updates the full-text index as the data is
(max) can be indexed for full-text search. modified in the associated tables.
KEY INDEX index_name is the name of the unique However, SQL Server does not keep a list of changes
made to the indexed data when the
key index on the table.
CHANGE_TRACKING option is OFF. This option is
fulltext_catalog_name specifies the full-text
specified while creating the full-text index by using the
catalog used for the full-text index. It is optional. If it is CREATE FULLTEXT INDEX statement.
not specified, a default catalog is used. If there is no
If you do not want the full-text index to be populated
default catalog, SQL Server returns an error.
when it is created by using the CREATE FULLTEXT
CHANGE_TRACKING specifies whether changes made to INDEX statement, then you must specify NO
table columns are covered by the full-text index. It can POPULATION along with the CHANGE TRACKING
contain the following values: OFF option. To populate the index, you need to execute
 MANUAL: Specifies that the tracked changes must the ALTER FULLTEXT INDEX command along with the
be propagated. START FULL, INCREMENTAL, or UPDATE
POPULATION clause.
For example, to create an empty full-text index on the
ProductDescription table, you can execute the following Searching Data by Using a Full-Text
statement: Search
CREATE FULLTEXT INDEX ON
Production.ProductDescription After the full-text index has been created on a table, you
(Description) can query the table by using the full-text predicates. The
KEY INDEX full-text predicates are used to specify how the search
PK_ProductDescription_ProductDescripti string should be searched in the table. The following
onID predicates can be used while performing the full-text
WITH CHANGE_TRACKING OFF, NO search:
POPULATION  FREETEXT: When the search criteria are given,
To populate the index, you need to execute the following FREETEXT searches for any variation of a word
statement: or a group of words given in the search column.
ALTER FULLTEXT INDEX ON FREETEXT is used for the prefix searches.
Production.ProductDescription START Considering the previous scenario of the bike
FULL POPULATION racing competition, you can use the FREETEXT
The preceding statement will populate the full-text index predicate to obtain the desired output, as shown in
created on the ProductDescription table. the following query:
Similar to regular SQL indexes, full-text indexes can also SELECT Description FROM
be updated automatically as the data is modified in the Production.ProductDescription
associated tables. This repopulation can be time- WHERE FREETEXT (Description,
consuming and adversely affect the usage of resources of 'race winners')
the database server during periods of high database  FREETEXTTABLE:It searches the character
activity. Therefore, it is better to schedule repopulation of type columns and returns a table of rows that
full-text indexes during periods of low database activity. contain the words nearer to searched data in
You can specify the following types of full-text index meaning. However, it does not return the exact
population methods to repopulate the index: searched word. It expands the searched terms to
 Full population include plurals, gender, and verb forms. For
 Change tracking-based population example, while searching the word 'fog', the
 Incremental timestamp-based population search is expanded to include fog, fogging,
fogged, and so on. In addition, it returns the
Full Population ranking value and full-text key for each row.
You can use this method when you need to populate the
It is referenced in the FROM clause of the
full-text catalog or the full-text index for the first time.
SELECT statement similar to the regular table. It
After that, you can the maintain the indexes by using
returns a table that contains a column named
change tracking or incremental populations.
KEY. This column contains full-text key values.
During a full population of a full-text catalog, index Each full-text indexed table has a KEY column
entries are built for all the rows in all the tables covered by
that contains unique values. The values returned
the catalog. If a full population is requested for a table,
in the KEY column are the full-text key values
index entries are built for all the rows in that table.
that match the selection criteria specified in the
Change Tracking-Based Population search condition.
SQL Server maintains a record of the rows that have been The returned table also contains a column named
modified in a table set up for full-text indexing. These RANK. This column contains values from 0
changes are propagated to the full-text index. through 1000 for each row indicating how well a
Incremental Timestamp-Based row matches the searched condition. You can use
Population the ORDER BY clause to return the highest-
ranking rows as the first rows in the result set.
The incremental population method updates the full-text
The syntax of using the FREETEXTTABLE
index with the data that has been changed since the last
predicate is:
time the index was refreshed. For an incremental
FREETEXTTABLE (table ,
population refresh to work, the indexed table must have a
{ column_name | (column_list) |
column of the timestamp data type. If a table does not
* } ,'search_string')
have a column of the timestamp data type, then only a full
population refresh can be done. where,
table is the name of the table to be used for
full-text querying. '"Advanced" AND "Seat"')
column_name is the name of one or more full- In the preceding query, the AND logical operator
text indexed columns of the table specified in the is used to specify the CONTAINS predicate
FROM clause. should search for those descriptions which
column_list indicates that you can specify contain both the words, Advanced and Seat.
several columns, separated by a comma.  CONTAINSTABLE: It returns the search result
search_string is the text to be searched in in the form of a table. The resulting table consists
the column. of two columns, a key column named KEY and a
For example, you can use the following query to rank column named RANK. The actual rows
search the term 'Chromony steel' in the returned by these functions are joined with the
Production.ProductDescription table: source table. The CONTAINSTABLE predicate is
SELECT referenced in the FROM clause of the SELECT
f.RANK,ProductDescriptionID,Descr statement. Its syntax is similar to the
iption FREETEXTABLE predicate. For example, you
From can use the following query to return the
Production.ProductDescription d matching word for 'Entry' in the
INNER JOIN FREETEXTTABLE Production.ProductDescription table:
(Production.ProductDescription, SELECT
Description,'Chromony steel')f f.RANK,ProductDescriptionID,Descr
ON d.ProductDescriptionID = f. iption
[KEY] From
ORDER BY f.RANK DESC Production.ProductDescription d
INNER JOIN CONTAINSTABLE
In the preceding query, f.[KEY] represents the
(Production.ProductDescription,
full-text key values in the table returned by
Description,'Entry ')f
FULLTEXTTABLE. This key is matched with
ON d.ProductDescriptionID = f.
the key of the primary table to get the desired
[KEY]
matching data.
ORDER BY f.RANK DESC
 CONTAINS: This predicate is used in queries
when you want to search for a specific phrase or
for the exact match. It also searches for the
proximity of words within a text. For example,
you can use the following query to search for the
word 'Ride' near the word 'Bike' in the
ProductDescription table:
SELECT Description FROM
Production.ProductDescription
WHERE CONTAINS (Description,
'ride NEAR bike')
If you want to search for those products who
contain the different forms of the word, ride, then
you can use the following query:
SELECT Description FROM
Production.ProductDescription
WHERE CONTAINS (Description,
'FORMSOF (INFLECTIONAL, ride)')
In the preceding query, INFLECTIONAL
keyword is used to search for different tenses of
word, ride.
You can also use logical operators to specify
different search conditions. For example, consider
the following query:
SELECT Description FROM
Production.ProductDescription
WHERE CONTAINS (Description,
 XML plan
 The graphical execution plan provides the
execution details of a query in the form of a tree
structure.
 The text execution plan displays all the
information regarding the execution plan in the
form of a single representation.
 An XML plan displays the execution plan in an
XML format.
 Hints instruct the database engine on how to
execute the query.
 SQL Server allows you to provide the following
types of hints:
 Query hints
 Join hints
- Loop join
- Merge join
- Hash join
Activity 6.3: Implementing a  Table hints
 A viewis a virtual table, which derives its data
Full-Text Search from one or more tables known as the base or
underlying tables.
 Views serve as security mechanisms, thereby
Summary protecting data in the base tables.
 SQL Server allows data to be modified only in
In this chapter, you learned that: one of the underlying tables when using views,
 Indexes are created to enhance the performance even if the view is derived from multiple
of queries. underlying tables.
 There are two types of indexes, clustered and  SQL Server provides the distributed partitioned
nonclustered. view to retrieve data across different servers.
 Indexes are created by using the CREATE  SQL Server provides catalog views that represent
INDEX statement. the information stored in the system tables.
 Clustered indexes should be built on an attribute  SQL Server enables users to search for a wide
whose values are unique and do not change often. range of text in the SQL tables through the full-
Data is physically sorted in a clustered index. text query feature.
 In a nonclustered index, the physical order of  A full-text catalog can be created by using the
rows is not the same as that of the index order. CREATE FULLTEXT CATALOG statement.
 A nonclustered index is the default index that is  A full-text index can be created by using the
created with the CREATE INDEX command. CREATE FULLTEXT INDEX statement.
 An XML index is built on columns with the XML  The types of full-text population methods are full
data type. population, change tracking-based population,
 Indexes can also be partitioned based on the value and incremental timestamp-based population.
ranges.  Full-text predicates that can be used to perform
 The common index maintenance tasks include full-text search are CONTAINS,
disabling, enabling, renaming, and dropping an CONTAINSTABLE, FREETEXT, and
index. FREETEXTTABLE.
 SQL Server provides the execution plan to view  A FREETEXT predicate searches for the word or
the details of execution of a SQL query. the words given in the search column.
 The execution plan of a query enables you to  The CONTAINS predicate searches for a specific
identify how the SQL Server query optimizer phrase or for the exact match.
executes that query.
 SQL Server provides the following types of
formats to view the execution plan: Reference Reading
 Graphical plan
 Text plan Creating and Managing Indexes
Reference Reading: Books Reference Reading: URLs
Beginning SQL Server 2012 http://
for Developers by Robin rusanu.com/2012/05/29/
Dewson inside-the-sql-server-2012-
columnstore-indexes/

Creating and Managing Views

Reference Reading: Books Reference Reading: URLs


Beginning Microsoft SQL http://msdn.microsoft.com/
Server 2012 Programming en-us/library/
by Paul Atkinson and Robert ms187956.aspx
Vieira

Implementing a Full-Text Search

Reference Reading: Books Reference Reading: URLs


Professional Microsoft SQL http://msdn.microsoft.com/
Server 2012 Administration en-us/library/
by Adam Jorgensen, Steven ms142571.aspx
Wort, and Ross LoForte
Abatch is a group of SQL statements submitted together to
SQL Server for execution. While executing batches, SQL
Server compiles the statements of a batch into a single
Chapter 7 executable unit called an execution plan. This helps in
saving execution time.
Implementing Stored Procedures and For example, you have to execute 10 statements and you
are executing them one by one by sending 10 requests.
Functions This process takes time if your queries are in a queue. All
As a database developer, you might need to execute a set the statements might not get executed together. Instead, if
of SQL statements together. SQL Server allows you to you execute all the 10 statements together in a batch, then
create batches with multiple statements that can be the execution process becomes faster as all the statements
executed together. These batches can also contain are sent to the server together.
programming constructs that include conditional logic to To create a batch, you can write multiple SQL statements
examine conditions before executing the statements. followed by the keyword GO at the end. The syntax of
At times, it might be required to execute a batch creating a batch is:
repeatedly. In such a case, a batch can be saved as <T-SQL Statement1>
database objects called stored procedures or functions. <T-SQL Statement2>
These database objects contain a precompiled batch that <T-SQL Statement3>
can be executed many times without recompilation. …
This chapter explains how to create batches to execute GO
multiple SQL statements. Further, it explains how to GO is a command that specifies the end of the batch and
implement stored procedures and functions in SQL Server. sends the SQL statements for execution.
For example, if you want to store the details of new
Objectives employees in the AdventureWorks database, you can write
multiple INSERT statements in a batch, as shown in the
In this chapter, you will learn to: following statements:
 Implement batches INSERT INTO [AdventureWorks].[Person].
 Implement stored procedures [Contact]
 Implement functions VALUES (0, null, 'Robert', 'J',
'Langdon', NULL ,'rbl@adventure-
works.com', 0, '1 (11) 500
Implementing Batches 555-0172' ,'9E685955-ACD0-4218-
AD7F-60DDF224C452', '2a31OEw=', NULL
As a database developer, you might need to execute more
, newid(), getdate())
than one SQL statement to perform a task. For example,
when a new employee joins AdventureWorks, Inc., you
INSERT INTO [AdventureWorks].
need to insert the employee details in the database. The
[HumanResources].[Employee]
details of the employees are stored in more than one table. VALUES ('AS01AS25R2E365W', 19978,
Therefore, you need to execute multiple insert statements 'robertl', 16, 'Tool Designer',
to store the details in each table. In such a case, you can '1972-05-15', 'S', 'M', '1996-07-31',
send all the SQL statements together to SQL Server to be 0, 16, 20, 1, newid(), getdate())
executed as a unit. This helps in reducing the network GO
traffic. When a batch is submitted to SQL Server, it is compiled to
At times, you might also need to check conditions before create an execution plan. If any compilation error occurs,
executing the SQL statements. For example, in a such as a syntax error, the execution plan is not created.
manufacturing unit, the InventoryIssue table stores the Therefore, none of the statements in the batch is executed.
details of an item issued for the manufacturing process. However, if a run-time error occurs after the execution
When you insert a record in this table, you need to check plan is created, the execution of the batch stops. In such a
that the quantity on hand is more than or equal to the case, the statements executed before the statement that
quantity issued. In such a case, you can create conditional encountered the run-time error are not affected.
constructs that check for a condition before executing a
statement. Using Variables
While creating batches, you might need to store some
values temporarily during the execution time. For
Creating Batches example, you might need to store some intermediate
values while performing calculations. To store the
intermediate values, you can declare variables and assign and use them in the same batch.
values to them. You can declare a variable by using the  You cannot define and use the CHECK constraint
DECLARE statement. A variable name is always preceded in the same batch.
by the "@" symbol. The syntax of the DECLARE  You cannot drop objects and recreate them in the
statement is: same batch.
DECLARE @variable_name data_type  You cannot alter a table by adding a column and
Variables that are declared in a batch and can be used in then referring to the new column in the batch
any statement inside the batch are called local variables. created earlier.
The following statements declare a variable, @Rate, and
assigns the maximum value of the Rate column from the
EmployeePayHistory table to the variable:
DECLARE @Rate int
SELECT @Rate = max(Rate)
FROM HumanResources.EmployeePayHistory
GO
In the preceding statements, the max aggregate function is
used to retrieve the maximum pay rate from the
EmployeePayHistory table.
Displaying User-Defined Messages
At times, you need to display values of variables or user-
defined messages when the batch is executed. For this,
you can use the PRINT statement.
The following statements display the value of the @Rate
variable by using the PRINT statement:
DECLARE @Rate int
SELECT @Rate = max(Rate)
FROM HumanResources.EmployeePayHistory
PRINT @Rate Using Constructs
GO
SQL Server allows you to use programming constructs in
You can also use comment entries in batches to write a batches for conditional execution of statements. For
description of the code. This will help understand the example, you need to retrieve data based on a condition. If
purpose of the code. A comment entry can be written in the condition is not satisfied, a message should be
the following ways: displayed.
 Multiple line comment entries enclosed within /* SQL Server allows you to use the following constructs to
and */ control the flow of statements:
 Single line comment entry starting with -- (double
 IF…ELSE statement
hyphens)
 CASE statement
Guidelines to Create Batches  WHILE statement
While creating batches, you need to consider the following Using the IF0ELSE Statement
guidelines:
You can use the IF…ELSE statement for conditional
 You cannot combine statements such as CREATE execution of SQL statements. A particular action is
DEFAULT, CREATE FUNCTION, CREATE performed when the given condition evaluates to TRUE,
PROCEDURE, CREATE RULE, CREATE and another action is performed when the given condition
TRIGGER, and CREATE VIEW with other evaluates to FALSE.
statements while creating a batch. Any statement
The syntax of the IF…ELSE statement is:
that follows the create statement is interpreted as
IF boolean_expression
part of the definition. {sql_statement | statement_block}
 You can use the EXECUTE statement in a batch ELSE
when it is not the first statement of the batch, {sql_statement | statement_block}]
otherwise the EXECUTE statement works
where,
implicitly.
boolean_expression specifies the condition that
In addition, you need to consider the following
evaluates to either TRUE or FALSE.
restrictions:
sql_statement specifies a T-SQL statement.
 You cannot bind rules and defaults to columns
statement_block is a collection of T-SQL statement is:
statements. You need to use the BEGIN and END CASE input_expression
keywords to define multiple T-SQL statements. WHEN when_expression THEN
For example, you can retrieve the pay rate of an employee result_expression
from the EmployeePayHistory table to a variable, @Rate. [[WHEN when_expression THEN
The value of the @Rate variable is compared with the result_expression] [...]]
value 15 by using the < (less than) comparison operator. [ELSE else_result_expression]
Based on the condition, different messages are displayed, END
as shown in the following statements: where,
DECLARE @Rate money input_expression specifies the input expression that
SELECT @Rate = Rate FROM is evaluated. input_expression is any valid expression.
HumanResources.EmployeePayHistory when_expression is the expression that is compared
WHERE EmployeeID = 23 with input_expression.
IF @Rate < 15 result_expression is the expression returned when
PRINT 'Review of the rate is required' the comparison of input_expression with when_expression
ELSE evaluates to TRUE. This can be a constant, a column
BEGIN name, a function, a query, or any combination of
PRINT 'Review of the rate is not arithmetic, bit-wise, and string operators.
required' else_result_expression is the expression
PRINT 'Rate =' returned if no comparison operation evaluates to TRUE. If
PRINT @Rate
this argument is omitted and no comparison operation
END
evaluates to TRUE, the result will be NULL.
GO
In a simple CASE construct, a variable or an expression is
In the preceding statements, the IF statement checks
compared with the expression in each WHEN clause. If
whether the @Rate variable is storing a value less than 15.
any of these expressions evaluate to TRUE, then the
If the result is true, the PRINT statement displays "Review
expression specified with the THEN clause is executed. If
of the rate is required", else it displays "Review of the rate
the expression does not evaluate to TRUE, the expression
is not required". Further, the next PRINT statement
with the ELSE statement is executed.
displays the value of the rate.
Consider the following statements, where a CASE
Consider another example, where a check is performed to
construct is included in the SELECT statement to display
see the existence of the Sales department, as shown in the
the marital status as "Married" or "Single":
following statement:
SELECT EmployeeID, 'Marital Status' =
IF EXISTS (SELECT * FROM
CASE MaritalStatus
HumanResources.Department WHERE Name =
WHEN 'M' THEN 'Married'
'Sales')
WHEN 'S' THEN 'Single'
BEGIN
ELSE 'Not specified'
SELECT * FROM
END
HumanResources.Department WHERE Name =
FROM HumanResources.Employee
'Sales'
GO
END
ELSE Using the WHILE Statement
PRINT 'Department details not You can use the WHILE statement in a batch to allow a set
available' of T SQL statements to execute repeatedly as long as the
GO given condition holds true. The syntax of the WHILE
In the preceding statement, if the Sales department exists, statement is:
all the details are displayed; otherwise, a user-defined WHILE boolean_expression
message is displayed. {sql_statement | statement_block}
[BREAK]
Using the CASE Statement {sql_statement | statement_block}
You can use the CASE statement in situations where
[CONTINUE]
several conditions need to be evaluated. The CASE
where,
statement evaluates a list of conditions and returns one of
boolean_expressionis an expression that evaluates
the possible results. You can use the IF statement to do the
same task. However, you can use a CASE statement when to TRUE or FALSE.
there are more than two conditions that check a common sql_statementis any SQL statement.
variable for different values. The syntax of the CASE statement_block is a group of SQL statements.
BREAK causes the control to exit from the WHILE loop. A TRY…CATCH construct includes a TRY block
CONTINUE causes the WHILE loop to restart, skipping followed by a CATCH block. A TRY block is a group of
all the statements after the CONTINUE keyword. SQL statements enclosed in a batch, stored procedure,
SQL Server provides the BREAK and CONTINUE trigger, or function. If an error occurs in any statement of
statements to control the statements within the WHILE the TRY block, the control is passed to another group of
loop. The BREAK statement causes an exit from the statements that are enclosed in a CATCH block.
WHILE loop. Any statements that appear after the END A CATCH block contains SQL statements that perform
keyword, which marks the end of the loop, are executed some operations when an error occurs. Therefore, an
after the BREAK statement is executed. The CONTINUE associated CATCH block must immediately follow a TRY
statement causes the WHILE loop to restart, skipping any block, as shown in the following syntax:
statements after this statement inside the loop. TRY
For example, the HR department of AdventureWorks, Inc. <SQL statements>
has decided to review the salary of all the employees. As …
per the current HR policy, the average hourly salary rate of CATCH
all the employees should be approximately $20. You need <SQL statements>
to increase the hourly salary of all the employees until the …
average hourly salary reaches near $20. In addition, you END CATCH
need to ensure that the maximum hourly salary should not If there are no errors in the code that is enclosed in a TRY
exceed $127. To accomplish this task, you can use the block, the control is passed to the statement immediately
following statement: after the associated END CATCH statement. In this case,
WHILE (SELECT AVG(Rate)+1 FROM statements enclosed in the CATCH block are not executed.
HumanResources.EmployeePayHistory) < The TRY…CATCH construct can be nested. Either a TRY
20 block or a CATCH block can contain nested TRY…
BEGIN CATCH constructs. A CATCH block can contain an
UPDATE embedded TRY…CATCH construct to handle errors
HumanResources.EmployeePayHistory encountered by the CATCH block.
SET Rate = Rate + 1 In the CATCH block, you can use the following system
FROM HumanResources.EmployeePayHistory functions to determine the information about errors:
IF (SELECT max(Rate)+1 FROM  ERROR_LINE(): Returns the line number at
HumanResources.EmployeePayHistory) which the error occurred.
>127  ERROR_MESSAGE(): Specifies the text of the
BREAK message that would be returned to the
ELSE application.
CONTINUE  ERROR_NUMBER(): Returns the error number.
END  ERROR_PROCEDURE(): Returns the name of
the stored procedure or trigger in which the error
occurred. This function returns NULL if the error
Handling Errors and Exceptions did not occur within a stored procedure or trigger.
When you execute a query, it is parsed for syntactical  ERROR_SEVERITY(): Returns the severity.
errors before execution. If the syntax is correct, it is  ERROR_STATE(): Returns the state of the error.
compiled and executed. Sometimes, due to factors, such as For example, the EmployeeID attribute of the Employee
incorrect data, an error can occur during execution even if table in the AdventureWorks database is an IDENTITY
the query is syntactically correct. The errors that occur at column and its value cannot be specified while inserting a
run time are known as exceptions. new record. However, if you specify the value for
For example, there is a primary key constraint applied on EmployeeID in the INSERT statement, an error will occur.
the EmployeeID attribute of the Employee table. When To handle such run-time errors, you can include the insert
you try to insert an employee ID that already exists in the statement in a TRY block and send the control to the
table, an error occurs while executing the INSERT CATCH block where the error information is displayed, as
statement. shown in the following statements:
Exceptions can be handled in the following ways: BEGIN TRY
 By using the TRY…CATCH construct INSERT INTO [AdventureWorks].[Person].
[Contact]
 By using the RAISERROR statement and
VALUES (0, null, 'Robert', 'J',
handling the error in the application
'Langdon', NULL ,'rbl@adventure-
Using TRY0CATCH works.com', 0, '1 (11) 500
555-0172' ,'9E685955-ACD0-4218- BEGIN TRY
AD7F-60DDF224C452', '2a31OEw=', NULL, DECLARE @Start datetime
newid(), getdate()) DECLARE @End datetime
INSERT INTO [AdventureWorks]. DECLARE @Date_diff int
[HumanResources].[Employee] SELECT @Start = '1900-01-01
VALUES ('AS01AS25R2E365W', 19979, 23:00:00.000', @End = '1900-01-02
'robertl', 16, 'Tool Designer', 06:00:00.000'
'1972-05-15', 'S', 'M', '1996-07-31', SELECT @Date_diff = datediff(hh,
0, 16, 20, 1, newid(), getdate()) @Start, @End)
END TRY IF (@Date_diff != 8)
BEGIN CATCH RAISERROR('Error Raised', 16, 1)
SELECT 'There was an error! ' + ELSE
ERROR_MESSAGE() AS ErrorMessage, BEGIN
ERROR_LINE() AS ErrorLine, UPDATE HumanResources.Shift
ERROR_NUMBER() AS ErrorNumber, SET StartTime = @Start, EndTime = @End
ERROR_PROCEDURE() AS ErrorProcedure, WHERE ShiftID = 3
ERROR_SEVERITY() AS ErrorSeverity, END
ERROR_STATE() AS ErrorState END TRY
END CATCH BEGIN CATCH
GO PRINT 'The difference between the
Using RAISERROR Start and End time should be 8
hours'
A RAISERROR statement is used to return messages to
END CATCH
the business applications that are executing the SQL
GO
statements. This statement uses the same format as a
system error or warning message generated by the In the preceding statements, if the difference between the
database engine. For example, consider an application that start time and the end time is less than eight hours, an
is executing a batch. If an error occurs while executing error is raised, and the update process is stopped.
this batch, an error message will be raised and sent to the
application. The application, in turn, will include the code
to handle the error.
You can also return user-defined error messages by using
the RAISERROR statement. The syntax of the
RAISERROR statement is:
RAISERROR('Message', Severity, State)
where,
Message is the text that you want to display.
Severity is the user-defined severity level associated
with the message. It represents how serious the error is.
Severity level can range from 0 to 25. The levels from 0
through 18 can be specified by any user. The preferable
value used by users is 10, which is for displaying
informational error messages. Severity levels from 20
through 25 are considered fatal.
State is an integer value from 0 through 255. If the
same user-defined error is raised at multiple locations,
using a unique state number for each location, it can help
find which section of the code is raising the errors.
A RAISERROR severity of 11 to 19 executed in the TRY
block causes the control to be transferred to the associated
CATCH block. For example, you have to update the Shift
table to store the details of the shift in which the
employees work. While updating the shift details, you
need to ensure that the difference between the start time
and the end time is eight hours, as shown in the following
statements:
CREATE PROCEDURE proc_name
WITH [ENCRYPTION][RECOMPILE][EXECUTE
AS]
AS
BEGIN
sql_statement1
sql_statement2
END
where,
proc_name specifies the name of the stored procedure.
ENCRYPTION is used to encrypt the original text of the
CREATE PROCEDURE statement.
RECOMPILE specifies that the stored procedure is
recompiled every time it executes.
EXECUTE AS specifies the security context under which
the stored procedure is executed. It can take any one of
the following values:
 CALLER: Specifies that the stored procedure is
Implementing Stored Procedures executed under the execution context of the user
executing it.
Batches are temporary in nature. To execute a batch more  OWNER: Specifies that the stored procedure is
than once, you need to recreate SQL statements and executed under the execution context of its
submit them to the server. This leads to an increase in the owner.
overhead, as the server needs to compile and create the  user_name: Specifies that the stored procedure
execution plan for these statements again. Therefore, if is executed under the execution context of the
you need to execute a batch multiple times, you can save it specified user.
within a stored procedure. A stored procedure is a  SELF: Specifies that the stored procedure is
precompiled object stored in the database. executed under the execution context of the user
Stored procedures can invoke the Data Definition creating or modifying it.
Language (DDL) and Data Manipulation Language The following statement creates a stored procedure to
(DML) statements and can return values. If you need to view the department names from the Department table:
assign values to the variables declared in the procedures at CREATE PROCEDURE prcDept
run time, you can pass parameters while executing them. AS
You can also execute a procedure from another procedure. BEGIN
This helps in using the functionality of the called SELECT Name FROM
procedure within the calling procedure. HumanResources.Department
An application is designed in three layers. These layers are END
the presentation, business, and data access layers. An When the CREATE PROCEDURE statement is executed,
application is well maintained if the stored procedures are the server compiles the procedure and saves it as a
used. These procedures are indeed a part of the data access database object. The procedure is then available for
layer. They are mapped to certain methods of the business various applications to execute.
layer. The application can access the required data from The process of compiling a stored procedure involves the
the database by invoking the specific methods of the following steps:
business layer. These methods, in turn, invoke the 1. The procedure is compiled and its components
statements or the procedures in the data access layer. are broken into various pieces. This process is
Therefore, the entire process is abstracted. known as parsing.
As a database developer, it is important for you to learn 2. The existence of the referred objects, such as
how to implement procedures. tables and views, are checked. This process is
known as resolving.
3. The name of the procedure is stored in the
Creating Stored Procedures sysobjects table and the code that creates the
You can create a stored procedure by using the CREATE stored procedure is stored in the syscomments
PROCEDURE statement. table.
The syntax of the CREATE PROCEDURE statement is: 4. The procedure is compiled and a blueprint for
how the query will run is created. This blueprint
is specified as an execution plan. The execution department name.
plan is saved in the procedure cache. When you execute a stored procedure, the number of rows
5. When the procedure is executed for the first time, affected by it is also returned. If the stored procedure is
the execution plan will be read, fully optimized, getting executed by a Web application, then the database
and then run. When the procedure is executed engine returns the result set along with the number of rows
again in the same session, it will be read directly affected. This creates an overhead on the network and
from the cache. This increases performance, as reduces the performance of the application. To avoid this,
there is no repeated compilation. you can turn off the message that contains the number of
rows affected by the SQL statement. You can perform this
task by using the SET NOCOUNT statement. The syntax
After creating the stored procedure, you can view the
code of the procedure by using the sp_helptext statement. of this statement is:
SET NOCOUNT { ON | OFF }
Guidelines to Create a Stored where,
Procedure ON prevents the message containing the count of the
The following points need to be considered before creating number of rows affected by the SQL statement or stored
a stored procedure: procedure from being returned.
 You cannot combine the CREATE PROCEDURE OFF allows the message containing the count of the
statement with other SQL statements in a single number of rows affected by the SQL statement or stored
batch. procedure to be returned.
 You must have the CREATE PROCEDURE For example, consider the following code snippet:
permission to create a procedure in the database ALTER PROCEDURE prcDept
and the ALTER permission on the schema, where AS
the procedure is being created. BEGIN
 You can create a stored procedure only in the SET NOCOUNT ON
current database. SELECT DepartmentID, Name FROM
After creating a stored procedure, you can execute the HumanResources.Department
procedure. You can also alter the procedure definition or END
drop it, if the existing procedure is not required. When you execute the prcDept stored procedure, the result
Executing a Stored Procedure set does not display the number of rows affected by the
A procedure can be executed by using the EXECUTE and procedure.
EXEC statement. The syntax of the EXECUTE statement Dropping a Stored Procedure
is: You can drop a stored procedure from the database by
EXEC | EXECUTE proc_name using the DROP PROCEDURE statement. The syntax of
where, the DROP PROCEDURE statement is:
proc_name is the name of the procedure DROP PROCEDURE proc_name
that you need to execute. You cannot retrieve a procedure once it is dropped.
You can execute the stored procedure, prcDept, as shown You can drop the prcDept stored procedure by using the
in the following statement: following statement:
EXEC prcDept DROP PROCEDURE prcDept
Altering a Stored Procedure
A stored procedure can be modified by using the ALTER
PROCEDURE statement. The syntax of the ALTER
PROCEDURE statement is:
ALTER PROCEDURE proc_name
You can alter the stored procedure by
using the following statement:
ALTER PROCEDURE prcDept
AS
BEGIN
SELECT DepartmentID, Name FROM
HumanResources.Department
END
In the preceding statement, the prcDept stored procedure
will be modified to display department Ids along with the
name and value of the parameter. In the previous example,
you can also pass the parameter value by using the name
of variable, as shown in the following statement:
EXECUTE prcListEmployee @title = 'Tool
Designer'
Apart from variables, you can pass a table-valued
parameter to a stored procedure. The table-valued
parameter enables you to send multiple rows of data to the
stored procedure without creating a temporary table or
many parameters. It must be declared with the
READONLY option while creating a stored procedure.
This is because you cannot modify the data in the rows of
the table-valued parameter.
For example, create a table named Branch having columns
as Branch_ID and Branch_Name by using the following
code:
CREATE TABLE Branch(
Branch_ID int Primary Key,
Creating Parameterized Stored Branch_Name Varchar (20)
)
Procedures Now, you need to insert data into the Branch table by
At times, you need to execute a procedure for different using a stored procedure. For this, you need to create a
values of a variable that are provided at run time. For this, stored procedure that accepts multiple values to be
you can create a parameterized stored procedure. inserted in the Branch table. You can perform this task
Parameters are used to pass values to the stored procedure easily by using a table-valued parameter. Execute the
during run time. These values can be passed by using following code to create a table type named NType:
standard variables. The parameter that passes the value to CREATE TYPE NType AS TABLE (Br_ID int,
the stored procedure is defined as an input parameter. A Br_Name Varchar(20))
stored procedure has the capability of using a maximum of In the preceding code, the NType table type consists of
2100 parameters. Each parameter has a name, data type, two columns, Br_ID and Br_Name. Now, you need to
direction, and a default value. create a stored procedure that takes a parameter of table
type by using the following code:
CREATE procedure Table_Proc
Direction represents whether a parameter is an input @ParamTable NType READONLY
parameter or an output parameter. By default, the direction of AS
a parameter is input. INSERT INTO Branch
The following statement creates a stored procedure (Branch_ID,Branch_Name)
displaying the employee ID, the login ID, and the title of SELECT * FROM @ParamTable
employees that have the same title provided as an input You can execute the Table_Proc stored procedure by using
during execution: the following code:
CREATE PROC prcListEmployee @title DECLARE @TableTest AS NType
char(50) INSERT INTO @TableTest (Br_ID,
AS Br_Name) VALUES(1,'Admin'), (2,'User')
BEGIN EXECUTE Table_Proc @TableTest
PRINT 'List of Employees' SELECT * FROM BRANCH
SELECT EmployeeID, LoginID, Title When the preceding statements are executed, two rows are
FROM HumanResources.Employee inserted in the Branch table, as shown in the following
WHERE Title = @title figure.
END
You can execute the stored procedure, prcListEmployee,
by using the following statement:
EXECUTE prcListEmployee 'Tool
Designer'
While executing stored procedures, you can also provide The Output Derived After Executing the Procedure
the values for the parameters by explicitly specifying the
FROM HumanResources.Department d
Returning Values from Stored JOIN
Procedures HumanResources.EmployeeDepartmentHis
tory h
Similar to providing input values to the procedures at run ON d.DepartmentID = h.DepartmentID
time, you can also return values as an output from the WHERE EmployeeID = @EmpId AND
procedures. The values can be returned to the calling h.Enddate IS NULL
application through output parameters. To specify a RETURN 0
parameter as the output parameter, you can use the END
OUTPUTkeyword. ELSE
The OUTPUT keyword has to be specified in both the RETURN 1
CREATE PROCEDURE and the EXECUTE statements. If END
the OUTPUT keyword is omitted, the procedure will be In the preceding statement, the prcGetEmployeeDetail
executed but will not return any value. procedure accepts the employee ID as an input parameter
The syntax of declaring an output parameter using the and returns the department name and shift ID as the output
OUTPUT keyword is: parameters. The procedure first checks the existence of the
CREATE PROCEDURE procedure_name given employee ID. If it exists, the procedure returns an
[ integer value 0 along with the required details.
{@parameter data_type} [OUTPUT]
]
AS Calling a Procedure from Another
sql_statement [...n] Procedure
@parameter data_type [OUTPUT] allows the stored
procedure to pass a data value to the calling procedure. If At times, you might need to use the values returned by a
the OUTPUT keyword is not used, then the parameter is procedure in another procedure. For this, you can execute
treated as an input parameter. or call one procedure from another procedure. A procedure
You can also return values from the stored procedure by that calls or executes another procedure is known as the
using the RETURN statement. The RETURN statement calling procedure, and the procedure that is called or
allows the stored procedure to return only an integer value executed by the calling procedure is termed as the called
to the calling application. The syntax of the RETURN procedure. You can also execute a procedure from another
statement is: procedure if you need to use the functionality provided by
RETURN value one into another.
where, Consider the previous example where the
value is any integer. prcGetEmployeeDetail procedure returns the employee
If a value is not specified, then the stored procedure details for a given employee ID. You can create the
returns a default value of 0 to specify success and a prcDisplayEmployeeStatus procedure, which accepts the
nonzero value to specify failure. employee ID of an employee as an input and displays the
For example, you need to display the details of an department name and shift ID where the employee is
employee whose employee ID has been provided as an working along with the manager ID and the title of the
input. For this, you need to create a procedure employee. To perform this task, you need to call the
prcGetEmployeeDetail that will accept employee ID as an prcGetEmployeeDetail procedure from the
input and return the department name and ID of the shift prcDisplayEmployeeStatus procedure, as shown in the
in which the employee works. You can create the following statement:
procedure, as shown in the following statement: CREATE PROCEDURE
CREATE PROCEDURE prcGetEmployeeDetail prcDisplayEmployeeStatus @EmpId int
@EmpId int, @DepName char(50) OUTPUT, AS
@ShiftId int OUTPUT BEGIN
AS DECLARE @DepName char(50)
BEGIN DECLARE @ShiftId int
IF EXISTS(SELECT * FROM DECLARE @ReturnValue int
HumanResources.Employee WHERE EXEC @ReturnValue =
EmployeeID = @EmpId) prcGetEmployeeDetail @EmpId,
BEGIN @DepName OUTPUT,
SELECT @DepName = d.Name, @ShiftId = @ShiftId OUTPUT
h.ShiftID IF (@ReturnValue = 0)
BEGIN sp_addsrvrolemem Is used to add a The following
PRINT 'The details of an employee ber login as a member statement adds
with ID: ' + convert(char(10), of a fixed server George to the
@EmpId) role. sysadmin fixed
PRINT 'Department Name: ' + @DepName server role:
PRINT 'Shift ID: ' + convert( char sp_addsrvrol
(1), @ShiftId) emember
SELECT ManagerID, Title FROM 'George',
HumanResources.Employee 'sysadmin'
WHERE EmployeeID = @EmpID sp_addrolemembe Is used to add a The following
END r database user, statement adds the
ELSE database role, database user
PRINT 'No records found for the given Windows login, or George to the
employee' Windows group to db_securityadmin
END a database role in role in the current
To execute the prcDisplayEmployeeStatus procedure, you the current database:
need to execute the following statement: database. sp_addroleme
EXEC prcDisplayEmployeeStatus 2 mber
'db_security
SQL Server provides a function, @@ROWCOUNT, admin',
which returns the number of rows affected by the last 'George'
statement. You can use this statement in the IF construct to sp_helpdb Is used to see the The following
check the result of the last executed statement. details of the statement displays
database. the details of the
AdventureWorks
database:
sp_helpdb
AdventureWor
ks
sp_renamedb Is used to rename The following
a database. statement renames
the ImportExport
database to
Export:
sp_renamedb
ImportExport
, Export
sp_bindrule Is used to bind a The following
rule with a column statement binds
or an alias data the ruleType rule
type. to the LeaveType
column of the
Using System Stored Procedures EmployeeLeave
table in the
System stored procedures provide functionalities to HumanResources
manage system resources. By using the system stored schema:
procedure, database administrators can manage the sp_bindrule
database server effectively. SQL Server provides a set of 'ruleType','
system-defined stored procedures used for general HumanResourc
maintenance of a particular database or the database server es.EmployeeL
as a whole. The following table lists some of the system- eave.LeaveTy
defined stored procedures in SQL Server. pe'
sp_unbindrule Is used to unbind a The following
System-defined Description Example rule from a column statement unbinds
Stored Procedure or alias data type. the rules bound to
the LeaveType EmployeeVaca
column of the tion],
EmployeeLeave [HumanResour
table in the ces.
HumanResources EmployeeLeav
schema: e]
sp_unbindrul sp_help Is used to see the The following
e details of a table, statement displays
'HumanResour built-in data types, the details of the
ces.Employee or user-defined Department table
Leave.LeaveT data types. in the
ype' HumanResources
sp_bindefault Is used to bind a The following schema:
default to a statement binds sp_help
column or an alias the default value 'HumanResour
data type. CL to the ces.Departme
LeaveType column nt'
of the sp_helpindex Is used to display The following
EmployeeLeave information about statement displays
table in the the indexes on a the details of the
HumanResources table or a view. indexes on the
schema: Department table
sp_ in the
bindefault HumanResources
'CL' schema:
'HumanResour sp_helpindex
ces.Employee 'HumanResour
Leave.LeaveT ces.Departme
ype' nt'
sp_unbindefault Is used to unbind The following sp_xml_preparedo Is used to parse The following
or remove a statement unbinds cument the XML statements parse
default from a the default bound document. This the XML document
column or an alias to the LeaveType stored procedure stored in the
data type in the column of the reads the XML @XMLDoc
current database. EmployeeLeave document and variable and
table in the parses it with the stores the output in
HumanResources MSXML parser. the @Doc
schema: variable:
sp_ DECLARE @Doc
unbindefault int
'HumanResour DECLARE
ces.Employee @XMLDoc
Leave.LeaveT nvarchar
ype' (1000)
sp_rename Is used to rename The following SET @XMLDoc
a table, index, or statement renames = N'<ROOT>
view. the <Customer
EmployeeVacation ID="JH01">
table in the </Customer>
HumanResources </ROOT>'
schema to EXEC
EmployeeLeave: sp_xml_prepa
sp_rename redocument
[HumanResour @Doc OUTPUT,
ces. @XMLDoc
sp_xml_removedo Is used to release The following configuration the global
cument the memory by statement releases settings for the configuration
removing the the memory by current server. setting of the
internal tree removing the current server to 1
representation of internal tree (enabled):
the parsed XML representation of sp_configure
document created the parsed XML CLR_ENABLED,
by using the document stored in 1
sp_xml_preparedo the @Doc sp_lock Is used to display The following
cument stored variable: information about statement displays
procedure. EXEC locks. the details of the
sp_xml_remov locks available on
edocument the current
@Doc instance of SQL
sp_fulltext_catalo Is used to create The following Server:
g and drop a full- statement creates sp_lock
text catalog. In a full-text catalog sp_recompile Is used to The following
addition, it is used named F_Cat: recompile the statement marks
to start and stop EXEC stored procedures the dEmployee
the indexing sp_fulltext_ and triggers, the trigger in the
action for a catalog next time they are HumanResources
catalog. 'F_Cat', run. schema for
'create' recompilation:
sp_helptext Is used to display The following sp_recompile
the definition for statement displays 'HumanResour
database objects, the definition of ces.dEmploye
such as a user- the dEmployee e'
defined rule, a trigger in the sp_dbremove Is used to remove The following
default HumanResources a database and all statement removes
unencrypted T- schema: files associated the Export
SQL stored EXEC with that database. database and its
procedure, a user sp_helptext associated files:
defined T-SQL 'HumanResour sp_dbremove
function, a trigger, ces.dEmploye 'Export'
a CHECK e' sp_helptrigger Is used to display The following
constraint, or a the type or types of statement displays
view. DML triggers the details of the
sp_settriggerorder Is used to change The following defined on the DML triggers on
the sequence of statement specifies specified table for the Employee
execution of the that the the current table in the
AFTER triggers. trgDeleteShift1trig database. HumanResources
ger is the first schema:
trigger to be fired sp_helptrigg
after a DELETE er
operation occurs 'HumanResour
on the table: ces.Employee
sp_settrigge '
rorder sp_addlinkedsrvlo Is used to create The following
'HumanResour gin or update a statement creates
ces.trgDelet mapping between a mapping to
eShift1', a login on the ensure that the
'FIRST', local instance of logins to the local
'DELETE' SQL Server and a server connect to
sp_configure Is used to display The following security account the
or change global statement changes on a remote server. SQLSERVER02
linked server by dynamic SQL:
using their own  Write a parameterized query.
user credentials:  Use the EXEC() function.
sp_addlinked  Use SP_EXECUTESQL.
srvlogin
'SQLSERVER02
Writing a Parameterized Query
You can pass parameters to the WHERE clause of the SQL
'
statements. Consider a scenario, where you need to find
sp_executesql Is used to execute The following out the details of the employee whose EmployeeID is
a T-SQL statement statements execute provided at runtime. For this, you can execute the
or batch. the T-SQL following statements:
statement stored in DECLARE @empid int
the @SQLString SET @empid = 3
variable: SELECT * FROM HumanResources.Employee
DECLARE WHERE
@SQLString HumanResources.Employee.EmployeeID =
nvarchar @empid
(500);
In the preceding statements, an integer type parameter,
SET
@empid, is declared and assigned the value, 3. You can
@SQLString =
change the value of this parameter to display the details of
'SELECT
different employees. The preceding statements display the
EmployeeID,
details of the employee whose ID is 3, as shown in the
NationalIDNu
following figure.
mber FROM
AdventureWor
ks.HumanReso
urces.Employ
ee WHERE The Output Derived After Executing the Statements
EmployeeID = Using the EXEC() Function
2'; The EXEC() function can be used to execute the
EXEC procedures as well as the SQL statements. This function
sp_executesq accepts the SQL statement to be executed as a parameter.
l @SQLString
Consider the following statements that show the execution
of a static SQL statement:
The System-defined Stored Procedures EXEC('SELECT EmployeeID,
NationalIDNumber,ContactID,LoginID,Man
agerID,Title FROM
Implementing Dynamic SQL HumanResources.Employee WHERE
SQL statements can be broadly classified into two HumanResources.Employee.EmployeeID =
categories, static and dynamic. Static SQL statements do 13')
not change at the time of execution and can be hard-coded The EXEC() function can also be used to execute dynamic
in the application. The complete text of static SQL SQL statements. For example, the following code shows
statements is known at the compile time. A stored the use of EXEC() to execute dynamic SQL statements:
procedure that does not expect any parameter at the time DECLARE @sqlCommand varchar(1000)
of execution is the simplest example of static SQL. At DECLARE @columnList varchar(75)
times, your query depends on certain values or parameters, DECLARE @empid varchar(10)
which are not fixed and are provided at the time of SET @columnList =
execution. Therefore, the complete text of the SQL 'EmployeeID,NationalIDNumber,ContactID
statement is not known until execution. Such statements ,LoginID,ManagerID,Title'
constitute dynamic SQL. SET @empid = '13'
For example, you write a procedure, which calculates the SET @sqlCommand = 'SELECT ' +
total amount payable, on the basis of the principle amount, @columnList +
' FROM HumanResources.Employee WHERE
loan duration, and rate of interest. The execution of this
HumanResources.Employee.EmployeeID = '
procedure depends on these values provided at runtime.
+ @empid
SQL Server provides the following ways to implement
EXEC (@sqlCommand)
The preceding statements display the details of the HumanResources.Employee.EmployeeID =
employee whose ID is 13, as shown in the following @empid'
figure. EXECUTE sp_executesql @sqlCommand,
N'@empid nvarchar(75)', @empid = @ID
The preceding statements display the details of the
employee whose ID is 13, as shown in the following
The Output Derived After Executing the EXEC() Function figure.
Using SP_EXECUTESQL
The SP_EXECUTESQL stored procedure is a better
option to execute SQL statements. Unlike the EXEC()
function, it supports parameter substitution. The use of The Output Derived by Using the SP_EXECUTESQL Statement
SP_EXECUTESQL generates an execution plan which
can be reused by SQL Server. Consider the preceding
example given for the EXEC() function, which expects Activity 7.1: Creating Stored
empid as a parameter. If we execute the above statement,
once with empid as 13 and again with empid as 14, SQL
Procedures
Server will generate two different execution plans.
However, in the case of SP_EXECUTESQL, the same
execution plan will be reused by the SQL Server query Implementing Functions
optimizer for different parameters passed at the time of
execution. Therefore, there is no overhead of compiling a Similar to stored procedures, you can also create functions
new execution plan for every new parameter passed. This, to store a set of T-SQL statements permanently. These
in turn, contributes to query performance. The following functions are also referred to as User-Defined Functions
syntax is used for SP_EXECUTESQL: (UDFs). A UDF is a database object that contains a set of
sp_executesql [ @stmt = ] statement T-SQL statements, accepts parameters, performs an action,
[ and returns the result of that action as a value. The return
{ , [ @params = ] N'@parameter_name value can be either a single scalar value or a result set.
data_type [ OUT | OUTPUT ][ ,...n ]' } UDFs have a limited scope as compared to stored
{ , [ @param1 = ] procedures. You can create functions in situations when
'value1' [ ,...n ] } you need to implement a programming logic that does not
] involve any permanent changes to the database objects
where, outside the function. For example, you cannot modify a
[ @stmt= ] statement specifies the Unicode string that database table from a function.
contains a Transact-SQL statement or batch to be UDFs are of different types, scalar functions and table-
executed. valued functions. As a database developer, you must learn
[ @params= ] N'@parameter_namedata_type [ ,... n ] to create and manage different types of UDFs.
' specifies the string that contains the definitions of all
parameters defined in @stmt.
[ @param1= ] 'value1' specifies the value of the first
Creating UDFs
parameter defined in @params. Similarly, you need to A UDF contains the following components:
specify the value of all the parameters in sequence as  Function name with optional schema/owner name
defined in @params.  Input parameter name and data type
For example, consider the following statements:  Options applicable to the input parameter
DECLARE @sqlCommand nvarchar(1000)  Return parameter data type and optional name
DECLARE @columnList varchar(75)  Options applicable to the return parameter
DECLARE @ID varchar(75)  One or more T-SQL statements
SET @columnList = 'EmployeeID To create a function, you can use the CREATE
,NationalIDNumber FUNCTION statement. The syntax of the CREATE
,ContactID FUNCTION statement is:
,LoginID' CREATE FUNCTION [ schema_name. ]
SET @ID = '13' function_name
SET @sqlCommand = 'SELECT ' + ( [ { @parameter_name [ AS ]
@columnList + [ type_schema_name. ]
' FROM HumanResources.Employee WHERE parameter_data_type
[ = default ] } pay rate and returns a single value after multiplying the
[ ,...n ] rate with the number of hours and number of days. You
] can create this function by using the following statement:
) CREATE FUNCTION
RETURNS return_data_type HumanResources.MonthlySal (@PayRate
[ WITH [SCHEMABINDING][ENCRYPION] float)
[EXECUTE AS] [,...n ] ] RETURNS float
[ AS ] AS
BEGIN BEGIN
function_body RETURN (@PayRate * 8 * 30)
RETURN expression END
END You can execute the preceding function by using the
[ ; ] following statements:
where, DECLARE @PayRate float
schema_name is the name of the schema to which the SET @PayRate =
UDF belongs. HumanResources.MonthlySal(12.25)
function_name is the name of the UDF. Function PRINT @PayRate
names must comply with the rules for identifiers and must In the preceding statements, @PayRate is a variable that
be unique within the database and to its schema. will store a value returned by the MonthlySal function.
@parameter_name is a parameter in the UDF. One or Creating Table-Valued Functions
more parameters can be declared. A table-valued function returns a table as an output, which
[ type_schema_name. ] parameter_data_type is can be derived as part of a SELECT statement. Table-
the data type of the parameter, and optionally the schema valued functions return the output as a table data type. The
to which it belongs. table data type is a special data type used to store a set of
[ = default ] is a default value for the parameter. rows. Table-valued functions are of the following types:
While executing a UDF with the default value, you must  Inline table-valued function
specify the DEFAULT keyword for the parameter having  Multistatement table-valued function
the default value. Inline Table-Valued Function
return_data_type is the return value of a scalar An inline table-valued function returns a variable of a
user-defined function. table data type from the result set of a single SELECT
function_body specifies a series of T-SQL statements. statement. An inline function does not contain a function
ENCRYPTION option is used to convert the text of the body within the BEGIN and END statements.
function body into the encrypted format. For example, the inline table-valued function,
SCHEMABINDING option is used to bind the function to fx_Department_GName, accepts a group name as a
the schema of the data objects it references. As a result, parameter and returns the details of the departments that
you cannot execute the ALTER or DROP statement to belong to the group from the Department table. You can
modify or to remove the tables, columns, views that are create the function by using the following statement:
referenced by the UDF. CREATE FUNCTION fx_Department_GName
EXECUTE AS clause is used to allow a user to grant all ( @GrName nvarchar(20) )
the necessary rights to execute the functions. The access RETURNS table
rights included in the EXECUTE AS clause are similar to AS
those specified with stored procedures. RETURN (
SELECT *
Creating Scalar Functions FROM HumanResources.Department
Scalar functions accept a single parameter and return a WHERE GroupName=@GrName
single data value of the type specified in the RETURNS )
clause. A scalar function can return any data type except GO
text, ntext, image, cursor, and timestamp. Some scalar You can use the following query to execute the
functions, such as current_timestamp, do not require any fx_Department_GName function with a specified
arguments. argument:
A function contains a series of T-SQL statements defined SELECT * FROM fx_Department_GName
in a BEGIN...END block of the function body that returns ('Manufacturing')
a single value. The preceding query will return a result set, as shown in
For example, consider a scalar function that calculates the the following figure.
monthly salary of employees. This function accepts the
END
In the preceding statement, the function returns a result set
in the form of a temporary table, @table, created within
the function. You can execute the function by using the
The Output Derived After Executing the Query following query:
Consider another example of an inline function that SELECT * FROM PayRate(45)
accepts rate as a parameter and returns all the records that
have a rate greater than the parameter value. You can Depending on the result set returned by a function, a
create this function, as shown in the following statement: function can be categorized as deterministic or
CREATE FUNCTION HumanResources.Emp_Pay nondeterministic. Deterministic functions always return the
(@Rate int) same result whenever they are called with a specific set of
RETURNS table input values. However, nondeterministic functions may return
AS different results each time they are called with a specific set
RETURN ( of input values.
SELECT e.EmployeeID, e.Title, er.Rate
FROM HumanResources.Employee AS e An example of a deterministic function is dateadd(), which
JOIN HumanResources.EmployeePayHistory returns the same result for any given set of argument values
AS er for its three parameters. getdate() is a nondeterministic
ON e.EmployeeID=er.EmployeeID WHERE function because it is always invoked without any argument,
er.Rate>@Rate but the return value changes on every execution.
)
GO
In the preceding statement, the Emp_Pay function will
return a result set that displays all the records of the
employees who have the pay rate greater that the
parameter. You can execute the preceding function by
using the following query:
SELECT * FROM HumanResources.Emp_Pay
(50)
Multistatement Table-Valued Function
A multistatement table-valued function uses multiple
statements to build the table that is returned to the calling
statement. The function body contains a BEGIN...END
block, which holds a series of T-SQL statements to build
and insert rows into a temporary table. The temporary
table is returned in the result set and is created based on
the specification mentioned in the function.
For example, the multistatement table-valued function,
PayRate, is created to return a set of records from the
EmployeePayHistory table. You can create this function
by using the following statement:
CREATE FUNCTION PayRate (@rate money)
RETURNS @table TABLE
(EmployeeID int NOT NULL,
RateChangeDate datetime NOT NULL,
Rate money NOT NULL,
PayFrequency tinyint NOT NULL,
ModifiedDate datetime NOT NULL)
AS
BEGIN
INSERT @table
SELECT *
FROM HumanResources.EmployeePayHistory
WHERE Rate > @rate
RETURN
 Navigate to a specific row of the result set.
 Retrieve a row from a particular position.
 Modify a row at a particular position.
Implementing a cursor includes the following tasks:
 Declare a cursor.
 Open the cursor.
 Fetch rows from the cursor.
 Close the cursor.
 Deallocate the cursor.
Declaring a Cursor
A cursor is declared by defining the SQL statement or the
query used to build the result set on which the cursor
operates. Additional attributes, such as the scrolling
behavior or the scope of the cursor, are also defined at the
time of declaration. The following syntax is used to
declare a cursor:
DECLARE cursor_name CURSOR [ LOCAL |
GLOBAL ]
Activity 7.2: Creating Functions [ FORWARD_ONLY | SCROLL ]
[ STATIC | KEYSET | DYNAMIC |
FAST_FORWARD ]
Implementing Cursors [ READ_ONLY | SCROLL_LOCKS |
OPTIMISTIC ]
You have been following a set-based approach to work FOR select_statement
with data in SQL Server. This approach allows working on [ FOR UPDATE [ OF column_name
multiple rows together as a single unit. Being a relational [ ,...n ] ] ]
database system, SQL Server is designed to process the [;]
sets, which are an unordered collection of rows, also where,
known as a result set. Cursor_name is the name of the cursor.
It means that multiple rows are handled together in an LOCAL specifies that the scope of the cursor is local. It
unordered manner during query execution. However, means that the cursor can be referenced only the batch,
cursors follow an iterative approach. This means that the stored procedure, or trigger in which it has been created.
database engine handles a single row at a time in a specific GLOBAL specifies that the scope of the cursor is global. It
order. means that the cursor can be referenced in any batch,
The following list helps you to understand how the set- stored procedure, or trigger executed by the current
based approach is different from an iterative approach: connection.
 In case of the set-based approach, you need to FORWARD_ONLY specifies that the cursor can be scrolled
instruct the database engine what is to be done in a forward direction only.
without specifying the how part. But in the SCROLL specifies that all the fetch options are available
iterative approach, you also need to specify how and the cursor can fetch data in all directions.
you want the engine to do a particular job. STATIC specifies that the cursor makes a temporary
 The Iterative approach involves the use of the copy of the data and all the requests to the cursor are
SELECT statement, loop management, answered from this temporary table. A static cursor can
navigation, and state-checking. Therefore, it move in both the directions forward and backward.
involves more of code writing in comparison to However, data cannot be updated or deleted by using
the set- based approach. static cursors.
 Since the iterative approach allows accessing one DYNAMIC specifies that the cursor reflects all data
row at a time, it is slower than the set-based changes made to the rows in its result set as you scroll
approach. around the cursor.
A cursor in SQL Server allows you to work with FAST_FORWARD specifies that the cursor is FORWARD
individual rows of a result set. Associating a cursor with ONLY and READ ONLY. Such cursors produce the least
the result set enables you to process the result set one row amount of overhead on SQL Server.
at a time. A cursor allows you to perform the following READ_ONLY specifies that the cursor is read only and
operations: cannot be updated.
SCROLL_LOCKS specifies that the rows will be locked negative, the rows are counted from bottom of the result
as they are read into the cursor. This is done to ensure that set. If n or @nvar is 0, no rows are returned. n must be an
the updates or deletes made through the cursor succeeds. integer constant and @nvar must be smallint, tinyint, or
OPTIMISTIC specifies that the cursor does not lock int.
rows as they are read into the cursor. Therefore, if any RELATIVE { n| @nvar} is used to return the nth
user changes the data in the rows being read by the row related to the current row. If n or @nvar is positive,
cursor, the updates or deletes made through the cursor the nth row after the current row is returned. If n or
will not succeed. @nvar is negative, nth row prior to the current row is
select_statement specifies the SQL statements to returned. If n or @nvar is 0, the current row is returned.
define the result set of the cursor. GLOBAL is used to specify the name of the cursor that
FOR UPDATE [ OF column_name [ ,...n ] refers to a global cursor.
specifies the columns that can be updated within the cursor_name specifies the name of the open cursor
cursor. If OF column_name [ ,...n ] is specified, then only from which the fetch should be made.
the listed columns can be updated. If OF column_name @cursor_variable_name is used as the name of a cursor
[ ,...n ] is not specified, then all the columns can be variable referencing the open cursor from which the fetch
updated. should be made.
Opening the Cursor INTO @variable_name[ ,...n] specifies the
The OPEN statement is used to open and populate the local variable names used to hold the data returned from
cursor by executing the T-SQL statements defined in the the cursor. The number of these variables must be equal
DECLARE CURSOR statement. The following syntax is to the number of columns specified in the cursor select
used to open a cursor: list. Each variable in the list, from left to right, is
OPEN [ LOCAL|GLOBAL ] cursor_name associated with the corresponding column in the cursor
where, result set.
cursor_name is the name of the cursor you want to Closing the Cursor
open. A cursor can be closed by using the CLOSE statement.
Fetching Rows from the Cursor When the cursor is closed, the current result set is
The FETCH statement is used to retrieve a row from the released. A cursor once closed can be reopened if required.
cursor, one by one. A row can be fetched from a cursor by The following syntax is used to close a cursor:
using the following syntax: CLOSE cursor_name
FETCH Deallocating the cursor
[ [ NEXT | PRIOR | FIRST | LAST Deallocating removes a cursor reference from the memory.
| ABSOLUTE n | @nvar Once deallocated, a cursor cannot be reopened. A cursor is
| RELATIVE n | @nvar deallocated by using the following syntax:
] DEALLOCATE cursor_name
FROM Consider an example. You want to retrieve the title of an
] employee on the basis of EmployeeID. You have written
{ { [ GLOBAL ] cursor_name } | the following statements for the same:
@cursor_variable_name } CREATE PROCEDURE cursor_demo @id int
[ INTO @variable_name [ ,...n ] ] AS
BEGIN
where, DECLARE @Ctitle varchar(50);
NEXT is used to return the row immediately following the DECLARE cur1 CURSOR FOR SELECT
current row. If FETCH NEXT is the first fetch against a HumanResources.Employee.Title FROM
cursor, it returns the first row in the result set. NEXT is HumanResources.Employee
the default cursor fetch option. WHERE
PRIOR is used to return the result row immediately HumanResources.Employee.EmployeeID =
preceding the current row. If FETCH PRIOR is the first @id;
fetch against a cursor, no row is returned and the cursor is OPEN cur1;
positioned left before the first row. FETCH cur1 INTO @Ctitle;
FIRST is used to return the first row in the cursor. SELECT @Ctitle;
LAST is used to return the last row in the cursor. CLOSE cur1;
ABSOLUTE { n| @nvar} is used to return the nth END
row in the cursor. If n or @nvar is positive, the rows are EXEC cursor_demo 10
counted from top of the result set. If n or @nvar is The preceding statements displays the title of the
employee whose ID is 10, as shown in the following  You can use a variable to store a temporary value.
figure.  You can use the PRINT statement to display a
user-defined message or the content of a variable
on the screen.
 You can use the comment entries in batches to
write a description of the code.
The Output Derived After Executing the Statements  You can use the IF…ELSE statement for
Consider another example, where you need to display the conditional execution of SQL statements.
first name, middle name, and the last name of a person on  The CASE statement evaluates a list of conditions
the basis of the contact ID. For this, you have written the and returns one of the various possible results.
following statements:  You can use the WHILE statement in a batch to
DECLARE @firstname varchar allow a set of T SQL statements to execute
(15),@middlename varchar(15), repeatedly as long as the given condition holds
@lastname varchar(15) true.
DECLARE EmpDetail CURSOR  The BREAK statement causes an exit from the
LOCAL SCROLL STATIC WHILE loop.
FOR  The CONTINUE statement causes the WHILE
SELECT firstName, MiddleName, LastName loop to restart, skipping any statements after the
FROM Person.Contact WHERE ContactID < CONTINUE statement within the loop.
10 AND MiddleName IS NOT NULL  Two ways of handling errors in a batch are:
OPEN EmpDetail  TRY…CATCH
FETCH NEXT FROM EmpDetail  RAISERROR
INTO @firstname, @middlename ,  A stored procedure is a collection of various T-
@lastname SQL statements that are stored under one name
PRINT @firstname + ' ' + @middlename and are executed as a single unit.
+' ' + @lastname  A stored procedure can be created by using the
WHILE @@FETCH_STATUS = 0 CREATE PROCEDURE statement.
BEGIN  A stored procedure allows you to declare
FETCH NEXT FROM EmpDetail parameters, variables, and use T-SQL statements
INTO @firstname,@middlename, @lastName and programming logic.
PRINT @firstname + ' '+@middlename+' '  A stored procedure provides better performance,
+ @lastname security, accuracy, and reduces network
END congestion.
CLOSE EmpDetail  A stored procedure accepts data through input
The preceding statements display the names of those parameters.
employees whose contact ID is less than 10 and the middle  A stored procedure returns data through output
name is not null, as shown in the following figure. parameters or return statements.
 A stored procedure is executed by using the
EXECUTE statement.
 A stored procedure can be altered by using the
ALTER PROCEDURE statement.
 A UDF is a database object that contains a set of
T-SQL statements.
 UDFs can return either a single scalar value or a
result set.
 UDFs are of two types, scalar functions and table-
valued functions.
 A scalar function accepts a single value and
The Output Derived After Executing the Statements
returns a single value.
 A table-valued function returns a table as an
Summary output, which can be derived as part of a
SELECT statement.
In this chapter, you learned that:  At times, your query depends on certain values or
 A batch is a set of SQL statements submitted parameters, which are not fixed and are provided
together to the server for execution. at the time of execution. Therefore, the complete
text of the SQL statement is not known until
execution. Such statements constitute dynamic
SQL.
 Cursor allows working on multiple rows together
as a single unit.

Reference Reading
Implementing Batches

Reference Reading: Books Reference Reading: URLs


Microsoft SQL Server 2012 http://msdn.microsoft.com/
Bible by Adam Jorgensen, en-us/library/
Jorge Segarra, and Patrick ms378070.aspx
LeBlanc

Implementing Stored Procedures

Reference Reading: Books Reference Reading: URLs


Beginning SQL Server 2012 http://www.mssqltips.com/
for Developers by Robin sqlservertutorial/160/sql-
Dewson server-stored-procedure/

Implementing Functions

Reference Reading: Books Reference Reading: URLs


Microsoft SQL Server 2012 http://msdn.microsoft.com/
Bible by Adam Jorgensen, en-us/library/
Jorge Segarra, and Patrick ms174318.aspx
LeBlanc
messages between the client and the server. One is to send
the SQL statement to the server. The other is to reply to
the message from the server after executing the SQL
Chapter 8 statement. This reduction in the number of messages,
which are passing between the client and the server,
Working with Triggers and minimizes the load on the network traffic. This improves
the performance of the server when the network traffic is
Transactions slow and there are more SQL statements to be executed.
In a relational database, data in a table is related to other Before you implement a trigger, it is important to learn
tables. Therefore, while manipulating data in one table, about the various types of triggers that can be created by
you need to verify and validate its effect on the data in the using SQL Server.
related tables. In addition, after inserting or updating data
in a table, you might need to manipulate data in another
table. You also need to ensure that if an error occurs while Identifying Types of Triggers
updating the data in a table, the changes are reverted. This In SQL Server, various kinds of triggers can be used for
helps in maintaining data integrity. SQL Server allows you different types of data manipulation operations. Triggers
to implement triggers and transactions to maintain data can be nested and fired recursively. SQL Server supports
integrity. the following types of triggers:
This chapter explains the various types of triggers that can  Data Modification Language (DML) triggers
be created in SQL Server. In addition, it discusses how to  Data Definition Language (DDL) triggers
implement triggers to enforce data integrity. Further, it
explains how to implement transactions.
DML Triggers
A DML trigger is fired when data in the underlying table is
Objectives affected by DML statements, such as INSERT, UPDATE,
or DELETE. These triggers help in maintaining consistent,
In this chapter, you will learn to: reliable, and correct data in tables. They enable the
 Implement triggers process of reflecting the changes made in a table to other
 Implement transactions related tables.
The DML triggers have the following characteristics:
 Fired automatically by SQL Server whenever any
Implementing Triggers data modification statement is issued.
At times, while performing data manipulation on a  Cannot be explicitly invoked or executed, as in
database object, you might also need to perform the case of the stored procedures.
manipulation on another object. For example, in an  Prevent incorrect, unauthorized, and inconsistent
organization, the employees use the Online Leave changes in data.
Approval system to apply for leaves. When an employee  Do not return data to the user.
applies for a leave, the leave details are stored in the  Can be nested up to 32 levels. The nesting of
LeaveDetails table. In addition, a new record is added to triggers occurs when a trigger performs an action
the LeavesForApproval table. When the supervisors log on that initiates another trigger.
to the system, all the leaves pending for their approval are Whenever a trigger is fired in response to the INSERT,
retrieved from the LeavesForApproval table and displayed DELETE, or UPDATE statement, SQL Server creates two
to them. temporary tables, called magic tables. The magic tables
To perform such operations, SQL Server allows you to are called Inserted and Deleted. These are logical tables
implement triggers. A trigger consists of a set of T-SQL and are similar in structure to the table on which the
statements activated in response to certain actions, such as trigger is defined.
insert or delete. Triggers are used to ensure data integrity The Inserted table contains a copy of all the records that
before or after performing data manipulations. Therefore, are inserted in the trigger table. A trigger table refers to the
a trigger is a special kind of stored procedure that executes table on which the trigger is defined. The Deletedtable
in response to specific events. contains all the records that have been deleted from the
Triggers are also used to enhance an application's trigger table. Whenever you update data in a table, the
performance. Consider a scenario where a client needs to trigger uses both theInserted table and the Deletedtable.
send 10 SQL statements to SQL Server. Suppose out of Depending on the operation performed, DML triggers can
these 10 SQL statements, if five SQL statements are fired be further categorized as:
by a trigger, the client saves at least 10 communication  INSERT trigger: Is fired whenever an attempt is
made to insert a row in the trigger table. When an
INSERT statement is executed, the newly inserted
rows are added to the Inserted table.
 DELETE trigger: Is fired whenever an attempt
is made to delete a row from the trigger table.
When a DELETE statement is executed, the
deleted rows are added to the Deleted table. The
Deleted table and the trigger table do not have
any rows in common, as in the case of the
Insertedtable and the trigger table.
There are three ways of implementing referential
integrity by using a DELETE trigger:
 The cascade method: Deletes the
corresponding records from the dependent
tables whenever a record is deleted from the
master table.
 The restrict method: Restricts the deletion
of records from the master table if the
related records are present in the dependent
tables.
 The nullify method: Nullifies the values in
the specified columns of the dependent The Functioning of the UPDATE Trigger
tables whenever a record is deleted from the When a DML trigger is fired, one or more rows of data
master table. can be affected. This is a common behavior of the
 UPDATE trigger: Is fired when an UPDATE UPDATE and DELETE triggers because these statements
statement is executed in the trigger table. It uses are frequently used for affecting multiple rows. This
the two logical tables for its operations. The behavior is less common for the INSERT trigger because
Deleted table contains the original rows (the rows usually, only one record is inserted in a table. However, if
with the values before updating) and the Inserted the INSERT INTO (table_name) SELECT statement is
table stores the new rows (the modified rows). used, multiple rows can be inserted by using a single
After all the rows are updated, the Deleted table trigger.
and the Inserted table are populated and the Depending on the way the triggers are fired, they can be
trigger is fired. further categorized as:
For example, you have a table with three  AFTER triggers
columns. It stores the details of hardware devices.  INSTEAD OF triggers
You updated a value in Column2 from 'Printer' to
AFTER Triggers
'Lex New Printer'. During the update process, the
The AFTER trigger can be created on any table for the
Deleted table holds the original row (the row with
insert, update or delete operation just like other triggers.
the values before updating) with the value
The main difference in the functionality of an AFTER
'Printer' in Column2. The Insertedtable stores the
trigger is that it is fired after the execution of the DML
new row (the modified row) with the value 'Lex
operation for which it has been defined. The AFTER
New Printer' in Column2.
trigger is executed when all the constraints and triggers
The following figure illustrates the functioning of the defined on the table are successfully executed.
UPDATE trigger.
If more than one AFTER trigger is created on a table, they
are executed in the order of creation.
For example, the EmpSalary table stores the salary and tax
details for all the employees in an organization. You need
to ensure that after the salary details of an employee are
updated in the EmpSalary table, the tax details should also
be recalculated and updated. In such a scenario, you can
implement an AFTER trigger to update the tax details
when the salary details are updated.
You can have multiple AFTER triggers for a single DML
operation.
INSTEAD OF Triggers
The INSTEAD OF triggers can be primarily used to Nested triggers are fired due to actions of other triggers.
perform an action, such as a DML operation on another Both DML and DDL triggers can be nested when a trigger
table or view. This type of trigger can be created on both a performs an action that initiates another trigger. For
table as well as a view. For example, if a view is created example, a DELETE trigger on the Department table
with multiple columns from two or more tables, then an deletes the corresponding employee records in the
insert operation on the view is only possible if the primary Employee table and a DELETE trigger on the Employee
key fields from all the base tables are used in the query. table inserts these deleted employee records in the
Alternatively, if you use an INSTEAD OF trigger, you can EmployeeHistory table. Therefore, the DELETE trigger on
insert data in the base tables individually. This makes the the Department table initiates the DELETE trigger on the
view logically updateable. Employee table, as shown in the following figure.
An INSTEAD OF trigger can be used for the following
actions:
 Ignoring parts of a batch
 Not processing a part of a batch and logging the
problem rows
 Taking an alternative action when an error
condition is encountered
You can even create an INSTEAD OF trigger to restrict
deletion in a master table. For example, you can display a
message "Master records cannot be deleted" if a delete
statement is executed on the Employee table of the
AdventureWorks database.
Unlike AFTER triggers, you cannot create more than one
INSTEAD OF trigger for a DML operation on the same A Nested Trigger
table or view.
Recursive Triggers
Recursive triggers are a special case of nested triggers.
Unlike nested triggers, support for recursive triggers is at
the database level. As the name implies, a recursive trigger
eventually calls itself. The types of recursive triggers are:
 Direct
 Indirect
Direct Recursive Triggers
When a trigger fires and performs an action that causes the
same trigger to fire again, the trigger is called a direct
recursive trigger. For example, an application updates the
Table A, which causes trigger T1 to fire. T1 updates the
Table A again, which causes the trigger T1 to fire again.
The following figure depicts the execution of a direct
recursive trigger.

DDL Triggers
DDL triggers are fired in response to DDL statements,
such as CREATE TABLE or ALTER TABLE. They can be
used to perform administrative tasks, such as database
auditing. Database auditing helps in monitoring DDL
operations on a database. DDL operations can include
operations such as creation of a table or view, or
modification of a table or procedure. Consider an example,
where you want the database administrator to be notified A Direct Recursive Trigger
whenever a table is created in the master database. For this Indirect Recursive Triggers
purpose, you can create a DDL trigger. An indirect recursive trigger fires a trigger on another
table and eventually the nested trigger ends up firing the
Nested Triggers
first trigger again. For instance, an UPDATE statement on
Table A fires a trigger that, in turn, fires an update on
Table B. The update on Table B fires another trigger that Creating Triggers
performs an update on Table C. Table C has a trigger that
You can use the CREATE TRIGGER statement to create
causes an update on Table A again. As a result, the
triggers. The syntax of the CREATE TRIGGER statement
UPDATE trigger of Table A is fired again. The following
is:
figure depicts the execution of an indirect recursive
CREATE TRIGGER trigger_name
trigger.
ON { table | view }
{ FOR | AFTER | INSTEAD OF }
[WITH [ENCRYPTION] [EXECUTE AS] ]
{ AS
{ sql_statement [ ...n ] }
}
where,
trigger_name specifies the name of the trigger to be
created.
table | view specifies the name of the table or view
on which the trigger is to be created.
FOR | AFTER | INSTEAD OF specifies the
precedence and execution context of a trigger.
WITH ENCRYPTION encrypts the text of the CREATE
An Indirect Recursive Trigger TRIGGER statement.
EXECUTE AS specifies the security context under which
the trigger is executed.
AS sql_statement specifies the trigger conditions
and actions. A trigger can contain any number of T-SQL
statements, provided these are enclosed within the
BEGIN and END keywords.
For example, the following statement creates a trigger on
the HumanResources.Department table of the
AdventureWorks database:
CREATE TRIGGER [HumanResources].
[trgDepartment] ON [HumanResources].
[Department]
AFTER UPDATE AS
BEGIN
UPDATE [HumanResources].[Department]
SET [HumanResources].[Department].
[ModifiedDate] = GETDATE()
FROM Inserted
WHERE Inserted.[DepartmentID] =
[HumanResources].[Department].
[DepartmentID];
END;
The preceding statement creates a trigger named
trgDepartment. This trigger is fired on every successfully
executed UPDATE statement on the
HumanResources.Department table. The trigger updates
the ModifiedDate column of every updated value with the
current date.
The following statement creates a trigger to display the
data that is inserted in the magic tables:
CREATE TRIGGER trgMagic ON
EmpDeptHistory
AFTER UPDATE AS Hence, cannot insert.'
BEGIN ROLLBACK TRANSACTION
SELECT * FROM Deleted END
SELECT * FROM Inserted RETURN
END;
The preceding statement creates an AFTER UPDATE
The ROLLBACK TRANSACTION statement is used to
trigger on the EmpDeptHistory table. Whenever an
roll back transactions. The ROLLBACK TRANSACTION
UPDATE statement is fired on the EmpDeptHistory table, statement in the trgInsertShift trigger is used to undo the
the trgMagic trigger is executed and displays the previous insert operation.
value in the table as well as the updated value.
Creating a DELETE Trigger
A DELETE trigger gets fired at the time of deleting rows
Use the following statement to create the from the trigger table. For example, the following
EmpDeptHistory table: SELECT * INTO statement creates a trigger to disable the deletion of rows
EmpDeptHistory FROM from the Department table:
HumanResources.EmployeeDepartmentHisto CREATE TRIGGER trgDeleteDepartment
ry ON HumanResources.Department
For example, you can execute the following UPDATE FOR DELETE
statement on the EmpDeptHistory table: AS
UPDATE EmpDeptHistory SET DepartmentID PRINT 'Deletion of Department is not
= 16 allowed'
WHERE EmployeeID = 4 ROLLBACK TRANSACTION
When the preceding statement is executed, the trgMagic RETURN
trigger is fired displaying the output, as shown in the Creating an UPDATE Trigger
following figure. An UPDATE trigger gets fired at the time of updating
records in the trigger table. For example, you need to
create a trigger to ensure that the average of the values in
the Rate column of the EmployeePayHistory table should
not be more than 20 when the value of Rate is increased.
To perform this task, you can use the following statement:
CREATE TRIGGER
The Output Derived by Using the UPDATE Statement trgUpdateEmployeePayHistory
In the preceeding figure, the result set on the top shows the ON HumanResources.EmployeePayHistory
values before the execution of the UPDATE statement and FOR UPDATE
the result set at the bottom shows the updated values. AS
IF UPDATE (Rate)
Creating an INSERT Trigger BEGIN
An INSERT trigger gets fired at the time of adding new DECLARE @AvgRate float
rows in the trigger table. For example, users at SELECT @AvgRate = AVG(Rate)
AdventureWorks, Inc. want the modified date to be set to FROM HumanResources.EmployeePayHistory
the current date whenever a new record is entered in the IF(@AvgRate > 20)
Shift table. To perform this task, you can use the following BEGIN
statement: PRINT 'The average value of rate
CREATE TRIGGER cannot be more than 20'
HumanResources.trgInsertShift ROLLBACK TRANSACTION
ON HumanResources.Shift END
FOR INSERT END
AS
DECLARE @ModifiedDate datetime Creating an AFTER Trigger
SELECT @ModifiedDate = ModifiedDate An AFTER trigger gets fired after the execution of a DML
FROM Inserted statement. For example, you need to display a message
IF (@ModifiedDate != getdate()) after a record is deleted from the Employee table. To
BEGIN perform this task, you can write the following statement:
PRINT 'The modified date should be CREATE TRIGGER trgDeleteShift ON
the current date. HumanResources.Shift
AFTER DELETE
AS CREATE TRIGGER trgDelete ON
PRINT 'Deletion successful' Sales.Customer
If there are multiple AFTER triggers for a single DML INSTEAD OF DELETE
operation, you can change the sequence of execution of AS
these triggers by using the sp_settriggerorder system PRINT 'Customer records cannot be
stored procedure. The syntax of the sp_settriggerorder deleted'
stored procedure is: Creating a DDL Trigger
sp_settriggerorder <triggername>, DDL triggers are special kind of triggers that fire in
<order-value>, <DML-operation> response to the DDL statements. They can be used to
where, perform administrative tasks in the database such as
triggername specifies the name of the trigger whose auditing and regulating database operations. The following
order of execution needs to be changed. statement creates a DDL trigger:
order-value specifies the order in which the trigger CREATE TRIGGER safety
needs to be executed. The values that can be entered are ON DATABASE
FIRST, LAST, and NONE. If FIRST is mentioned, then FOR DROP_TABLE, ALTER_TABLE
the trigger is the first trigger to be executed. If LAST is AS
mentioned, then the trigger will be the last trigger to be PRINT 'You must disable Trigger
executed. If NONE is specified, then the trigger is "safety" to drop or alter tables!'
executed on a random basis. ROLLBACK
DML-operation specifies the DML operation for which In the preceding statement, the safety trigger will fire
the trigger was created. This should match the DML whenever a DROP_TABLE or ALTER_TABLE event
operation associated with the trigger. For example, if occurs in the database.
UPDATE is specified for a trigger that is created for the While creating DDL triggers, you need to use DDL events
INSERT operation, the sp_settriggerorder stored that can be used to fire a DDL trigger. Some of the DDL
procedure will generate an error. events that can be used with DDL triggers are:
For example, you have created another AFTER trigger,  CREATE_FUNCTION
trgDeleteShift1 on the Shift table, as shown in the  ALTER_FUNCTION
following statement:  DROP_FUNCTION
CREATE TRIGGER trgDeleteShift1 ON  CREATE_INDEX
HumanResources.Shift  ALTER_INDEX
AFTER DELETE  DROP_INDEX
AS  CREATE_PROCEDURE
PRINT 'Attempting to Delete'  ALTER_PROCEDURE
By default, triggers are executed in the sequence of their  DROP_PROCEDURE
creation. However, if you need to execute the trigger  CREATE_SYNONYM
named trgDeleteShift1 before the trgDeleteShift trigger,  DROP_SYNONYM
you can execute the following statement:  CREATE_TABLE
sp_settriggerorder  ALTER_TABLE
'HumanResources.trgDeleteShift1',  DROP_TABLE
'FIRST', 'DELETE'  CREATE_TRIGGER
RETURN  ALTER_TRIGGER
Creating an INSTEAD OF Trigger  DROP_TRIGGER
INSTEAD OF triggers are executed in place of the events The events in the preceding list correspond to the SQL
that cause the trigger to fire. For example, if you create an statement, the syntax of which is modified to include
INSTEAD OF UPDATE trigger on a table, the statements underscores ('_') between keywords.
specified in the trigger will be executed instead of the
UPDATE statement that caused the trigger to fire.
These triggers are executed after the inserted table and the
Managing Triggers
deleted table reflecting the changes to the base table are While managing triggers, you can perform the following
created, but before any other action is taken. They are operations on a trigger:
executed before any constraint, and therefore, supplement  Alter a trigger
the action performed by a constraint. You can create the  Delete a trigger
following INSTEAD OF trigger to restrict the deletion of
records in the Customer table:
Altering a Trigger
As a database developer, you might need to modify the
logic or code behind a trigger. For example, a trigger is
used to calculate a 10 percent discount on every item sold.
With the new management policy, the discount rate has
been increased to 15 percent. To reflect this change in the
trigger, you need to change the code in the trigger. You can
use the ALTER TRIGGER statement to modify the trigger.
The syntax of the ALTER TRIGGER statement is:
ALTER TRIGGER trigger_name
{ FOR | AFTER | INSTEAD OF}
{ event_type [ ,...n ] |
DDL_DATABASE_LEVEL_EVENTS }
{ AS
{ sql_statement [ ...n ] }
}
For example, you can modify the trgDeleteShift trigger
that was created earlier to restrict the deletion of records in
the Shift table. To modify the trgDeleteShift trigger, you
need to execute the following statement: Disabling a Trigger
ALTER TRIGGER Sometimes, you need to prevent the execution of a trigger
HumanResources.trgDeleteShift ON to perform a specific operation on a table. For example, a
HumanResources.Shift trigger is created on the Employee table that prevents the
INSTEAD OF DELETE modification of the employee data. However, one of the
AS employees has shifted to another department. This requires
PRINT 'Deletion of Shift details is you to make the necessary changes in the Employee table.
not allowed' You can perform this task by disabling the trigger.
ROLLBACK TRANSACTION Once the trigger is disabled, it will not execute until it is
RETURN enabled again. Disabling a trigger does not delete the
Apart from altering a DML trigger, you can modify a DDL trigger. It remains in the database, but does not execute in
trigger by executing the following ALTER statement: response to an event.
ALTER TRIGGER safety SQL Server provides the DISABLE TRIGGER statement
ON DATABASE to disable an existing trigger. The syntax of the DISABLE
FOR DROP_TABLE TRIGGER statement is:
AS DISABLE TRIGGER { [ schema_name . ]
PRINT 'YOU CAN ALTER BUT NOT DELETE trigger_name | ALL }
TABLE' ON { object_name | DATABASE }
After executing the preceding statement, the safety trigger where,
is modified for dropping a table. The safety trigger is fired schema_name specifies the name of schema to which
whenever you try to drop any table in the database. the trigger belongs.
Deleting a Trigger trigger_name specifies the name of the trigger to be
As the requirements change, you may need to delete some disabled.
triggers. For example, you have a trigger that updates the All specifies that all triggers defined at the scope of the
salaries of the employees in their pay slips. Now, this ON clause are disabled.
function is performed by a front-end application in your object_name specifies the name of the table, or view
organization. Therefore, you need to remove the trigger. on which the trigger was defined.
To delete a trigger, you can use the DROP TRIGGER DATABASE is used for a DDL trigger.
statement. The syntax of the DROP TRIGGER statement For example, you can disable the safety trigger by
is: executing the following statement:
DROP TRIGGER { trigger } DISABLE TRIGGER safety ON DATABASE
where, Enabling a Trigger
trigger is the name of the trigger you want to drop. You disable the triggers when you do not want them to be
The following statement drops the trgMagic trigger: executed. Later, if you want them to be executed in
DROP TRIGGER trgMagic response to their respective events, you can again enable
them.
SQL Server provides the ENABLE TRIGGER statement
to enable a trigger. The syntax of the ENABLE TRIGGER CommandText)[1]','nvarchar(max)')
statement is: ROLLBACK
ENABLE TRIGGER { [ schema_name . ] In the preceding code, the value() function is used to
trigger_name | ALL } display the data of the CommandText tag. This tag stores
ON { object_name | DATABASE } the actual query that caused the trigger to fire.
For example, you can enable the safety trigger by You can display the event information after executing the
executing the following statement: following CREATE TABLE statement:
ENABLE TRIGGER safety ON DATABASE CREATE TABLE NewTable
Displaying Events of a Trigger (
Sometimes, you want to know the information about the Customer_name varchar(30),
Salary int
events that caused the trigger to be executed. For example,
)
a new payroll software is being installed in an
organization. James, a database developer, wants to After executing the preceding statement, the Info_Event
understand the behavior of the new software under the trigger is fired and the output is displayed, as shown in the
predefined data. He has created a trigger that is fired when following figure.
the database is modified. While executing the trigger, he
wants to get the detailed information, such as the events
that caused the trigger to be fired and the SQL statement
that was executed to fire the trigger.
The Output Derived After Info_Event Trigger Fires
SQL Server provides the EVENTDATA() function that
can be embedded with the CREATE TRIGGER statement
to provide the information, such as time and type of the Using the UPDATE() Function
event that caused the trigger to fire. The EVENTDATA()
function returns the details of the trigger in the XML While performing the UPDATE operation on a database
format. This XML data contains <EVENT_INSTANCE> object, you may need to perform specific actions on
as the parent tag. The sample format of the XML data another database object. To achieve this functionality, you
returned by the EVENTDATA() function is: can use the UPDATE trigger on a database object. The
<EVENT_INSTANCE> scope of the UPDATE trigger is tables. In other words, the
<EventType> </EventType> UPDATE trigger is fired on updating any column of a
<PostTime> </PostTime> table on which the trigger is defined. However, at times,
<SPID> </SPID> you require that the UPDATE trigger should be fired when
<ServerName> </ServerName> a specific column in a table is updated.
<LoginName> </LoginName> For example, in an organization, the employees use the
<UserName> </UserName> Online Leave Approval system to apply for leaves. When
<DatabaseName> </DatabaseName> an employee applies for a leave, the leave details are
<SchemaName> </SchemaName> stored in the LeaveDetails table. In addition, a new record
<ObjectName> </ObjectName> is added to the LeavesForApproval table. When the
<TSQLCommand> supervisors log on to the system, all the leaves pending for
<CommandText> </CommandText> their approval are retrieved from the LeavesForApproval
</TSQLCommand> table and displayed to them. The supervisor approves or
</EVENT_INSTANCE> denies a leave by updating the LeaveStatus column of the
To retrieve the data stored in the preceding XML format, LeavesForApproval table. Therefore, you want that after a
you need to use the functions of the XQuery language. supervisor updates the value of the LeaveStatus column in
For example, you can create a trigger on the the LeavesForApproval table, the LeaveStatus column in
AdventureWorks database with the EVENTDATA() the LeaveDetails table should also be updated.
function by executing the following statement: To achieve the functionality required in the preceding
CREATE TRIGGER Info_Event scenario, you can use the UPDATE() function with an
ON DATABASE UPDATE trigger. SQL Server provides the UPDATE()
FOR CREATE_TABLE function that can be used to create an UPDATE trigger
AS applied to specific columns. The syntax of the UPDATE()
PRINT 'CREATING TABLE' function is:
RAISERROR ('New tables cannot be UPDATE (column)
created in this database.', 16, 1) where,
SELECT EVENTDATA().value('(/
column specifies the name of the column on which an
EVENT_INSTANCE/TSQLCommand/
UPDATE trigger is applied. until one transaction is executed so that only one
For example, you want that whenever an attempt is made transaction can work on a database resource at a time.
to update the VacationHours or Title columns of the
Employee table, a message should be displayed and the
updates should be rolled back. For this, you can create an Creating Transactions
AFTER UPDATE trigger with the UPDATE() function. To
A transaction can be defined as a sequence of operations
accomplish this task, you can use the following statement:
performed together as a single logical unit of work. A
USE AdventureWorks
single unit of work must possess the following properties
GO
called ACID (Atomicity, Consistency, Isolation, and
CREATE TRIGGER reminder
Durability).
ON HumanResources.Employee
AFTER UPDATE  Atomicity: This states that either all the data
AS modifications are performed or none of them are
IF (UPDATE (VacationHours) OR UPDATE performed.
(Title))  Consistency: This states that all data is in a
BEGIN consistent state after a transaction is completed
Print 'You cannot update the specified successfully. All rules in a relational database
columns' must be applied to the modifications in a
ROLLBACK TRAN transaction to maintain complete data integrity.
END  Isolation: This states that any data modification
GO made by concurrent transactions must be isolated
In the preceding statement, the VacationHours and Title from the modifications made by other concurrent
columns are specified in the UPDATE() function to fire transactions. In simpler words, a transaction
the trigger whenever an attempt is made to update these either accesses data in the state in which it was
columns. before a concurrent transaction modified it or
After creating the trigger, you can use the following accesses the data after the second transaction has
statement to verify the trigger: been completed. There is no scope for the
UPDATE HumanResources.Employee transaction to see an intermediate state.
SET VacationHours=25  Durability: This states that any change in data by
WHERE Employee.EmployeeID=1 a completed transaction remains permanently in
When the preceding statement is executed, the reminder effect in the system. Therefore, any change in
trigger is fired to prevent the updation of the data due to a completed transaction persists even
VacationHours column. in the event of a system failure. This is ensured
by the concept of backing up and restoring
transaction logs.
Activity 8.1: Implementing It is important that a database system provides
mechanisms to ensure the physical integrity of each
Triggers transaction. To fulfill the requirements of the ACID
properties, SQL Server provides the following features:
 Transaction management: Ensures the atomicity
Implementing Transactions and consistency of all transactions. A transaction
must be successfully completed after it has started
At times, you are required to execute a sequence of or SQL Server undoes all the data modifications
statements as a single logical unit of work. For example, made since the start of the transaction.
whenever you transfer money from one bank account to  Locking: Preserves transaction durability and
another account, the amount is debited from one account isolation.
and credited to another account. In such a situation, you SQL Server allows implementing transactions in the
need either all the statements to be executed successfully following ways:
or none of them to be executed. This helps in ensuring  Autocommit transaction
data integrity.  Implicit transaction
In SQL Server, you can implement transactions to ensure  Explicit transaction
data integrity. In a multi user environment, there can be
multiple transactions accessing the same resource at the Autocommit Transaction
same time. To prevent errors that could occur due to The autocommit transaction is the default transaction
transactions accessing the same resource, you can use management mode of SQL Server. Based on the
locks. Locks provide a mechanism to secure a resource completeness of every T-SQL statement, transactions are
automatically committed or rolled back. A statement is Explicit Transaction
committed if it is completed successfully, and it is rolled An explicit transaction is the one where both the start and
back if it encounters an error. the end of the transaction are defined explicitly. Explicit
Implicit Transaction transactions were called user-defined or user-specified
An implicit transaction is the one where you do not need transactions in earlier versions of SQL Server. They are
to define the start of the transaction. You are only required specified by using the following statements:
to commit or roll back the transaction. You also need to  BEGIN TRANSACTION: Is used to set the
turn on the implicit transaction mode to specify the starting point of a transaction.
implicit transaction. After you have turned on the implicit  COMMIT TRANSACTION: Is used to save the
transaction mode, SQL Server starts the transaction when changes permanently in the database.
it executes any of the statements listed in the following  ROLLBACK TRANSACTION: Is used to undo
table. the changes.
 SAVE TRANSACTION: Is used to establish
ALTER TABLE INSERT CREATE save points that allow partial rollback of a
OPEN DELETE DROP transaction.
REVOKE SELECT FETCH
TRUNCATE GRANT UPDATE You can use the BEGIN TRANSACTION statement to
TABLE override the default autocommit mode. SQL Server returns to
the autocommit mode when the explicit transaction is
The Implicit Transaction Statements committed or rolled back.
The transaction remains in effect until you issue a Beginning a Transaction
COMMIT or ROLLBACK statement. After the first The BEGIN TRANSACTION statement marks the start of
transaction is committed or rolled back, SQL Server starts a transaction. The syntax of the BEGIN TRANSACTION
a new transaction the next time any of the preceding statement is:
statements is executed. SQL Server keeps generating a BEGIN TRAN[SACTION] [transaction_name
chain of implicit transactions until you turn off the implicit | @tran_name_variable]
transaction mode. where,
You can turn on the implicit transaction mode by using the transaction_name is the name assigned to the
following statement: transaction. This parameter must conform to the rules for
SET IMPLICIT_TRANSACTIONS ON; identifiers and should not be more than 32 characters.
For example, consider the following statements: @tran_name_variable is the name of a user-defined
SET IMPLICIT_TRANSACTIONS ON; variable that contains a valid transaction name. This
Insert into Depositor (Customer_name, variable must be declared with a char, varchar, nchar, or
Acc_num) values('Nora',101), ('Robin', nvarchar data type.
4101), Commiting a Transaction
('James', 501), ('Jennifer', 7101) The COMMIT TRANSACTION or COMMIT WORK
statement marks the end of an explicit transaction. This
-- Commit first transaction statement is used to end a transaction for which no errors
COMMIT TRANSACTION; were encountered during the transaction. The syntax of the
-- Second implicit transaction started COMMIT TRANSACTION statement is:
by a SELECT statement COMMIT [ TRAN[SACTION]
SELECT COUNT(*) FROM Depositor [transaction_name |
INSERT INTO Depositor VALUES ('Peter', @tran_name_variable] ]
9200)
where,
SELECT * FROM Depositor;
-- Commit second transaction transaction_name specifies a transaction name
COMMIT TRANSACTION; assigned by a previous BEGIN TRANSACTION
In the preceding statements, the implicit transaction mode statement. It can be used to indicate the nested BEGIN
is turned on. After the first transaction is committed, the TRANSACTION statement that is associated with the
second implicit transaction is started as soon as the COMMIT TRANSACTION statement.
SELECT statement is executed. @tran_name_variable is the name of a user-defined
You can turn off the implicit transaction mode by using the variable that contains a valid transaction name. This
following statement: variable must be declared with a char, varchar, nchar, or
SET IMPLICIT_TRANSACTIONS OFF; nvarchar data type.
Consider a scenario where the salary of an employee transaction '+ convert(varchar
named Robert is changed to $15000 and the salary of an (3),@@TRANCOUNT)
employee named Jack is changed to $18000. To perform BEGIN TRAN
these transactions, you need to execute the following PRINT'beginning with the third
statements: transaction ' + convert(varchar
UPDATE EmployeeDetails (3),@@TRANCOUNT)
SET Salary = 15000 COMMIT
WHERE EmpName = 'Robert' PRINT 'commiting the first trasaction
UPDATE EmployeeDetails '+ convert(varchar(3),@@TRANCOUNT)
SET Salary = 18000 COMMIT
WHERE EmpName = 'Jack' PRINT 'commiting the second
When the preceding statements are executed, either both transaction '+ convert(varchar
should be executed successfully or none of them should be (3),@@TRANCOUNT)
executed. If any of the statements fails to execute, the commit
entire transaction should be rolled back. Therefore, you PRINT 'commiting the third transaction
need to define the beginning and end of a transaction, as '+ convert(varchar(3),@@TRANCOUNT)
shown in the following statements: The following figure displays the output of the preceding
BEGIN TRAN myTran statements.
UPDATE EmployeeDetails
SET Salary = 10000
WHERE EmpName = 'Robert'
UPDATE EmployeeDetails
SET Salary = 12000
WHERE EmpName = 'Jack'
COMMIT TRAN myTran
The preceding statements create a transaction named
myTran, which updates the salaries of the employees in
the EmployeeDetails table.

The Output Derived by Using the @@TRANCOUNT Function


Determining the Count of Local
Transactions
In SQL Server, the @@TRANCOUNT function is used to
count the number of local transactions executing on the
current connection. SQL Server allows transactions to be
nested. The @@TRANCOUNT function returns the
current nesting level of these transactions. The outermost
BEGIN TRANSACTION statement sets the value of
@@TRANCOUNT to one. Its value increases by one for
every BEGIN TRANSACTION statement, which follows
and decreases by one with every COMMIT
TRANSACTION statement. However, the ROLLBACK
TRANSACTION statement sets the value of
@@TRANSACTION to zero.
Consider the following statements:
PRINT 'Count of active
transactions:'+convert(varchar
(3),@@TRANCOUNT)
BEGIN TRAN Reverting Transactions
PRINT 'Beginning with the first
Transaction '+ convert(varchar Sometimes, all the statements of a transaction do not
(3),@@TRANCOUNT) execute successfully due to some problem. For example,
BEGIN TRAN in case of a power failure between two statements, one
PRINT'beginning with the second statement will be executed and the other will not. This
leaves the transaction in an invalid state. In such a case, transaction is rolled back.
you need to revert to the statement that has been At times, you may want SQL Server to automatically roll
successfully executed to maintain consistency. back the current transaction if a T-SQL statement raises a
The ROLLBACK TRANSACTION statement rolls back runtime error. To accomplish this requirement, SQL Server
an explicit or implicit transaction to the beginning of the provides the SET XACT_ABORT statement. The syntax
transaction or to a savepoint within a transaction. A of the SET XACT_ABORT statement is:
savepoint is used to divide a transaction into smaller parts. SET XACT_ABORT { ON | OFF }
Savepoints allow you to discard parts of a long transaction If SET XACT_ABORT is ON and a runtime error is
instead of rolling back the entire transaction. encountered in the T-SQL statement, the entire current
The syntax of the ROLLBACK TRANSACTION transaction is rolled back.
statement is: If SET XACT_ABORT is OFF and a runtime error is
ROLLBACK [TRAN[SACTION] encountered in the T-SQL statement, the current statement
[transaction_name |@tran_name_variable is rolled back and the transaction continues processing.
|savepoint_name | However, depending on the severity of the transaction, the
@savepoint_variable] ] entire current transaction may be rolled back. SET
where, XACT_ABORT OFF is the default setting.
transaction_name is the name assigned to the Consider the following statements to create tables named
transaction. This parameter must conform to the rules for table1 and table2:
identifiers and should not be more than 32 characters. CREATE TABLE table1
@tran_name_variable is the name of a user-defined (x INT NOT NULL PRIMARY KEY);
variable that contains a valid transaction name. This CREATE TABLE table2
variable must be declared with a char, varchar, nchar, or (x INT NOT NULL REFERENCES table1(x));
nvarchar datatype. GO
savepoint_name is the name assigned to the Consider the following statements to insert records into
savepoint. table1:
@savepoint_variable is the name of a user-defined INSERT INTO table1 VALUES (1);
variable containing a valid savepoint name. This variable INSERT INTO table1 VALUES (3);
must be declared with a char, varchar, nchar, or nvarchar INSERT INTO table1 VALUES (4);
datatype. INSERT INTO table1 VALUES (6);
For example, while updating the personal details of an GO
employee, you want all the statements to be rolled back if The following statement turns off the automatic rollback
any query fails. To ensure this, you can write the following of the current transaction if any runtime error occurs:
statements: SET XACT_ABORT OFF;
BEGIN TRANSACTION TR1 The following statements insert the values in table2:
BEGIN TRY BEGIN TRANSACTION;
UPDATE Person.Contact INSERT INTO table2 VALUES (1);
SET EmailAddress='[email protected]' INSERT INTO table2 VALUES (2); //This
WHERE ContactID = 1070 statement violates referential //
--Statement 1 integrity and will be rolled back
UPDATE HumanResources.EmployeeAddress INSERT INTO table2 VALUES (3);
SET AddressID = 32533 COMMIT TRANSACTION;
WHERE EmployeeID = 1 GO
COMMIT TRANSACTION TR1 The preceding statements insert the values, 1 and 3, into
--Statement 2 table2. The value, 2, is not inserted into table2 as this
SELECT 'Transaction Executed' value does not exist in table1. Therefore, it violates the
END TRY referential integrity. The following figure displays the data
BEGIN CATCH stored in table2.
ROLLBACK TRANSACTION TR1
SELECT 'Transaction Rollbacked'
END CATCH
In the preceding statements, the TR1 transaction updates
the e-mail address of an employee. In addition, this
transaction updates the address of the employee. In the The Data Stored Inside the Table2
query, the first statement is executed, but the second Now, execute the following statement to turn on the
statement gives an error due to which the whole
automatic rollback of the current transaction if any Need for Locking
runtime error occurs: In the absence of locking, problems may occur if more
SET XACT_ABORT ON; than one transaction uses the same data from a database at
GO the same time. These problems include:
Execute the following statements to insert more records in  Lost updates
table2:  Uncommitted dependency
BEGIN TRANSACTION;  Inconsistent analysis
INSERT INTO table2 VALUES (4);  Phantom reads
INSERT INTO table2 VALUES (5); //This
Lost Updates
statement violates referential //
A lost update occurs when two or more transactions try to
integrity and the entire transaction
modify the same row. In this case, each transaction is
will be rolled back
unaware of the other transaction. The last update in the
INSERT INTO table2 VALUES (6);
COMMIT TRANSACTION; transaction queue overwrites the updates made by the
GO previous transactions. This leads to loss of data
manipulation performed by the previous transactions.
All the preceding statements are rolled back as the value,
5, does not exist in table1 and violates the referential For example, in a banking application, two transactions
integrity. Therefore, table2 still contains two records, 1 are simultaneously trying to update the balance details for
and 3. a particular account. Both the transactions select data from
the table simultaneously and get the same value for the
current balance. When one transaction is committed, the
Implementing Transactional Integrity balance is updated, but the second transaction does not get
the updated value. Therefore, when the second transaction
In a multi-user environment, multiple users can access the is committed, the changes done by the previous
database server at a single point in time. Multiple users transaction will be lost. This results in the loss of an
might also execute the UPDATE or SELECT statements update.
on the same data. This may lead to data redundancy or Uncommitted Dependency
incorrectness in the database. An uncommitted dependency is also known as a dirty
Consider the example of AdventureWorks, Inc. A user read. This problem occurs when a transaction queries data
sends a request to update all the records in a table. At the from a table when the other transaction is in the process of
same time, another user might send a query to update data modifying data.
in only selected records in the same table. In such a case, For example, the details of all the products are stored in
there are chances of losing information that results the Products table in a database. A user is executing a
inconsistency in the database. Such problems can be query to update the price for all the products. While the
resolved by using locks. changes are being made, another user generates a report
SQL Server uses the concept of locking to ensure from the same table and distributes it to the intended
transactional integrity. In a multi-user environment, audience. The update query finally commits and the table
locking prevents different users from changing the same is updated now. In this case, the distributed report contains
data at the same time. In SQL Server, locking is data that no longer exists and should be treated as
implemented automatically. However, you can also redundant.
explicitly use locks. Locks are used to guarantee that the This problem is knows as the problem of dirty read. To
current user of a resource has a consistent view of that avoid such a problem, you should not allow any user to
resource, from the beginning to the end of an operation. read the table until the changes are finalized.
This ensures completeness of data modifications. Inconsistent Analysis
For a transaction-processing database, a DBMS resolves An inconsistent analysis problem is also known as a non-
potential conflicts between two different processes that are repeatable problem. This problem arises when the data is
attempting to change the same information at the same changed between simultaneous read by one user.
time. For example, in a banking application, a user generates a
report to display the balance of all the accounts. The user
Transactional concurrency is the ability of multiple uses the result set to update data. Then, the user again
transactions to access or change the shared data at the same retrieves the same result set to reflect the changes.
time. Transactional concurrency is impacted when a Between the execution of these two queries, another user
transaction trying to modify the data prevents other updates the original table. When the user queries the table
transactions from reading the data. for the second time, the data is changed. This leads to
confusion.
Phantom Reads An intent (I) lock, by its functionality, indicates that SQL
A phantom read is also known as the phantom problem. Server wants to acquire a shared or exclusive lock on
This problem occurs when new records inserted by a user some of the resources lower in the hierarchy. For example,
are identified by transactions that started prior to the when a shared intent lock is implemented at the table
INSERT statement. For example, in a ticket reservation level, a transaction will place shared locks on pages or
application, a user, User 1, starts a transaction and queries rows within that table.
the available seats. The query returns a value X. Then, the Implementing an intent lock at the table level ensures that
transaction tries to reserve the X seats. Simultaneously, no other transaction can subsequently acquire an exclusive
another user, User 2, reserves the X-2 seats. When the lock on the table containing that page. SQL Server
transaction of User 1 tries to reserve X seats, the required examines the intent locks only at the table level to
number of seats is unavailable. determine if a transaction can safely acquire a lock on that
Locking in SQL Server table. Therefore, you need not examine every row or page
SQL Server implements multi-granular locking, which lock on the table to determine whether a transaction can
allows transactions to lock different types of resources at lock the entire table.
different levels. To minimize the effort on locking, SQL Intent locks with their diversified features include Intent
Server automatically locks resources at a level appropriate Shared (IS), Intent Exclusive (IX), and Shared with Intent
to the transaction, for example, row level or data page Exclusive (SIX) locks.
level. For transactions to access resources, SQL Server Schema Locks
resolves a conflict between the concurrent transactions by A schema lock (SL) is used when a schema dependent
using lock modes. SQL Server uses the following lock operation is performed on a table. SQL Server considers
modes: schema modification (Sch-M) locks when any DDL
 Shared locks operation is performed on a table. However, SQL Server
 Exclusive locks considers schema stability (Sch-S) locks while compiling
 Update locks queries. An Sch-S lock does not block other locks
 Intent locks including the exclusive (X) locks. Therefore, other
 Schema locks transactions including those with exclusive (X) locks on a
 Bulk update locks table can run while a query is being compiled.
Shared Locks Bulk Update Locks
Shared (S) locks, by their functionality, allow concurrent A bulk update lock (BU) secures your table from any other
transactions to read a resource. If there are any shared normal T-SQL statement, but multiple BULK INSERT
locks on a resource, no other transaction can modify the statements or a bulk copy program can be performed at the
data on that resource. A shared lock releases the resource same time.
after the data has been read by the current transaction. Controlling Locks
Exclusive Locks Locks are implemented automatically in SQL Server. By
Exclusive (X) locks, by their functionality, exclusively default, SQL Server locks every row that you query.
restrict concurrent transactions from accessing a resource. Sometimes, when you query a large record set, locks can
No other transaction can read or modify the data locked grow from rows to data pages and further to table levels. If
with an exclusive lock. the query you are executing takes time to execute, it will
Update Locks prevent other users from accessing the database objects.
An update (U) lock falls in between a shared and an This results in the lack of concurrency in the database. In
exclusive lock. For example, to update all the products addition, you might need to change the lock mode from a
with a price more that $10, you can run an UPDATE normal shared lock to an exclusive lock. To resolve such
statement on the table. To determine the records that need problems, you need to use isolation levels.
to be updated, the query will acquire a shared lock on the You can use isolation levels to specify the rights other
table. transactions will have on the data being modified by a
When physical updates occur, your query acquires an transaction. SQL Server supports the following types of
exclusive lock. In the time gap between the shared and the isolation levels:
exclusive lock, any other transaction might change the  READ UNCOMMITTED
data that you are going to update. Therefore, an update  READ COMMITED
lock can be acquired. An update lock is applied to the table  REPEATABLE READ
along with a shared lock, which prevents other  SNAPSHOT
transactions from updating the table until the update is  SERIALIZABLE
complete. READ UNCOMMITTED
Intent Locks The READ UNCOMMITED isolation level specifies that
a transaction can read the data modified by the current as it places a lock on each statement of the transaction. In
transaction but the modifications have not been committed this isolation level, the concurrency is at the lowest.
yet. Transactions running with this isolation level do not Implementing Isolation Levels
perform a shared lock on the database object, enabling You can implement isolation levels in your transactions by
other transactions to modify the data being read by the using the SET TRANSACTION ISOLATION LEVEL
current transaction. The database objects are also not statement before beginning a transaction.
blocked by the exclusive locks enabling other transaction The syntax of the SET TRANASCTION ISOLATION
to read the data being modified but not committed by the LEVEL statement is:
current transaction. SET TRANSACTION ISOLATION LEVEL { READ
When this level is set, the transaction can read the UNCOMMITTED | READ COMMITTED |
uncommitted data, resulting in the dirty read problem. It is REPEATABLE READ | SNAPSHOT |
the least safe isolation level. SERIALIZABLE } [ ; ]
READ COMMITED BEGIN TRANSACTION
The READ COMMITED isolation level specifies that a COMMIT TRANSACTION
transaction cannot read the data that is being modified by For example, while updating the records of an employee,
the current transaction. This prevents the problem of dirty you do not want any other transaction to read the
read. uncommitted records. For this, you can use the following
This isolation level places an exclusive lock on each statements:
UPDATE statement in the current transaction. When this SET TRANSACTION ISOLATION LEVEL
isolation level is set, other transactions can update the data READ COMMITTED
that has been read by the current transaction. This results BEGIN TRANSACTION TR
in a problem of phantom read. BEGIN TRY
It is the default isolation level in SQL Server. UPDATE Person.Contact
REPEATABLE READ SET EmailAddress='[email protected]'
The REPEATABLE READ isolation level specifies that a WHERE ContactID = 1070
transaction cannot read the data that is being modified by UPDATE HumanResources.EmployeeAddress
the current transaction. In addition, no other transaction SET AddressID = 32533
can update the data that has been read by the current WHERE EmployeeID = 1
transaction until the current transaction completes. COMMIT TRANSACTION TR
This isolation level places an exclusive lock on each PRINT 'Transaction Executed'
UPDATE statement within the current statement. In END TRY
addition, it places a shared lock on each SELECT BEGIN CATCH
statement. ROLLBACK TRANSACTION TR
PRINT 'Transaction Rollbacked'
When this isolation level is set, other transactions can
END CATCH
insert new rows, which result in a phantom read.
The preceding statements sets the isolation level of
SNAPSHOT transaction "TR" as READ COMMITTED. This prevents
The SNAPSHOT isolation provides every transaction with other transactions from reading the uncommitted updates
a snapshot of the current data. Every transaction works in the tables.
and makes changes on its own copy of the data. When a
Consider another example. While reading records from the
transaction is ready to update the changes, it checks
EmployeePayHistory table, you do not want any other
whether the data has been modified since the time it
transaction to update the records until the current
started working on the data and decides whether to update
transaction completes its execution. For this, you can write
the data.
the following statements:
The ALLOW_SNAPSHOT_ISOLATION database option USE AdventureWorks
must be set to ON before you can start a transaction that GO
uses the SNAPSHOT isolation level. If a transaction using SET TRANSACTION ISOLATION LEVEL
the SNAPSHOT isolation level accesses data in multiple REPEATABLE READ;
databases, the ALLOW_SNAPSHOT_ISOLATION must GO
be set to ON in each database. BEGIN TRANSACTION
SERIALIZABLE GO
The SERIALIZABLE isolation level specifies that no SELECT * FROM
transaction can read, modify, or insert new data while the HumanResources.EmployeePayHistory
data is being read or updated by the current transaction. GO
This is the safest isolation level provided by SQL Server SELECT * FROM
HumanResources.Department; Setting Deadlock Priority
GO SQL Server provides the SET DEADLOCK_PRIORITY
COMMIT TRANSACTION statement to customize deadlocking. Setting
GO DEADLOCK_PRIORITY as LOW for a session causes a
The preceding statements set the isolation level of the particular session to be chosen as the deadlock victim. The
transaction as REPEATABLE READ. This prevents other DEADLOCK_PRIORITY option controls how the
transactions from updating the records untill the current particular session reacts in a deadlock.
transaction completes. However, new records can be The syntax of the DEADLOCK_PRIORITY statement is:
inserted. SET DEADLOCK_PRIORITY {LOW | NORMAL |
@deadlock_var}
where,
LOWis used to specify that the current session is the
preferred deadlock victim.
NORMALis used to specify that the session returns to the
default deadlock-handling method.
@deadlock_varis a character variable with a length of
three charactersfor string of low priority (LOW) and six
characters for string of normal priority (NORMAL). It
also specifies the deadlock-handling method.

The periodic detection mechanism of SQL Server


reduces the overhead of deadlock detection because
deadlocks affect only a small number of transactions.
Customizing Lock Timeout
When a transaction attempts to lock a resource, which is
already held by another transaction, SQL Server informs
the first transaction of the current availability status of the
Resolving Deadlocks resource. If the resource is locked, the first transaction is
A deadlock is a situation where two or more transactions blocked, waiting for that resource. If there is a deadlock,
have locks on separate objects, and each transaction waits SQL Server terminates one of the participating
for a lock on the other object to be released. Deadlocks are transactions. In case a deadlock does not occur, the
dangerous because they decrease the concurrency and requesting transaction is blocked until the other
availability of the database and the database objects. The transaction releases the lock. By default, SQL Server does
following figure displays the deadlock between two not enforce the timeout period.
objects. The SET LOCK_TIMEOUT statement can be used to set
the maximum time that a statement waits on a blocked
resource. After LOCK_TIMEOUT is set, when a
statement has waited longer than the LOCK_TIMEOUT
setting, SQL Server automatically cancels the waiting
transaction. The syntax of LOCK_TIMEOUT is:
SET LOCK_TIMEOUT [timeout_period]
where,
timeout_period is represented in milliseconds and is
the time that will pass before SQL Server returns a locking
error for a blocked transaction. You can specify a value of
The Deadlock Between Two Objects
1 to implement default timeout settings.
In the preceding figure, Transaction A has locked the
DISTRIBUTOR table and wants to lock the PRODUCTS Detecting Deadlocks
table. Transaction B has locked the PRODUCTS table and In order to detect deadlock situations, SQL Server scans
wants to lock the DISTRIBUTOR table. This results in a for sessions that are waiting for a lock request. SQL
deadlock as both the transactions wait for the other Server, during the initial scan, marks a flag for all the
transaction to release the table. Since no lock will be waiting sessions. When SQL Server scans the sessions for
released, this results in a deadlock. the second time, a recursive deadlock search begins. If any
circular chain of lock requests is found, SQL Server
cancels the least expensive transaction and marks that
transaction as the deadlock victim.
With the intelligent use of a deadlock scan for sessions,
SQL Server ends a deadlock by automatically selecting the
user who can break the deadlock as the deadlock victim.
In addition, after rolling back the deadlock victim's
transaction, SQL Server notifies the user's application
through error message number 1205.
Using sys.dm_exec_requests
The sys.dm_exec_requests system view returns
information about each transaction that is executing within
SQL Server. This view can be used to detect the
transaction that is causing the deadlock. You can query
this view by using the following query:
SELECT * FROM sys.dm_exec_requests
The following figure shows the output of the preceding
query.

The Output Derived by Using sys.dm_exec_requests


The output shows the list of all the transactions currently
running on the server. In addition, it shows the status of all
the transactions, which includes the session_id, status, and
the owner.
Avoiding Deadlocks by Using Update
Locks
When two concurrent transactions acquire shared mode
locks on a resource, and then attempt to update the data
concurrently, one transaction attempts conversion of the
lock to an exclusive lock. In such a scenario, the
conversion from a shared mode to an exclusive lock must
wait. This is because the exclusive lock for one transaction
is not compatible with the shared mode lock of the other
transaction. Therefore, a lock wait occurs.
The second transaction modifies the data and attempts to
acquire an exclusive lock. Under these circumstances,
when both the transactions are converting from shared to
exclusive locks, a deadlock occurs because each
transaction is waiting for the other transaction to release
its shared mode lock. Therefore, update locks are used to
avoid this potential deadlock problem. SQL Server allows
only one transaction to obtain an update lock on a resource
at a time. The update lock is converted to an exclusive
lock if a transaction modifies a resource. Otherwise, the Activity 8.2: Implementing
lock is converted to a shared mode lock.
Transactions
Server 2012 Programming en-us/library/
Summary by Paul Atkinson and Robert ms189799.aspx
In this chapter, you learned that: Vieira
 A trigger is a block of code that constitutes a set
of T-SQL statements that are activated in Implementing Transactions
response to certain actions.
 SQL Server supports the following triggers: Reference Reading: Books Reference Reading: URLs
 DML triggers Professional Microsoft SQL http://msdn.microsoft.com/
 DDL triggers Server 2012 Administration en-us/library/
 You can alter and delete a trigger. by Adam Jorgensen, Steven ms174377.aspx
 SQL Server provides the DISABLE TRIGGER Wort, and Ross LoForte
statement to disable an existing trigger.
 SQL Server provides the ENABLE TRIGGER
statement to enable an existing trigger.
 SQL Server provides the EVENTDATA()
function that can be embedded with the CREATE
TRIGGER statement to provide the information,
such as time and type of the event that caused the
trigger to fire.
 Transactions are used to execute a sequence of
statements together as a single logical unit of
work.
 Every transaction possesses the ACID property.
 SQL Server supports the following transactions:
 Autocommit transaction
 Implicit transaction
 Explicit transaction
 Locks are used to maintain transactional integrity.
 In the absence of locking, the following problems
may occur if multiple transactions use the same
data from a database at the same time:
 Lost updates
 Uncommitted dependency
 Inconsistent analysis
 Phantom reads
 SQL Server supports the following lock modes:
 Shared locks
 Exclusive locks
 Update locks
 Intent locks
 Schema locks
 Bulk update locks
 A deadlock is a situation where two users (or
transactions) have locks on separate objects, and
each user wants to acquire a lock on the other
user's object.

Reference Reading
Implementing Triggers

Reference Reading: Books Reference Reading: URLs


Beginning Microsoft SQL http://msdn.microsoft.com/
individual T-SQL statements or transactions. This tool is
used by business application developers to identify the T-
SQL statements or stored procedures that slow down the
Chapter 9 performance of the server.
To enable server monitoring, SQL Server Profiler tracks
Monitoring and Optimizing the events that occur in the database engine. An event is an
action generated within an instance of SQL Server, such as
Performance execution of T-SQL statements, start or end of stored
With an increase in the size of a database or the number of procedures, or error returned by the database engine. An
users, the performance of the database server might get event can also include locks acquired or released by the
affected. An important task of a database administrator is database objects.
to monitor the performance of the database server in terms While monitoring the performance, you need to create a
of the time taken in responding to user queries or trace and specify the type of events you need to track. A
generating reports. trace is a type of template that contains the details of the
In addition to monitoring performance, a database events to be monitored. SQL Server Profiler uses a trace to
administrator is responsible for the security of data in the store the details of the events you need to monitor.
database. Many users connect to the database server and Creating, Configuring, and Starting a
make changes to the data stored in the database. The Trace
details regarding who accessed the database and what While creating a trace, you can specify the events and the
changes have been made are important for the security and values for the events that you need to monitor. For
integrity of data. example, you might need to monitor only those events for
This chapter discusses the ways of monitoring and which the CPU time is greater than or equal to 100
optimizing the performance of a database server by using milliseconds. Similarly, you can also monitor the events
the tools provided by SQL Server. only for selected logins. To specify the values for which
you want to monitor the events, you can apply filters.
Objectives If you need to monitor the same set of events regularly,
In this chapter, you will learn to: you can store the trace settings in a template. SQL Server
 Monitor performance Profiler supports the following types of templates:
 Optimize performance  Default template
 Custom template
Default Template
Monitoring Performance The default template is the template shipped with SQL
Server Profiler. Under the default template, SQL Server
One of the important activities of a database administrator
captures typical values from a trace, such as start time, end
is to monitor the performance of the database server. The
time, and login name.
performance of a database server is measured by the time
and resources consumed in responding to queries of the Custom Template
users. An administrator should regularly monitor the In addition to the default template, SQL Server Profiler
performance of a database server and implement allows the database administrators to create their own
appropriate solutions to optimize it. SQL Server provides templates. You can select the columns and values to be
various tools to monitor and optimize performance. included in the trace.
Consider an example. Robert, a database developer at
Adventure Works, Inc. has notified the database
Monitoring Performance by Using administrator that the queries being executed from his
computer are taking longer than usual. The database
SQL Server Profiler administrator has decided to trace the queries being
While monitoring performance of a server, an executed from the computer used by Robert. In addition,
administrator needs to check for the events occurring on the database administrator will need to trace the queries in
the server. These events include the execution of T-SQL future. Therefore, the database administrator needs to
statements or a change in the database properties. create a template so that it can be reused whenever
SQL Server Profiler provides a graphical user interface to required.
monitor the life cycle of the transactions being executed To monitor the activities of users, the database
on a particular instance of the database engine. You can administrator needs to perform the following tasks:
track the login details of users, or the execution of 1. Create a template.
2. Create and run a trace.
various I/O sys.dm_io_pendin
Task 9.1: Creating a Template operations, such g_io_requests
as backup and sys.dm_io_cluster
restore. _shared_drives
Task 9.2: Creating and Running sys.dm_io_virtual_
files_stats
a Trace Database Check the details sys.dm_db_mirrori
You can view the selected events in the trace file as they mirroring-related about the ng_connections
occur in the database server. In addition, the trace is stored DMVs mirroring sys.dm_db_mirrori
in the file. This file can be used later to analyze the connections ng_auto_page_rep
performance of the server. You can also correlate the event available on a air
details stored in this trace file with the performance data server.
logged by the System Monitor tool. Query Check the details sys.dm_qn_subscri
notifications- about active query ptions
related DMVs notification
Monitoring Performance by Using subscriptions on
DMVs the server.
Database-related Check the details sys.dm_db_file_sp
When monitoring the performance of a server, you might DMVs about the database ace_usage
also need to check the state of the server at any given point state present in sys.dm_db_session
in time. The state of the server can be in terms of the SQL Server, such _space_usage
number of sessions running on the server or the amount of as the session sys.dm_db_partiti
free space available. space or the on_stats
SQL Server provides database administrators with partition space of sys.dm_db_task_s
Dynamic Management Views (DMVs), which return the current pace_usage
server state information. This information can be used to database.
monitor the health of a server instance, diagnose problems, Replication- Check the details sys.dm_repl_articl
and tune performance. The DMVs are used as a tool to related DMVs about the state of es
identify the activities of SQL Server. various objects sys.dm_repl_tranh
The DMVs are a group of views and table-valued related to ash
functions. Some DMVs are applied on the server as a replication, such sys.dm_repl_sche
whole and are stored in the master database. To view these as the list of mas
DMVs, the user must have the VIEW SERVER STATE various database sys.dm_repl_trani
permission. The remaining DMVs are specific to a objects published nfo
particular database, and to view them the user must have in a replication.
the VIEW DATABASE STATE permission. DMVs are Execution-related Provide sys.dm_exec_sessi
defined in the sys schema and the names contain the dm DMVs information ons
prefix to distinguish them from catalog views. For related to the state sys.dm_exec_requ
example, the sys.dm_db_partition_stats DMV can be used of query execution ests
to view the partition statistics. on the server, such sys.dm_exec_sql_t
In SQL Server, DMVs are organized in the various as the current ext
categories, as shown in following table. sessions list and sys.dm_exec_quer
the query y_stats
Name of the Used to DMVs present in execution plans sys.dm_exec_quer
category the category for queries. y_optimizer_info
CLR-related Check the state of sys.dm_clr_appdo sys.dm_exec_conn
DMVs the server with mains ections
regard to the CLR. sys.dm_clr_proper Service Broker- Provide sys.dm_broker_act
ties related DMVs information ivated_tasks
sys.dm_clr_tasks related to the state sys.dm_broker_co
sys.dm_clr_loaded of Service Broker nnections
_assemblies objects on the sys.dm_broker_for
I/O-related DMVs Check the details sys.dm_io_backup server, such as the warded_messages
about the state of _tapes Service Broker sys.dm_broker_qu
connections and eue_monitors Security-related Display sys.dm_audit_acti
the list of Service DMVs information about ons
Broker queues. security measures. sys.dm_cryptograp
Full-text Search- Provide sys.dm_fts_active_ hic_provider_prop
related DMVs information catalogs erties
regarding various sys.dm_fts_crawl_ sys.dm_audit_clas
full-text related angles s_type_map
objects, such as sys.dm_fts_memor sys.dm_cryptograp
currently active y_pools hic_provider_sessi
catalogs and sys.dm_fts_memor ons
available memory y_buffers sys.dm_cryptograp
buffers. hic_provider_algo
SQL Operating Check the sys.dm_os_buffer_ rithms
System-related information about descriptors sys.dm_database_
DMVs the operating sys.dm_os_memor encryption_keys
system resources y_pools sys.dm_cryptograp
that are specific to sys.dm_os_child_i hic_provider_keys
SQL Server. nstances sys.dm_server_au
sys.dm_os_sys_inf dit_status
o Change Tracking- Display sys.dm_tran_com
sys.dm_os_loaded related DMVs transaction mit_table
_modules committed for a
sys.dm_os_tasks table that is
sys.dm_os_memor tracked by SQL
y_clerks Server change
sys.dm_os_worker tracking.
s Change Data Return sys.dm_cdc_log_s
Index-related Provide details sys.dm_db_index_ Capture-related information about can_sessions
DMVs about the state of operational_stats DMVs change data sys.dm_cdc_errors
various indexes sys.dm_db_index_ capture, such as sys.dm_repl_trani
available on SQL physical_stats row for each log nfo
Server. sys.dm_db_index_ scan session in the
usage_stats current database,
Transaction- Provide details sys.dm_tran_activ error encountered
related DMVs about the state of e_snapshot_datab during the change
various ase_transactions data capture log
transactions sys.dm_tran_activ scan session.
currently running e_transactions Extended Events Display sys.dm_xe_map_v
on the server. sys.dm_tran_curre DMVs information about alues
nt_snapshot extended events. sys.dm_xe_session
sys.dm_tran_curre _events
nt_transaction sys.dm_xe_object_
Resource Display status of sys.dm_resource_g columns
Governor DMVs the resource overnor_configura sys.dm_xe_session
governor. tion _object_columns
sys.dm_resource_g sys.dm_xe_objects
overnor_workload sys.dm_xe_session
_groups _targets
sys.dm_resource_g sys.dm_xe_packag
overnor_resource_ es
pools sys.dm_xe_session
s
sys.dm_xe_session
_event_actions
Object-related Return one row for sys.dm_sql_refere following query to execute this DMV:
DMVs each entity in the nced_entities SELECT * FROM sys.dm_exec_requests
current database sys.dm_sql_refere The preceding query displays a list of all the requests
that references ncing_entities passed on the server by various sessions.
another user-
defined entity by
name.

The Categories of DMVs


The syntax to use a DMV is:
SELECT * FROM [DMV_NAME]
where,
DMV_NAME is the name of the DMV you want to view.
For example, you can use the
sys.dm_tran_database_transactions DMV to view the
information about transactions at the database level, as
shown in the following query:
SELECT * FROM
sys.dm_tran_database_transactions
DMVs are the most important tools that the database
administrators use to monitor SQL Server. Some of the
frequently used DMVs are:
 sys.dm_exec_sessions
 sys.dm_exec_connections
 sys.dm_exec_requests
The sys.dm_exec_sessions DMV
This DMV is used to view the authenticated SQL Server
sessions, as shown in the following query:
SELECT * FROM sys.dm_exec_sessions
The preceding query provides a list of all the authenticated
sessions running on a particular server instance.

The information returned from the


sys.dm_exec_sessions DMV can be used to identify a session
or transaction that is affecting the performance. For
example, if a session is using lot of memory space, you can
kill that session by using the KILL statement. The syntax of
the KILL statement is:
KILL
where, <sp_id> is the session ID of an errant session.
The sys.dm_exec_connections DMV
This DMV is used to view the connection information of
all the sessions currently connected to SQL Server. The
details include the IP address and the session ID of the
client. You can use the following query to execute this
DMV:
SELECT * FROM sys.dm_exec_connections
The preceding query provides the connection details of all
the sessions currently available.
The sys.dm_exec_requests DMV
This DMV is used to view the requests being passed by
various sessions on the server. This DMV can be used to
observe each session on the server. You can use the
Monitoring Performance by Using
Database Engine Tuning Advisor Implementing Statistics
Statistics in SQL Server refers to information that the
Database tuning is one of the most important tasks that a
server collects about the distribution of data in columns
database administrator performs. It involves a set of
and indexes. This data, in turn, is used by the query
activities used to optimize the performance of a database.
optimizer to determine the execution plan for returning
It refers to configuring the database files, the Database
results when you run a query. Statistics is created
Management System (DBMS), and the operating system
and hardware the DBMS runs on. automatically when you create indexes. In addition, SQL
Server creates statistics for columns that do not have
The goal of database tuning is to maximize the use of
indexes defined on them.
system resources. Most systems are designed to manage
SQL Server can automatically create and update statistics.
work efficiently, but it is possible to improve performance
This feature is set to ON by default. For majority of
by customizing settings and configuring the database and
databases and applications, developers and administrators
the DBMS. For example, if your query takes three seconds
rely on the automatic creation and modification of
to execute, you can tune it to return the result in less than
statistics to provide accurate statistics about their data. By
one second.
using SQL Server query optimizer, you can produce
SQL Server provides Database Engine Tuning Advisor to
effective query plans consistently. This also helps in
help the database administrator tune the database.
keeping the development and administration costs low.
Database Engine Tuning Advisor tests the database in
However, if you need to use statistics on columns that are
various conditions by putting a workload on it. Workload
not indexed in order to create more optimal execution
is a set of T-SQL statements that are executed on the
plans, you can manually create and update statistics.
database. The workload can be a trace file, a trace table, or
a file consisting of T-SQL statements. Creating Statistics
Based on the throughput of the queries given in the Statistics can be created on specific columns of a table or
workload, a report is generated containing the current state view by using the CREATE STATISTICS statement. The
of the database objects. In addition, the report includes syntax of the CREATE STATISTICS is:
suggestions to tune the database. The suggestions include CREATE STATISTICS statistics_name
partitioning the table, partitioning the indexes, dropping ON { table | view } ( column
the indexes, or creating new indexes. [ ,...n ] )
For example, if one of your database clients complains [ WITH
about the slow execution of queries, you can record the [ [ FULLSCAN
statements executed by the client in a trace and put them | SAMPLE number { PERCENT |
in the Database Engine Tuning Advisor to resolve the ROWS } ]
issues causing the slowing down of the query [ NORECOMPUTE ] ]
performance. where,
statistics_name is the name of the statistics group
to be created.
Task 9.3: Running the Database table is the name of the table on which the named
Engine Tuning Advisor statistics is to be created.
view is the name of the view on which the named
statistics is to be created.
column is the column or set of columns on which
Optimizing Performance statistics is to be created.
When creating a database, a lot of indexes are created to FULLSCAN specifies that all rows in the table or view
improve the query performance. The performance of should be read to gather the statistics. This option cannot
indexes decreases as the database grows in size. This be used with the SAMPLE option.
results in a decrease in the query processing performance. SAMPLE number { PERCENT | ROWS } specifies
As a database administrator, it is your responsibility to that a percentage or a specified number of rows of data
ensure that the performance of queries does not suffer. For should be read by using random sampling to gather the
this, you should check and regulate the performance of statistics number must be an integer. If PERCENT is
indexes. You can do this by checking the statistics specified, number should be from 0 through 100; if
information. In addition, you can use the Statistics IO to ROWS is specified, number can be from 0 to the total
get information regarding the amount of disk activity number of rows.
generated. NORECOMPUTE specifies that the database engine should
not automatically recompute statistics. [
For example, you can create the ContactEMail statistics on [FULLSCAN ]
the ContactID and EmailAddress columns of the Contact |SAMPLE number { PERCENT |
table of the AdventureWorks database by using the ROWS } ]
following statement: |RESAMPLE
USE AdventureWorks ]
GO [ [ , ] [ ALL | COLUMNS |
CREATE STATISTICS ContactEMail INDEX ]
ON Person.Contact (ContactID, [ [ , ] NORECOMPUTE ]
EmailAddress) ]
GO where,
You can view the list of all the statistics being maintained table | view is the name of the table or indexed
on a table by using the sp_helpstats system stored view for which the statistics is to be updated.
procedure. For example, you can view all the statistics on index is the index for which statistics are being updated.
the Person.Contact table by using the following statement: statistics_name is the name of the statistics group
sp_helpstats 'Person.Contact', 'ALL' (collection) to update.
You can also view the details of an individual statistics by FULLSCAN specifies that all rows in the table or view
using the DBCC SHOW_STATISTICS statement, as should be read to gather the statistics.
shown in the following statement: SAMPLE number { PERCENT | ROWS } specifies
DBCC SHOW_STATISTICS the percentage of the table or indexed view, or the number
('Person.Contact', AK_Contact_rowguid) of rows to sample when collecting statistics for larger
The preceding statement displays the information for the tables or views.
AK_Contact_rowguid statistics on the Person.Contact RESAMPLE specifies that statistics will be gathered by
table. using an inherited sampling ratio for all existing statistics
including indexes.
By default, the AUTO_CREATE_STATISTICS
ALL | COLUMNS | INDEX specifies whether the
database option is set as ON. As a result, the database engine UPDATE STATISTICS statement affects column
automatically creates statistics for columns without indexes statistics, index statistics, or all existing statistics.
that are used in the WHERE clause. NORECOMPUTE specifies that statistics that become out
of date are not automatically recomputed.
Updating Statistics For example, you can update the distribution statistics for
The query optimizer determines when to update the all indexes on the Person.Contact table by using the
statistics. In some cases, you need to update the statistics following statements:
more frequently than automatically updated by the query USE AdventureWorks
optimizer. For example, the SalesDetail table contains the GO
details of sales transactions. The data in this table is huge. UPDATE STATISTICS Person.Contact
Every day, lot of records are inserted or updated in this GO
table. Due to huge data in the table, it takes too long to The following statement updates only the distribution
retrieve the data. In this case, you need to update the information for the AK_Contact_rowguid index of the
statistics manually to make the query optimizer use the Person.Contact table:
updated statistics to enhance query performance. UPDATE STATISTICS Person.Contact
Statistics can be updated by using the UPDATE AK_Contact_rowguid
STATISTICS statement. You can update the information
about the distribution of key values for one or more
statistics groups in the specified table or indexed view. Sampling the data, instead of analyzing all the data,
The syntax of the UPDATE STATISTICS statement is: minimizes the cost of automatic statistical update. You can
UPDATE STATISTICS table | view control the amount of data sampled during manual statistics
[ updates on a table-by-table basis by using the SAMPLE and
{ FULLSCAN clauses of the UPDATE STATISTICS statement.
{ index | statistics_name }
| ( { index | Statistics can also be created on all eligible columns in
statistics_name } [ ,...n ] ) all user tables in the current database in a single statement
} by using the sp_createstats system stored procedure.
]
[WITH
In the preceding scenario, you can use the plan guides to
optimize the performance of such queries. The plan guides
allow you to attach query hints or a fixed query plan with
the query to optimize its performance. You can attach the
query hints by using the OPTION clause. Otherwise, you
can attach a specific query plan with the query to optimize
its performance. When the query executes, the OPTION
clause of the plan guide that matches the query is attached
to it for execution, or it uses the specified query plan.
The following types of plan guides can be created:
 OBJECT: This plan guide matches the query that
executes in the context of stored-procedures,
scalar user-defined functions, multi-statement
table-valued user-defined functions, and DML
triggers.
 SQL: This plan guide matches the query that
executes in the context of a stand-alone T-SQL
Statistics IO statement and batches that are not part of any
In some cases, you need to know about the statistics
database object like a procedure or a function.
information for the T-SQL statement. For example, you
 TEMPLATE: This plan guide matches the query
are retrieving the sales records from the SalesDetail table.
that executes in the context of parameterized T-
You want to know about the amount of logical reads,
SQL statements or batches. A parameterized
physical reads and scan counts generated by the query.
query allows you to substitute the literal values
In this case, you can use the Statistics IO to display contained in a query with the parameters provided
information regarding the amount of disk activity at the time of execution.
generated by T-SQL statement. The syntax of statistics IO The sp_create_plan_guide statement is used to create the
is: query plan. The syntax of the sp_create_plan_guide
SET STATISTICS IO { ON | OFF } statement is:
where, sp_create_plan_guide [ @name = ]
{ ON | OFF } specifies that the statistics information N'plan_guide_name'
is displayed when the STATISTICS is ON and the , [ @stmt = ] N'statement_text'
statistics information is not displayed when STATISTICS , [ @type = ] N'{ OBJECT | SQL |
is OFF. TEMPLATE }'
For example, you can get the disk information on the , [ @module_or_batch = ]
Person.Address table by using the following statements: {
USE AdventureWorks N'[ schema_name. ]
GO object_name'
SET statistics IO on | N'batch_text'
select * from person.address where | NULL
city='bothell' }
SET STATISTICs IO off , [ @params = ] { N'@parameter_name
GO data_type [ ,...n ]' | NULL }
The preceding statements displays the disk information of , [ @hints = ] { N'OPTION ( query_hint
the Person.Contact table. [ ,...n ] )'
| N'XML_showplan'
| NULL }
Implementing Plan Guides where,
Consider a scenario where you are working as a database [ @name = ] N'plan_guide_name' is the name
administrator at DBM Technologies. The company works of the plan guide.
with many third-party vendors. These vendors often [ @stmt = ] N'statement_text' is a T-SQL
execute some of their queries on the database application statement against which query plans need to be created.
of the company. Some queries of third-party vendors are [ @type = ] N'{ OBJECT | SQL |
not performing as expected. Moreover, you do not have TEMPLATE }' is the context for matching the SQL
the permission to change the query text to optimize the statement to the plan_guide name.
performance of these queries. [ @module_or_batch = ]
{ N'[ schema_name. ] object_name' | = N''Bothell''))'
N'batch_text' | NULL } is the name of an object After creating the preceding plan guide, Plan1, when the
or a batch in which the query appears. query specified in the sp_create_plan_guide
[ @params = ] { N'@parameter_name statement executes, the query is modified to include the
data_type [ ,...n ]' | NULL } specifies the OPTIMIZE FOR (@City = N''Bothell'')
definitions of all the parameters embedded in the query clause for optimizing the query.
statement.
[ @hints = ] { N'OPTION ( query_hint
[ ,...n ] )' | N'XML_showplan' | Activity 9.1: Monitoring the
NULL } specifies the OPTION clause to attach to the Database
query. The OPTION clause specifies the query hints to be
attached.
Consider the following stored procedure:
CREATE PROCEDURE Tracking Data Changes
HumanResources.GetEmployeeByCity In an organization, tables are created to store the details of
(@City varchar(20)) entities, such as employees, customer, and sales. The data
AS in these tables is changed frequently by inserting,
BEGIN updating, or deleting the records. Sometimes, it is required
SELECT * FROM HumanResources.Employee to track the changes made on these tables to view the
E, HumanResources.EmployeeAddress EA, historical data. For example, an employee is shifted to
Person.Address PA another department. For this, you need to update the
Where PA.AddressID=EA.AddressID
department details of that employee in the table. However,
AND EA.EmployeeID=E.EmployeeID
you also want to retain the previous department details of
AND City = @City
the employee as well in a separate table. For this, you need
END
to track the changes made in the Employee table.
The preceding stored procedure takes the @City
SQL Server provides functionality to track data changes
parameter and returns the records of those employees who by using Change Data Capture (CDC) and change tracking
live in the specified city. methods. CDC provides detailed information about the
Suppose, the preceding stored procedure is optimized for data that got changed in the table. It provides you with the
@City = 'Portland'. However, only a few details of the historical data as well as the updated data.
employees live in Portland. The performance suffers when However, change tracking only enables you to capture the
the query executes for other cities in which more information that the data in the table has changed.
employees live. As most of the employees live in the
Bothell city, a query plan that is created for @City =
'Bothell' will optimize the query. Using CDC
The OPTIMIZE FOR query hint can be used to instruct
the query optimizer to use a specific value for a local Data in tables is changed when the DML statements are
variable when the query is compiled and optimized. executed in the database for inserting, updating, or
Consider the following plan guide to optimize the stored deleting records. SQL Server provides the CDC method to
procedure, GetEmployeeByCity for track the changes made by the DML statements. For
example, if you perform an update operation on a table,
@City='Bothell':
CDC will provide you with the data before and after the
EXEC sp_create_plan_guide
update operation.
@name = N'Plan1',
@stmt = N'SELECT * FROM To use CDC to track changes, you need to perform the
HumanResources.Employee E, following steps:
HumanResources.EmployeeAddress EA,  Enable CDC on a database.
Person.Address PA  Enable CDC on a table.
Where PA.AddressID=EA.AddressID  Track changes.
AND EA.EmployeeID=E.EmployeeID
AND City = @City', If you enable CDC on an existing table, its database
@type = N'OBJECT', schema does not change. The table must have a primary key
@module_or_batch = before applying CDC method.
N'HumanResources.GetEmployeeByCity',
@params = NULL, Enabling CDC on a Database
@hints = N'OPTION (OPTIMIZE FOR (@City Before tracking the changes made by the DML statements,
you need to enable CDC on the database by executing the For example, to enable CDC on the
sp_cdc_enable_db stored procedure. For example, to HumanResources.Employee table, you need to execute the
enable CDC on the AdventureWorks database, you need to following statement:
execute the following statements: EXEC sys.sp_cdc_enable_table
USE AdventureWorks @source_schema= 'HumanResources',
EXEC sys.sp_cdc_enable_db @source_name= 'Employee',
You can verify whether CDC is enabled by executing the @role_name = 'NULL'
following query: After the HumanResources.Employee table is enabled for
SELECT is_cdc_enabled FROM CDC, a new table named
sys.databases cdc.HumanResources_Employee_CT is created in the
WHERE name = 'AdventureWorks' system tables of the AdventureWorks database. This table
If the value in the is_cd_enabled column is 1, then the will store the details of the DML operations performed on
AdventureWorks database is enabled for CDC. When the HumanResources.Employee table.
CDC is enabled on a database, a new user named cdc, a Tracking Changes
schema named cdc, and the following tables are created in After enabling CDC on the HumanResources.Employee
the CDC-enabled database: table, you can track the changes made in this table. To
 cdc.captured_columns: Contains the details of modify the HumanResources.Employee table, you can
all the columns that are part of the CDC-enabled execute the following statement:
tables. ALTER TABLE HumanResources.Employee
 cdc.change_tables: Contains the information ADD New_Column int NULL;
about which tables have been enabled for CDC. The preceding statement adds a new column to the
 cdc.ddl_history: Contains the details of the DDL HumanResources.Employee table. The details of this
statements executed on the CDC-enabled tables. statement are stored in the cdc.ddl_history table. You can
 cdc.index_columns: Contains the details of the view the details of the preceding statement by executing
indexes associated with the CDC-enabled tables. the following query:
 cdc.lsn_time_mapping: Contains the details of SELECT * FROM cdc.ddl_history
the transactions, such as begin and end time of The following figure displays the output of the preceding
the transaction, performed on the CDC-enabled query.
tables.
All the preceding tables are created under the System
Tables folder of the CDC-enabled database in the Object
Explorer window.
Enabling CDC on a Table
After enabling CDC on the AdventureWorks database, you The cdc.ddl_history Table
need to enable it on the table for which you want to
capture data changes. The sp_cdc_enable_table stored
procedure is used to enable CDC on a table. The syntax of Using Change Tracking
sp_cdc_enable_table stored procedure is: You can also use the change tracking method to track the
sys.sp_cdc_enable_table changes made in the tables. However, this method does
[ @source_schema= ] 'source_schema', not provide the information about the historical data. It
[ @source_name= ] 'source_name', only captures the fact that rows in a table were changed,
[ @role_name= ] 'role_name' but does not capture the data that was changed. This
where, enables you to determine which rows have changed in the
[ @source_schema= ] 'source_schema' table. However, you need to query the table itself to
specifies the name of the schema to which the source retrieve the latest data. This method is useful for those
table belongs. applications that just require the information about the
[ @source_name= ] 'source_name' specifies changed rows, and do not require historical data.
the name of the source table on which CDC is to be To use change tracking, you need to perform the following
enabled. steps:
[ @role_name= ] 'role_name' specifies the  Enable change tracking on a database.
name of the database role used to access the changed  Enable change tracking on a table.
data. If you do not specify any role by passing a NULL  Implement change tracking.
value, access to the changed data will be available to
everyone.
You must have dbcreator server role to implement
change tracking on a database. to enable it on tables. For example, you can enable change
Enabling Change Tracking on a tracking on the HumanResources.Employee table by
executing the following statement:
Database ALTER TABLE HumanResources.Employee
Before tracking the changes using the change tracking ENABLE CHANGE_TRACKING
method, you need to enable it on the database by using the You can disable change tracking on the
ALTER DATABASE statement. The syntax of the ALTER HumanResources.Employee table by executing the
DATABASE statement is: following statement:
ALTER DATABASE database_name ALTER TABLE HumanResources.Employee
CHANGE_TRACKING = {ON |OFF} DISABLE CHANGE_TRACKING
[SET AUTO_CLEANUP = {ON | OFF}]
[SET CHANGE_RETENTION = Implementing Change Tracking
retention_period {DAYS | HOURS | After enabling change tracking on a table, you can track
MINUTES}] the changes made in this table.
where, You can view the details of the tables on which track
database_name is the name of the database on which changes have been applied by executing the following
change tracking is enabled. query:
CHANGE_TRACKING option enables or disables change SELECT * from
tracking on the database. If this option is set to ON, the sys.change_tracking_tables
database is enabled for change tracking. However, if set The preceding query uses the sys.change_tracking_tables
to OFF, the database is disabled for change tracking. DMV which returns one row for each change tracking-
SET AUTO_CLEANUP option if set to ON automatically enabled table in the current database. For example, you
removes the change tracking information after the can enable track changing on the Person.Contact table by
specified retention period. However, if this option is set to executing the following statement:
OFF, the change tracking data is not removed from the ALTER TABLE Person.Contact
database. ENABLE CHANGE_TRACKING
SET CHANGE_RETENTION = After this if you execute the preceding SELECT query
retention_period is an integer value to specify the again, the output will be displayed as shown in following
minimum time period for which the change tracking figure.
information is kept in the database. The default retention
period is 2 days. The minimum retention period is 1
minute.
For example, to enable change tracking on the The Output Derived by Enabling Track Changes on Contact
AdventureWorks database, you need to execute the Table
following statement: In the preceding figure, the min_valid_version column
ALTER DATABASE AdventureWorks depicts the minimum valid version of change tracking
SET CHANGE_TRACKING = ON information that is available for the table. The
(CHANGE_RETENTION = 3 DAYS, begin_version column depicts the version of the database
AUTO_CLEANUP = ON) when change tracking began for the table.
In the preceding statement, the retention period is
specified as 3 days. The AUTO_CLEANUP parameter is
set as ON to remove the change tracking after 3 days. You The data in the preceding figure may differ depending
can verify whether change tracking is enabled on the upon the operations performed on the table in the database.
database by using the following query: You can verify the name of the table by executing the
SELECT * FROM following query:
sys.change_tracking_databases SELECT OBJECT_ID, NAME FROM SYS.TABLES
The preceding code uses the WHERE OBJECT_ID = 341576255
sys.change_tracking_databases DMV that displays the The following figure displays the object ID and the name
database ID of the database on which the change tracking of the table on which change tracking is enabled.
method is enabled. Further, you can view the name of the
database by executing the following query:
SELECT name FROM sys.databases where
database_id = 17
The Output Derived by Executing the Preceding Query
Enabling Change Tracking on a Table Then, you can use the CHANGETABLE function to view
After enabling change tracking on the database, you need the changes made to the table. The syntax of the
CHANGETABLE function is:
CHANGETABLE (CHANGES table,
version_number) [AS] table_alias
where,
table specifies the name of the table for which the The Output Derived by Executing the Preceding Query
changed data needs to be retrieved. However, if you want only the changes made after the
version_number specifies the version number. This version number 1, execute the following query:
number specifies the state of the table before performing SELECT * FROM CHANGETABLE (CHANGES
a particular operation on the table. For a single operation Person.Contact, 1) AS CT
performed on a change tracking-enabled table, the version The following figure displays the output of the preceding
number is incremented by 1. For example, after enabling query.
change tracking on a table, the version number of the
table is 0. You inserted a record in the table. This insert
operation changes the version number of the table to 1.
Now, if you perform an update operation, the version
number will be incremented to 2. If you pass 0 as the
version number, you will get all the changes that were The Output Derived by Executing the Preceding Query
done in the table after the 0 version. However, if you pass
1 as the version number, you will get all the changes that Activity 9.2: Tracking Database
were done in the table after the 1 version.
table_alias is used to provide a name for the results Changes
that are returned.
For example, you can execute the following statement to
modify the Person.Contact table: Summary
UPDATE Person.Contact
SET MiddleName = 'S.' In this chapter, you learned that:
WHERE ContactID = 1  Performance of an SQL Server is measured by the
Then, execute the following query: time and resources consumed in responding to
SELECT * FROM CHANGETABLE (CHANGES queries of the users.
Person.Contact, 0) AS CT  An event is any action generated within an
The following figure displays the output of the preceding instance of SQL Server, such as the log on status,
query. execution of T-SQL statements, start or end of
stored procedures, error returned by SQL Server,
or lock acquired or released by an object.
 A trace captures and stores details of events you
need to monitor for an instance of SQL Server.
The Output Derived by Executing the Preceding Query  A template defines the standard set of events to be
In the preceding figure, the SYS_CHANGE_VERSION monitored in a trace.
depicts the current version of the table after performing  DMVs are a set of views and table-valued
the update operation. While retrieving changes from the functions that return server state information to
table by using the CHANGETABLE function, the value of the administrator.
the version number must be greater than or equal to the  The frequently used DMVs are:
version depicted in the min_valid_version column of the  sys.dm_exec_sessions
sys.change_tracking_tables table.  sys.dm_exec_connections
Modify the Person.Contact table again by executing the  sys.dm_exec_requests
following statement:  Database Tuning Advisor is a tool that checks the
UPDATE Person.Contact performance of a workload and suggests how to
SET MiddleName = 'S.' improve the performance of the server.
WHERE ContactID = 2  Statistics in SQL Server refers to information that
Then, again execute the preceding SELECT query, the the server collects about the distribution of data in
output will display all the changes that were done after the columns and indexes.
 SQL Server can automatically create and update
0 version, as shown in the following figure.
statistics. This feature is set to ON by default.
 Statistics can be created on specific columns of a
table or view by using the CREATE STATISTICS
statement.
 Statistics can be updated by using the UPDATE
STATISTICS statement.
 Statistics IO displays information regarding the
amount of disk activity generated by T-SQL
statement.
 SQL Server provides the CDC method to track
the changes made by the DML statements.
 CDC provides the detailed information about the
data that got changed.
 You can use CDC to track changes by performing
the following steps:
 Enabling CDC on a database
 Enabling CDC on a table
 Tracking changes
 Before tracking the changes made by the DML
statements, you need to enable CDC on the
database by executing the sp_cdc_enable_db
stored procedure.
 The change tracking method only captures the
fact that rows in a table were changed, but does
not capture the data that was changed.

Reference Reading
Monitoring Performance

Reference Reading: Books Reference Reading: URLs


Professional Microsoft SQL http://msdn.microsoft.com/
Server 2012 Administration en-us/library/
by Adam Jorgensen, Steven ms189081.aspx
Wort, and Ross LoForte

Optimizing Performance

Reference Reading: Books Reference Reading: URLs


Microsoft SQL Server 2012 http://
Performance Tuning blog.sqlauthority.com/2012/
Cookbook by R. Shah and B. 04/20/sql-server-
Thaker performance-tuning-part-2-
of-2-analysis-detection-
tuning-and-optimizing/

Tracking Data Changes

Reference Reading: Books Reference Reading: URLs


Microsoft SQL Server 2012 http://msdn.microsoft.com/
Bible by Adam Jorgensen, en-us/library/
Jorge Segarra, and Patrick bb933994.aspx
LeBlanc
HTTP is the protocol used for communication over the
Internet.
I
Glossary Index
A An internal table created to speed up queries and searches
Atomicity in a database.
A property of a transaction. It states that either all the data Inserted Table
modifications are performed or none of them. A table that contains a copy of all records that are inserted
Atomicity, Consistency, Isolation, and Durability in the trigger table.
(ACID) Isolation
The four properties that a transaction must posses to work A property of a transaction. It states that any data
together as a single logical unit of work. modification made by concurrent transactions must be
C isolated from the modifications made by other concurrent
Clustered Index transactions.
An index that sorts and stores the data rows in the table Isolation Level
based on their key values. Plan used to specify the rights other transactions will have
Column on the data being modified by a transaction.
Vertical slice of a table. Column is defined to be of a M
single data type. Magic Tables
Composite Index These are the conceptual tables and are similar in structure
An index based on one or more columns. to the table on which the trigger is defined.
Consistency N
A property of a transaction. It states that all the data should Nonclustered Index
be in a consistent state after the transaction is completed. An index in which the logical order of the index does not
Contract match the physical stored order of the rows in a table.
An agreement between the participant applications P
defining the messages that will be exchanged between Parsing
them. The process of compiling and breaking the components of
Correlated Subquery stored procedure into various parts.
A subquery in which the information retrieved by the Population
subquery is referenced by the outer, main query. A The process of storing values in the full-text index.
correlated subquery cannot be stand alone, it depends on Q
the outer query. Qualifier
D A prefix used to identify a column of a particular table.
Deadlock Victim For example, in "Student.sname" Student is the table
The transaction that is canceled by the SQL Server to qualifier.
resolve the deadlock. R
Deleted Table Resolving
A table that contains all records that have been deleted The process of checking the existence of the referred
from the trigger table. objects, such as tables and views.
Durability S
A property of a transaction. It states that any change in Service Program
data by a completed transaction remains permanently in A program that provides logic to the service.
effect in the system. Shredding
E The process of transforming XML data into a rowset.
Exceptions Simple Object Access Protocol (SOAP)
The errors that occur at run time. A standard communication protocol to interchange
Execution Plan information in a structured format within a distributed
The SQL Server compiles the statements of a batch into a environment.
single executable unit called an execution plan while Stopwords
executing batches. Words that are used in a search, but are excluded from the
H search string such as a, an, the, and are.
Hyper Text Transfer Protocol (HTTP) Stored Procedure
A precompiled object stored in the database.
T
Timeout
The time period for which a transaction waits for the lock
to be released on a blocked resource.
U
User-Defined Functions (UDF)
A user-defined database object that contains a set of T-
SQL statements, accepts parameters, performs an action,
and returns the result of that action as a value.
V
View
A virtual table that provides access to a subset of columns
from one or more tables.
X
XML Index
An index that is created on columns storing XML data
values.
created by using XML. This tag is used to store the name
of the employee.
Elements
Appendix Elementsare the basic units that are used to identify and
describe data in XML. They are the building blocks of an
Extensible Markup Language (XML) XML document. Elements are represented by using tags.
XML allows you to provide meaningful names to
XML is a markup language that is used to describe the
elements, which helps improve the readability of the code.
structure of data in a standard hierarchical manner. The
Meaningful element names also enable easy identification
structure of the documents containing data is described
of the element content. For example, an Authorname
with the help of tags contained in the document. An XML
document is attached to a Document Type Definition element can be created for an application. Consider the
(DTD) or XML Schema that describes its structure. following code snippet:
<Authorname>John Smith</Authorname>
Components of an XML Document In the preceding code snippet, the Authorname element is
used to store the names of authors. In this case, the
An XML document is composed of a number of element name provides a description of the content within
components that can be used to represent information in a the tags. The Authorname element is represented by using
hierarchical order. These components are: the <Authorname> and </Authorname> tags, and
 Processing Instruction the author name is enclosed between these tags.
 Tags An XML document must always have a root element. A
 Elements root element contains all other elements in the document.
 Content Consider the following code snippet:
 Attributes <?xml version=“1.0”?>
 Comments <AUTHORS>
Processing Instruction <AUTHOR>
An XML document usually begins with the XML <FIRSTNAME> John </FIRSTNAME>
declaration statement also called the Processing <LASTNAME> Norton </LASTNAME>
Instruction (PI). The PI provides information regarding the </AUTHOR>
way in which the XML file should be processed. The PI </AUTHORS>
statement can be written as shown in the following code In the preceding code snippet, the AUTHORS element
snippet: contains all other elements in the XML document and is
<?xml version="1.0" encoding="UTF-8"?> therefore called the root element. An XML document can
In the preceding code snippet, the PI states that XML contain only one root element and all other elements are
version 1.0 is used. embedded within the opening and closing tags of the root
element.
Tags
Tags are used to specify a name for a given piece of Content
information. It is a means of identifying data. Data is The information that is represented by the elements of an
marked-up by using tags. A tag consists of opening and XML document is referred to as the content of that
closing angular bracket (<>). These brackets enclose the element. For example, consider the following code
name of the tag. Tags usually occur in pairs. Each pair snippet:
consists of a start tag and an end tag. The start tag only <BOOKNAME>The Painted House</BOOKNAME>
contains the name of the tag while the end tag includes a In the preceding code snippet, the name of the book The
forward slash (/) before the name of the tag. Consider the Painted House is the content of the BOOKNAME
following code snippet: element.
<P>Nick Shaw</P> Elements can contain only textual information. Such
In the preceding code snippet, <P> is a predefined HTML elements are said to have character or data content.
tag or mark-up, which encloses the name of an employee. Consider the following code snippet:
Here, <P> is the start tag and </P> is the end tag. As <BOOKNAME>The Painted House</BOOKNAME>
XML allows you to create your own tags, the same In the preceding code snippet, the BOOKNAME element
information can be stored as shown in the following code contains only textual information and is therefore said to
snippet: have character or data content.
<EMP_NAME>Nick Shaw</EMP_NAME> Attributes
In the preceding code snippet, <EMP_NAME> is a new tag Attributes provide additional information about the
elements for which they are declared. An attribute consists the code.
of a name-value pair. Consider the following code snippet: Comments are created by using an opening angular
<PRODUCTNAME PRODID="P001">Barbie bracket followed by an exclamation mark and two
Doll</PRODUCTNAME> hyphens (<!--). This is followed by the text that comprises
In the preceding code snippet, the element the comment. The comment entry can be closed by using
PRODUCTNAME has an attribute called PRODID. The two hyphens followed by a closing angular bracket (-->).
value of this attribute is set to P001. The attribute name The following code snippet illustrates the use of a
and the attribute value are specified within the opening tag comment in an XML document:
of the PRODUCTNAME element. <!--PRODUCTDATA is the root element-->
Elements can have one or more attributes. Attributes or The text contained within a comment entry cannot have
attribute values can be either mandatory or optional. two hyphens that occur consecutively, as shown in the
When you create the structure of an XML document, you following code snippet:
must decide whether a specific piece of information is to <!--PRODUCTDATA is the --root
be represented as an element or an attribute. In general, an element-->
element is used to represent a definable unit. An attribute This is an invalid comment because the text enclosed by
is used to represent data that further qualifies the element. the opening and closing tags includes two consecutive
For example, an element called font could have an hyphens.
attribute called color that is used to specify the color of
the font. In this case, the color attribute further qualifies Defining the Structure of an XML
the font element. Therefore, color is represented as an Document
attribute and not as an element.
To represent data in a consistent format, it needs to be
You may decide to represent information either by using
given a meaningful structure. A well-formed document in
elements or attributes. There are no rules governing this
XML may not necessarily have a meaningful structure.
decision. However, you may consider the following
Anyone can create a well-formed structure, but this
guidelines while deciding whether to represent
structure will be specific only to the XML document in
information by using an element or an attribute:
which it is created. It cannot be applied consistently across
 If the data must be displayed, you can represent it
multiple documents.
as an element. In general, element attributes are
By defining the role of each element in a formal model,
used for intangible, abstract properties such as ID.
users of XML can ensure that each component of the
 If the data must be updated frequently, it is better
document appears in a valid place in the XML document.
represented as an element because it is easier to
DTD or XML Schemas can be used to define the structure
edit elements than attributes with XML editing
of an XML document.
tools. For example, in the case of products, the
quantity on hand needs to be updated when a Document Type Definition
transaction takes place. Therefore, you can A DTD defines the structure of the content of an XML
represent the quantity by using an element. document, thereby allowing you to store data in a
 If the value of a piece of information must be consistent format. It specifies the elements that can be
checked frequently, it may be represented as an present in the XML document, attributes of these
attribute. This is because an XML processor can elements, and their arrangement with relation to each
check the content of an attribute value more other. A DTD also allows you to specify whether an
easily than it can check the content of an element. element is optional or mandatory.
For example, you often retrieve details about Creating a DTD is similar to creating a table in a database.
products based on their IDs and categories. In DTDs, you specify the structure of the XML document
Therefore, you can represent product ID and by declaring elements to denote the data. This is similar to
category as attributes. creating columns in a table. You can also specify whether
Comments providing a value for the element is mandatory or optional.
Comments are statements that are used to explain the You can then store the data in an XML document that
code. They are also used to provide documentation conforms to the DTD for that application. This is similar
information about an XML file or even the application to to adding records in a table.
which the file belongs. When the code is executed, XML allows you to create your own DTDs for
comment entries are ignored by the parser. applications. This gives you complete control over the
Comments are not essential in an XML file. However, it is process of checking the content and the structure of XML
good programming practice to include comments along documents created for an application. The process of
with the code. This ensures that you can easily understand checking is called validation. XML documents that
conform to a DTD are considered valid documents. For example, in the preceding code, the statement
The following code is a sample XML DTD for the <xsd:schema xmlns:xsd="http://www.w3.org/2001/
PRODUCTDATA data structure: XMLSchema"> specifies that xsd will be used as a prefix
<!ELEMENT PRODUCTDATA (PRODUCT)+> to identify the elements that are defined at the location
<!ELEMENT PRODUCT (PRODUCTNAME, http://www.w3.org/2001/XMLSchema. This is the location
DESCRIPTION, PRICE, QUANTITY)> where the schema instructions are defined by the World
<!ELEMENT PRODUCTNAME (#PCDATA)> Wide Web Consortium (W3C).
<!ELEMENT DESCRIPTION (#PCDATA)>
<!ELEMENT PRICE (#PCDATA)>
<!ELEMENT QUANTITY (#PCDATA)>
<!ATTLIST PRODUCT PRODUCTID ID
#REQUIRED
CATEGORY (BOOKS | TOYS) "TOYS">
XML Schema
An XML schema is used to define the structure of an
XML document. A schema defines the list of elements and
attributes that can be used in an XML document. In
addition to the list of elements, an XML schema also
specifies the order in which these elements appear in the
XML document and their data types.
A sample XML schema for the PRODUCTDATA data
structure must be given as shown in the following code:
<xsd:schema xmlns:xsd=“http://
www.w3.org/2001/XMLSchema”>
<xsd:element name="PRODUCTDATA"
type="prdata"/>
<xsd:complexType name="prdata">
<xsd:sequence>
<xsd:element name="PRODUCT"
type="prdt"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="prdt">
<xsd:sequence>
<xsd:element name="PRODUCTNAME"
type="xsd:string"/>
<xsd:element name="DESCRIPTION"
type="xsd:string"/>
<xsd:element name="PRICE"
type="xsd:positiveInteger"/>
<xsd:element name="QUANTITY"
type="xsd:nonNegativeInteger"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
As shown in the preceding code, the declaration of an
XML schema begins with the schema element. The
schema element uses the xmlns attribute to specify the
namespace associated with the document.
A namespace is a string that is used to refer to Unique
Resource Identifiers (URI), such as "http://
www.microsoft.com" and "http://www.w3.org/2001/
XMLSchema", where the definition of the keywords and
the data types used in the schema is stored.

You might also like