T-SQL Concepts PDF
T-SQL Concepts PDF
T-SQL Concepts PDF
Table of Contents
RDBMS Concepts..................................................................................................................................................................... 5
Constraints ............................................................................................................................................................. 5
Difference between BLANK and NULL ................................................................................................................... 9
Normalization and De-Normalization .................................................................................................................... 9
SQL Commands Types ........................................................................................................................................................... 13
DDL - Data Definition Language ........................................................................................................................... 13
DML - Data Manipulation Language .................................................................................................................... 13
DCL - Data Control Language ............................................................................................................................... 13
DQL - Data Query Language ................................................................................................................................. 13
Difference between Truncate and Delete ........................................................................................................... 14
Services Running in SQL Server ............................................................................................................................................. 15
SSMS Tool Overview ............................................................................................................................................................. 16
System databases ................................................................................................................................................ 16
Some important system objects .......................................................................................................................... 17
Linked Server........................................................................................................................................................ 18
Mdf, Ndf and Ldf files........................................................................................................................................... 20
SELECT statement sequence ................................................................................................................................................. 23
Joins....................................................................................................................................................................................... 24
Inner Join:............................................................................................................................................................. 25
Left Join: ............................................................................................................................................................... 25
Right Join: ............................................................................................................................................................. 26
Cross Join: ............................................................................................................................................................ 26
Self -Join: .............................................................................................................................................................. 27
Duplicate values join example ............................................................................................................................. 27
DISTINCT, Group BY, Having clause, Difference between WHERE and HAVING .................................................................. 28
Group BY .............................................................................................................................................................. 28
Multiple Column Grouping: ................................................................................................................................. 31
Other Examples: ................................................................................................................................................... 31
HAVING and WHERE ............................................................................................................................................ 33
Distinct/Count ...................................................................................................................................................... 35
RDBMS Concepts
Constraints
Primary key: It is the column value which uniquely identifies a record or row in a database table. It is not
NULL column. It means no NULL values are allowed. A table can have only one primary key. But the
primary key can also be the combination of columns.
Example:
/* Method 1*/
IF EXISTS(SELECT * FROM sys.tables WHERE name ='Employee')
DROP TABLE Employee
/* Method 2*/
IF EXISTS(SELECT * FROM sys.tables WHERE name ='Employee')
DROP TABLE Employee
/* Throw error since Primary key is created on the nullable column (Emp_Id)*/
IF EXISTS(SELECT * FROM sys.tables WHERE name ='Employee')
DROP TABLE Employee
/*Method 3*/
IF EXISTS(SELECT * FROM sys.tables WHERE name ='Employee')
DROP TABLE Employee
Unique key: It is same as Primary key which uniquely identifies a record but Unique key allows one NULL
value. This unique key is also called as Alternate key. A table can have multiple Unique key columns.
/* Method 1*/
IF EXISTS(SELECT * FROM sys.tables WHERE name ='Employee')
DROP TABLE Employee
/* Method 2*/
IF EXISTS(SELECT * FROM sys.tables WHERE name ='Employee')
DROP TABLE Employee
/* Method 3*/
IF EXISTS(SELECT * FROM sys.tables WHERE name ='Employee')
DROP TABLE Employee
Foreign key: Foreign key is used to link two tables. A column in one table will be the primary key in
another table. Then such column is called Foreign key.
Let’s take an example, suppose we have an Employee table and Dept table. Employee table has Emp_Id as
primary key and it also has Emp_Name, Dept_Id columns. Now in Dept table Dept_Id is the primary key and
it also has Dept_Name column. Now Dept_Id in Employee table is called Foreign key as this is primary key
in Dept table.
Dept_Id Dept_Name
1 HR
2 Sales
3 Finance
/*First Make an entry in the dept table and then enter the value in Employee table*/
INSERT INTO Dept VALUES(1,'D1')
INSERT INTO Employee VALUES(1, 1,'AAA', 1)
/*Throws error since the dept value exists in the employee table*/
TRUNCATE TABLE Dept
DELETE FROM Dept
/*First truncate or delete the value in employee table and then delete the dept table(You cannot
truncate the dept table bcoz its DDL command). On truncating Dept table it throws error*/
TRUNCATE TABLE Employee
TRUNCATE TABLE Dept
Composite key: It is the combination of columns values which uniquely identify a record. That is if more
than one column form a Primary key then it is also a Composite key.
In the below table Cust_Id and Prod_Id both together uniquely identifies a record. Since PK includes more
than one column as PK this is called Composite PK.
Candidate key: Suppose a table has 5 columns and among them 3 columns are unique, then any 1 column
among 3 can be primary key. Since 3 columns participate to be a primary key, all 3 columns are called
Candidate key.
Default Constraint: The DEFAULT constraint is used to insert a default value into a column.The default
value will be added to all new records, if no other value is specified.
;WITH CTE
AS
(
SELECT '' AS BLANK,NULL AS [NULL]
)
SELECT LEN(BLANK),LEN([NULL]) FROM CTE
What is Normalization?
Normalization is the process of organizing the fields and tables of relational database to minimize redundancy and
dependency. Normalization usually involves dividing large tables into smaller and less redundant tables and
defining relationships between them.
Types of Normalization:
But its normal practice that we follow till 3NF. Here only three normal forms are explained. Let’s consider the
below example which in not in normalized form, where for each employee there are multiple values in some fields.
1st NF :-->
• The table cells must be of single value.
• Eliminate repeating groups in individual tables.
• Create a separate table for each set of related data.
• Identify each set of related data with a primary key.
In the below fig 2 you can see that each cell has one and only one value, but we need to remove the redundancy by
placing each set of related data in different table and identify Primary key
in each table as in fig 3A and 3B.
2nd NF :-->
Every Non key attribute should be fully dependent on the whole key(Composite key) but not on the part of the key.
In the fig 3B we can see that only Time is dependent on both EmpId and ProjectNum, where as ProjectTitle,
ProjectMgr, MgrPhn are only dependent on ProjectNum but not on EmpID. So keep EmpID, ProjectNum and Time
in one table . ProjectNum, ProjectTitle, ProjectMgr ,MgrPhn in other table as shown in fig 4C.
Fig 4C
3rd NF :-->
If any non key attribute is dependent on other non key attribute , and inturn that non key attribute is dependent on
any key attribute ,then keep both non key attributes in other table.
In fig 4C you can see that MgrPhn is dependent on ProjectMgr but not dependent on ProjectNum and ProjectMgr is
dependent on ProjectNum. So place MgrPhn and ProjectMgr in other table as shown in fig 5D.
What is De-normalization?
De-normalization is the process of attempting to optimize the read performance of a database by adding redundant
data or by grouping data. Adding same number of redundancy increases the read performance.
Normalized databases fair very well under conditions where the applications are write-intensive and the write-
load is more than the read-load. Like, the updates are very fast because the data to be updated is located at a single
place and there are no duplicates. Normalization is followed in the OLTP systems (Application database)
De-normalized databases fair well under heavy read-load and when the application is read intensive. The data is
present in the same table so there is no need for any joins; hence the selects are very fast. But because the data is
duplicated, the updates and inserts become complex and costly. De-normalization is followed in the OLAP systems
(Data Warehouse)
DROP Deletes an entire table, a view of a table or other object in the database.
Truncate is a DDL command, whereas Delete is a DML command. This is because, suppose a table has
identity column and if we Truncate table and insert a record its identity property is reset i.e. count starts
from beginning. It means the table structure is reset. Where as in case of delete if we delete and insert a
record the identity column value will be one more than the value last deleted.
Truncate and Delete both is logged. Where Delete logs the whole record deleted but Truncate logs pointer
to the data page. Because of this Truncate is faster and Delete is slower.
Truncate is bulk operation whereas Delete is Row by Row operation.
In Truncate we cannot specify where condition, where as in Delete we can specify where condition.
BEGIN TRAN
DELETE FROM tranTest
SELECT * FROM tranTest
ROLLBACK
SELECT * FROM tranTest
BEGIN TRAN
TRUNCATE TABLE tranTest
SELECT * FROM tranTest
ROLLBACK
SELECT * FROM tranTest
Model database: The model database provides you a template for creating new databases. All the objects in the
model databases are automatically copied to the new user database. Any modification in the model database is also
applied to all the user databases created on the server.
USE [model]
MSDB database: The msdb database contains configuration information about various support services, such as
SQL Server Agent, Database Mail and Service Broker. The SQL Server Agent service uses the msdb database to store
scheduling information about jobs and alerts. Modification of the data of the msdb database should be avoided;
however, if modifications are necessary, you should use the stored procedures and views of the msdb database to
modify the database.
TempDB database: The tempdb database is used to store temporary tables generated automatically by SQL
Server and the temporary tables created explicitly by the users. SQL Server uses the tempdb database to store the
intermediate results of the queries when doing complex database operations. Whenever SQL Server restarts, the
tempdb database is dropped and then recreated.
ReportServer database: The report server database is a SQL Server database that stores the following content:
Items managed by a report server (reports and linked reports, shared data sources, report models, folders,
resources) and all of the properties and security settings that are associated with those items.
Subscription and schedule definitions.
Report snapshots (which include query results) and report history.
System properties and system-level security settings.
Report execution log data.
Symmetric keys and encrypted connection and credentials for report data sources.
ReportServerTempDB database: Each report server database uses a related temporary database to store session
and execution data, cached reports, and work tables that are generated by the report server. Background server
processes will periodically remove older and unused items from the tables in the temporary database. Reporting
Services does not re-create the temporary database if it is missing, nor does it repair missing or modified tables.
Although the temporary database does not contain persistent data, you should back up a copy of the database
anyway so that you can avoid having to re-create it as part of a failure recovery operation. If you back up the
temporary database and subsequently restore it, you should delete the contents. Generally, it is safe to delete the
contents of the temporary database at any time. However, you must restart the Report Server Windows service
after you delete the contents.
Database Snapshot: Database snapshots are an Enterprise only feature which made its debut in SQL Server 2005
A database snapshot is a view of what the source database looked like at the time at which the snapshot was
created. This means that all the objects will be the same as what it was when the snapshot was taken and all of the
data will be exactly as it was then. To use database snapshots to recover from an unwanted DML statement, you
need to have a suitable snapshot in place. Snapshots can only be created by using a T-SQL statement. Here is an
example of how to create a database snapshot
Suppose something went wrong with the actual database, like objects got dropped or data got deleted, then using
the snapshot you can restore it back. And we can use the snapshot for read operation only like SELECT. We cannot
do any modifications like INSERT, UPDATE, DELETE, DROP, CREATE on the snapshot database. Please refer below
example
USE [master]
Linked Server
It is used to link between two servers. From one server you can access the objects of another server. It is not
recommended to use linked server unless and until it is necessary.
Distributed Query:
/** Execute below query in Server2 which is been linked. In my case it’s my local system Sql server**/
SELECT TOP 10 * FROM [AMSMSAAPP02-PRD.HQ.NETAPP.COM].imports.dbo.Temp_SK_Training
Open Query:
There are implications when trying to join the results of OPENQUERY with a local table. Typically joining remote
tables with local tables across the network is not the most efficient method of querying. In some cases it may be
better to subscribe to a remote table by importing it locally, then joining it locally.Open queries are useful when
you are not referencing multiple servers in one query. It’s generally fast as SQL does not break it into multiple
operations.
So to access the tables in Server1 (AMSMSAAPP02-PRD.HQ.NETAPP.COM) we have to create linked server in Server2
(which is my local system SQL Server in my case). Below is the steps to create a linked server. Linked Server can be
found under Server objects.
In case of distributed query the query optimizer will try to parse the remote table locally and even though the data
filter applied in the query, first all the data from the remote table is bought to local and then the data filter is
applied. This takes more time.
In case of open query the entire query is passed to the remote server and there the remote table is parsed, by
applying filter and then the result obtained is joined with the local table. This is much faster when compared to the
distributed query. But in the open query you can refer only one linked server.
Primary Data File (.mdf): It's a SQL Data file where all the data in the database objects are stored in. (like tables,
stored procedures, views, triggers etc. are stored in the mdf file of sql server). There can be only one primary file
for a database.
Secondary Data File (.ndf): This is same as the primary data file, where there can be “n” number of secondary files.
Secondary database files are used to store all data that does not fit in the primary database file. A database should
not include a secondary database file if the primary database file can hold all of the data. Some databases might
need one or more secondary data files because of their size or use secondary files on separate disk drives to spread
data across multiple disks.
Transaction Log File (.ldf): Every database by default has one transaction log which is created along with the mdf
file, but it can also have multiple transaction logs in case if the 1st log is full and running out of space. A transaction
log stores every transaction made to a SQL Server database, except some which are minimally logged like BULK
IMPORT or SELECT INTO. The transaction log is the most important component of a SQL Server database when it
comes to the disaster recovery – however, it must be uncorrupted.
http://www.sqlshack.com/beginners-guide-sql-server-transaction-logs/
http://www.mssqltips.com/sqlservertip/3076/how-to-read-the-sql-server-database-transaction-log/
We will see now how the transactions are written to log file and how to read the log. This can be understood by a
function called "fn_dblog ()".
--Create DB.
USE [master];
GO
CREATE DATABASE ReadingDBLog;
GO
-- Create tables.
USE ReadingDBLog;
GO
CREATE TABLE [Location] (
[Sr.No] INT IDENTITY,
[Date] DATETIME DEFAULT GETDATE (),
[City] CHAR (25) DEFAULT 'Bangalore');
Below query will give the information about the transaction log.
USE ReadingDBLog
go
INSERT INTO Location DEFAULT VALUES ;
GO 100
GO
UPDATE Location
SET City='New Delhi'
WHERE [Sr.No]<5
GO
DELETE Location
WHERE [Sr.No]>90
Go
Now read the transaction log again. It tells what all transactions happened.
USE ReadingDBLog
go
SELECT
[Current LSN],
[Transaction ID],
[Operation],
[Transaction Name],
[CONTEXT],
[AllocUnitName],
[Page ID],
[Slot ID],
[Begin Time],
[End Time],
[Number of Locks],
[Lock Information]
FROM sys.fn_dblog(NULL,NULL)
WHERE Operation IN
('LOP_INSERT_ROWS','LOP_MODIFY_ROW',
'LOP_DELETE_ROWS','LOP_BEGIN_XACT','LOP_COMMIT_XACT')
Now shrink the database log and check the transaction log. All the transactions will be cleaned off from the log.
Joins
Joins are used to retrieve the data from two or more tables, based on a relationship between certain columns in
these tables.
Inner Join:
Returns only matching records from two or more tables which are being joined.
Left Join:
Returns all the records from the left table and only matching records from the right table.
Right Join:
Returns all the records from the right table and only matching records from the left table.
Cross Join:
Each and every record from left table is joined with each and every record in the right table.
Self -Join:
Here we join the same table again with itself.
NOTE: while using self-join be care full about the order of column used in join condition. The condition
e.Emp_manager=m.Emp_id is different from e.Emp_Id=m.Emp_Manager
Group BY is used to summarize the table data. As the name implies it will group the set of similar data in a column.
Grouping may be based on only one column or multiple columns. Below examples illustrate this:
Sreehari Katageri, http://Skatageri.blogspot.com | DISTINCT, Group BY, Having clause, Difference between 28
WHERE and HAVING
T-SQL Concepts
In the above fig we can see that EmpDept has a set of similar values as highlighted in read box: FIN, HR , IT.
Below query returns Number of Employees in each department with the following condition:
A dept should have more than 2 employees, only those records should be displayed.
So HR dept will not be returned in the output as it has 2 employees.
Sreehari Katageri, http://Skatageri.blogspot.com | DISTINCT, Group BY, Having clause, Difference between 29
WHERE and HAVING
T-SQL Concepts
Working:
Below query returns the Number of Employees in each dept with the following condition:
A dept should have more than 2 employees, only those records should be displayed.
Except FIN dept all other dept should be displayed.
Working:
Sreehari Katageri, http://Skatageri.blogspot.com | DISTINCT, Group BY, Having clause, Difference between 30
WHERE and HAVING
T-SQL Concepts
Below query is the example for multiple column grouping which will return, in a dept how many employees are
from same places. In below example we can see, from FIN dept from Hydrabad there are 2 employees and rest all
have 1 employee.
Working:
Other Examples:
Similarly instead of count we can use aggregate functions like MIN(), MAX(), AVG(), SUM() etc.
Below queries returns Minimum and Maximum salary in each department
Sreehari Katageri, http://Skatageri.blogspot.com | DISTINCT, Group BY, Having clause, Difference between 31
WHERE and HAVING
T-SQL Concepts
Sreehari Katageri, http://Skatageri.blogspot.com | DISTINCT, Group BY, Having clause, Difference between 32
WHERE and HAVING
T-SQL Concepts
People say that HAVING cannot exists without GROUP BY, but this is wrong. HAVING can exists without GROUP BY.
When HAVING alone is used its compulsory to use aggregate function. In the absence of GROUP BY HAVING will
group entire table as one and applies aggregate function.
WHERE is also a filter condition and HAVING is also a filter condition. WHERE applies filter on single record,
HAVING applies filter on grouped data. In where clause we cannot use aggregate functions but in having clause we
can use aggregate function.
Sreehari Katageri, http://Skatageri.blogspot.com | DISTINCT, Group BY, Having clause, Difference between 33
WHERE and HAVING
T-SQL Concepts
Below query will return the table count if HAVING condition is satisfied or else no output is displayed. Here since
HAVING exists without GROUP BY entire table is grouped as one . Since Avg of EmpSal in the entire table is 28500
((20000.00 + 30000.00 + 15000.00 + 10000.00 + 25000.00 + 26000.00 +40000.00 + 26000.00 + 80000.00 + 13000
.00)/10) and in the Having clause it is mentioned that if this avg is greater than 28000 ,output 10 is displayed
which is the count of table records. It is something like, if HAVING condition is true it will return the select
statement output. Similarly you can find the one for average also.
SELECT COUNT(*)
FROM dbo.Employee
HAVING AVG(EmpSal)>28000
SELECT AVG(EmpSal)
FROM dbo.Employee
HAVING AVG(EmpSal)>28000
Sreehari Katageri, http://Skatageri.blogspot.com | DISTINCT, Group BY, Having clause, Difference between 34
WHERE and HAVING
T-SQL Concepts
Distinct/Count
Distinct will remove the duplicate records in the output as shown in below example:
Below query first it will take the count of EmpDept values and then applies distinct on the result obtained. First it
will return 10 and DISTINCT 10 is always 10.
Below query first it will take the distinct values and then applies count on the result obtained. First it will return
the distinct EmpDept which is 3 records IT,FIN,HR then COUNT of obtained result is 3.
Lets see DISTINCT and COUNT with NULL's and BLANK's in a column
UPDATE dbo.Employee
SET EmpLoc=''
WHERE EmpID='E006'
UPDATE dbo.Employee
SET EmpLoc=NULL
WHERE EmpID='E007'
Sreehari Katageri, http://Skatageri.blogspot.com | DISTINCT, Group BY, Having clause, Difference between 35
WHERE and HAVING
T-SQL Concepts
DISTINCT will consider both NULL as well as BLANK values. NULL is nothing whereas BLANK is a string of
zero characters.
COUNT will not consider NULL values but it considers BLANK values.
“*” represents all the columns in the table. So when COUNT(*) is specified the count is taken on group of
columns. So irrespective of one column EmpLoc it will consider all columns and displays count as 12.
CREATE TABLE dbo.TestCnt
(
Col1 varchar(max),
Col2 varchar(max),
Col3 varchar(max),
Col4 varchar(max)
)
Sreehari Katageri, http://Skatageri.blogspot.com | DISTINCT, Group BY, Having clause, Difference between 36
WHERE and HAVING
T-SQL Concepts
Sreehari Katageri, http://Skatageri.blogspot.com | DISTINCT, Group BY, Having clause, Difference between 37
WHERE and HAVING
T-SQL Concepts
Sreehari Katageri, http://Skatageri.blogspot.com | DISTINCT, Group BY, Having clause, Difference between 38
WHERE and HAVING
T-SQL Concepts
System Functions
String Functions
LOWER (): This will convert all the characters of a string to lower case.
UPPER (): This will convert all the characters of a string to upper case.
LTRIM (): This will return a character expression after it removes leading blanks. Meaning if there is any blank
space before the character/word this will remove it.
RTRIM (): This will return a character expression after it removes all trailing space. Meaning if there is any blank
space after the character/word this will remove it.
REPLACE (): This will replace all the occurrence of the specified string/character in a string/character with the
given string/character.
Syntax: REPLACE ([String], [String or character to replace], [the new replacement string or character])
SUBSTRING (): This will return the specified length of characters from the given string. You need to specify start
position and number of characters from the start position.
Syntax: SUBSTRING ([String], [Start position], [number of characters from start position])
LEFT (): This will return the left part of a character string with the specified number of characters.
RIGHT (): This will return the right part of a character string with the specified number of characters.
LEN (): This will return the number of characters of the specified string expression, excluding trailing blanks and
including leading blanks.
DATALENGTH (): This will return the number of bytes used to represent any expression. It will consider both
trailing as well as leading space.
CHARINDEX (): This will return the starting position of the specified string/character in a given string. You can
also define an option to say from which position within a given string to start searching the specified
character/string.
PATINDEX (): This will return the starting position of the first occurrence of a pattern in a specified expression, or
zero’s if the pattern is not found, on all valid text and character data types.
REPLICATE (): This will return a string value a specified number of times.
STUFF (): This will insert a string into another string. It deletes a specified length of characters in the first string at
the start position and then inserts the second string into the first string at the start position.
STR (): This will return character data converted from numeric data. It takes the numeric/float/decimal value and
if the length specified is less than the number of digits before decimal then it will return ‘*’. Note that in the second
example the decimal points are rounded off for few outputs. In the length decimal point is also considered.
Syntax: STR ([Float/Decimal/Numeric], [length of digits], [number of digits after decimal point])
SOUNDEX (): This will convert a character string to a four-digit code for use in a comparison. Vowels are ignored
in the comparison. Based on the sound produced by the string it returns a value. It ignore the numeric values as
well.
DIFFERENCE (): This will return an integer value that indicates the difference between the SOUNDEX values of two
character expressions. The return value ranges from 0 to 4. 4 is the best match and 0 is the worst match. This value
is derived from the number of characters in the SOUNDEX of each phrase that are the same.
This can be used when you want to match the similarities between the string, like for address, names etc.
CAST (): This will convert one data type to another. This is an ASCII standard. We don’t have any formatting option
here while converting date time.
CONVERT (): This will convert one data type to another. This can be used for date time formatting.
Math Functions
ROUND (): This will round a numeric field to the number of decimals specified. The optional value can be either 0
or any other numeric value. When operation is 0 (or this parameter is omitted), the ROUND function will round the
result to the number of decimal_places. If operation is any value other than 0, the ROUND function will truncate the
result to the number of decimal_places.
Syntax: ROUND ([float number], [number of decimal places to round off], [Optional value to truncate the decimal
part])
ABS (): This will return absolute value of the given number. Meaning if the number is negative it will make it
positive.
ISNUMERIC (): Determines whether an expression is a valid numeric type. It returns 0 if the expression non
numeric, 1 if expression is a numeric value.
CEILING (): The CEILING function returns the smallest integer greater than or equal to the specified numeric
expression.
FLOOR (): The FLOOR function returns the largest integer less than or equal to the specified numeric expression
Aggregate Functions
MIN (): This will return minimum value of the expression. It gives minimum on both numeric as well as character.
MAX (): This will return maximum value of the expression. It gives maximum on both numeric as well as character.
AVG (): This will return average value of the expression. AVG will not consider NULL.
COUNT (): This will return COUNT value of the expression. COUNT will not consider NULL but it will consider
BLANK value as shown in below example.
Ranking/Analytical Functions
PARTITION BY (): This is used to divide the rows based on the specified columns.
ROW_NUMBER (): This will give the sequential number based on the partitioned column or ordered column. For
this ORDER BY is mandatory. But it can exist without PARTITION BY.
RANK (): This will give rank based on the partitioned column or ordered column. For this ORDER BY is mandatory.
But it can exist without PARTITION BY. If there are two records with same value then both get the same rank, but
for next record the next rank will be skipped and assigned that next rank. Suppose if two records are assigned rank
as 1 each, 3rd record will get rank as 3 but not 2.
DENSE_RANK (): This is same as RANK () which give rank based on the partitioned column or ordered column. For
this ORDER BY is mandatory. But it can exist without PARTITION BY. If there are two records with same value then
both get the same rank, but for next record the next rank will not be skipped and assigned that next rank. Suppose
if two records are assigned rank as 1 each, 3rd record will get rank as 2 but not 3.
GROUPING SETS (): Suppose if you need the aggregations on different column combination (permutation -
combination) of the columns specified in the group by, it cannot be achieved using normal group by. For this we
need to use GROUPING SETS.
Syntax: GROUP BY GROUPING SETS (different permutation combination of the grouped columns)
GROUPING (): Indicates whether a specified column expression in a GROUP BY list is aggregated or not.
GROUPING returns 1 for aggregated or 0 for not aggregated in the result set. GROUPING can be used only in the
SELECT <select> list, HAVING, and ORDER BY clauses when GROUP BY is specified.
ROLLUP: This is used to get the subtotals in the aggregations. ROULLUP is used with the GROUP BY.
CUBE: This is similar to the GROUPING SETS, which gives all possible aggregations of the grouped columns. CUBE
is used with the GROUP BY.
NTILE (): Distributes the rows in an ordered partition into a specified number of groups. The groups are
numbered, starting at one. For each row, NTILE returns the number of the group to which the row belongs.
Date Functions
DATEADD (): This is used add number of days, weeks, seconds, nanoseconds, month etc. to the specified date.
DATEDIFF (): This will return the difference between two days, based on the specified option.
YEAR (): This will return year part of the specified date.
MONTH (): This will return month part of the specified date.
DAY (): This will return day part of the specified date.
DATENAME (): This will return the result based on the specified datepart. In few case it will give the name instead
of the number.
DATEPART (): This will return the result based on the specified datepart.
ISDATE (): This will validate if the specified value is date or not. If it is date it will return 1 else 0.
Other Functions
COALESCE (): This will return first non-NULL value among the multiple columns specified.
ISNULL (): This will replace the NULL with the specified value.
Data Types
INT: This will take the values in between -2147483648 to 2147483647. Its size is 4 bytes and it’s constant for any
value in the specified range.
BIGINT: This will take the values in between -9223372036854775808 to 9223372036854775807. Its size is 8
bytes and it’s constant for any value in the specified range.
SMALLINT: This will take the values in between -32768 to 32767. Its size is 2 bytes and it’s constant for any value
in the specified range.
TINYINT: This will take the values in between 0 to 255. Its size is 1 bytes and it’s constant for any value in the
specified range.
CHAR: This is of fixed length in memory. Even though if u define length as 10 bytes and use only 5 characters, in
the memory 10 bytes are allotted (1 character = 1 byte). This data type is used when the values in the columns are
of consistent size/wont vary. Maximum characters this can accommodate is 8000.
NCHAR: This is of fixed length in memory. Even though if u define length as 10 bytes and use only 2 characters, in
the memory 10 bytes are allotted (1 character = 2 byte). This data type is used when the values in the columns are
of consistent size/wont vary. This is used for special languages like Chinese, Arabic, and German etc. Maximum
characters this can accommodate is 4000.
VARCHAR: This is of variable length in memory. Even though if u define length as 10 bytes and use only 2
characters, in the memory 2 bytes are allotted (1 character = 2 byte). This data type is used when the values in the
columns are of not consistent size. Maximum characters this can accommodate is 8000. VARCHAR (max) will take
only 8000 characters.
NVARCHAR: This is of variable length in memory. Even though if u define length as 10 bytes and use only 2
characters, in the memory 4 bytes are allotted (1 character = 2 byte). This data type is used when the values in the
columns are of not consistent size. Maximum characters this can accommodate is 4000. NVARCHAR (max) will
take only 4000 characters.
NUMERIC/ DECIMAL: Numeric and Decimal data types are same. They give the same result. It takes the precision,
which is the length of the digit and the scale, which tells how many digits after the decimal point. Maximum
precision you can specify is 38.
FLOAT: This is similar to Numeric and Decimal. In case of Numeric and Decimal if the length of value is less than
the precision, then the end of digits will be occupied by 0’s. For example my value is 12.34, but the precision is 5
and scale is 3, result will be 12.340. But in case of Float it will not append with 0’s.
Precision with 1 to 24 will occupy 7 digits which takes 4 bytes.
Precision with 25 to 53 will occupy 15 digits which takes 8 bytes.
So basically for float it depends on how many bytes your column needs to be.
DATETIME: Defines a date that is combined with a time of day with fractional seconds that is based on a 24-hour
clock. It takes both date and the time
USER DEFINED DATA TYPE: In some case we may need to define our own data type. Like a column with phone
number, email address etc. These columns should take only those values defined with some rule.
Example 1: Just create user defined data type saying the column should take varchar value of length less than or
equal to 20
Step 3: Insert a record with string more than 20 characters, it will throw error.
INSERT INTO @Table VALUES ('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')
Step 4: Insert a record with less than or equal to 20 character. The record gets inserted.
INSERT INTO @Table VALUES ('AAAAAAAAAAAAAAAAAAA')
Example 2: Just create user defined data type saying the column should take varchar value of length less than or
equal to 14 and column with phone number, which should take either “Unknown Number” or number with
following format : +91-9999999999.
Identity Property
IDENTITY: Creates an identity column in a table. This property is used with the CREATE TABLE and ALTER TABLE
Transact-SQL statements. It is an integer incremental number as specified by the seed. Seed is the value that is
used for the very first row loaded into the table. Increment is the incremental value that is added to the identity
value of the previous row that was loaded.
IDENTITY INSERT ON/OFF: Allows explicit values to be inserted into the identity column of a table. Identity
column must be of data type int, bigint, smallint, tinyint, or decimal or numeric with a scale of 0, and constrained to
be nonnullable.
SET IDENTITY_INSERT Test.dbo.ID_Example ON; -- Allows value to insert in identity column
SET IDENTITY_INSERT Test.dbo.ID_Example OFF; -- Not Allows value to insert in identity column
Set operators
EXCEPT: This will return distinct records from the left query output which are not present in the right query
output. If both the query output matches it will not return anything. This is helpful in doing QA.
INTERSECT: This will return distinct records which are common between the left query output and the right query
output. This is helpful in doing QA.
UNION: This will combine two distinct data sets. It will remove the duplicate records.
UNION ALL: This will combine two data sets. It will include the duplicate records.
Logical operators
Below is the sample data set
AND: If you want to select rows that must satisfy all the given conditions, you can use the logical operator, AND.
OR: If you want to select rows that satisfy at least one of the given conditions, you can use the logical operator, OR.
BETWEEN: If you want to select records based on the range of values then use BETWEEN. It will consider the
extreme values as well, meaning the extreme values of the range specified, in our example 20 and 27. This can be
used for date range as well.
EXISTS/ NOT EXISTS: This is used to search for the presence of a row in a specified table that meets certain
criteria. Returns true if a subquery contains any rows.
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (1,'Paul',
'Revere', 'AL', 0, 72)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (2,'Elgibeth',
'Revere', 'AL', 0, 72)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (3,'Peter',
'John', 'AL', 0, 34)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (4,'John',
'Lennon', 'NY', 0, 69)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (5,'Steve',
'Martin', 'NY', 1, 75)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (6,'George',
'Washington', 'VA', 0, 75)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (6,'Patrick',
'Hamilton', 'VA', 0, 75)
INSERT INTO Test.dbo.addressbook (ID, firstname, lastname, email) VALUES (1,'Paul', 'Revere',
'paul@email.com')
INSERT INTO Test.dbo.addressbook (ID, firstname, lastname, email) VALUES (2,'Wade', 'Harvey',
'wade@email.com')
INSERT INTO Test.dbo.addressbook (ID, firstname, lastname, email) VALUES (3,'Jack', 'Powers',
'jack@email.com')
INSERT INTO Test.dbo.addressbook (ID, firstname, lastname, email) VALUES (4,'George', 'Washington',
'george@email.com')
IN: Determines whether a given value matches any value in a subquery or a list.
NOT IN: Returns the records apart from the values in the sub query result or list.
LIKE: This is used when you don’t know exactly what word/ string you are looking for. Like operator compares
given character string with specified pattern.
Wildcard
character Description Example
WHERE ProductName LIKE '%chai%' displays
Compares 0 or more characters in a all products where productname includes
% string. word 'chai'.
Compares any single character in a WHERE ProductName LIKE '_hai' finds all
_ (underscore) string. four-letter first names that end with hai.
Compares any single character within WHERE ProductName LIKE '[a-c]hai' displays
the specified range or set of characters product name ending with hai and first
[] like range [a-c] or set [abc]. character between a and c.
Compares any single character not WHERE ProductName LIKE '[^a-c]%' displays
within the specified range [^a-c] or set all product name not starting with character
[^] [^abc]. range a,b and c.
ALL: This compares a single value against a set of data from a query. With ALL you can use only <= or >=. If you use
<= then the outer query will return only those records where the column value specified in the where clause is less
than the min value in the subquery. If you use >= then the outer query will return only those records where the
column value specified in the where clause is greater than the max value in the subquery.
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (1,'Paul',
'Revere', 'AL', 0, 72)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (2,'Elgibeth',
'Revere', 'AL', 0, 72)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (3,'Peter',
'John', 'AL', 0, 34)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (4,'John',
'Lennon', 'NY', 0, 69)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (5,'Steve',
'Martin', 'NY', 1, 75)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (6,'George',
'Washington', 'VA', 0, 75)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (7,'Patrick',
'Hamilton', 'VA', 0, 75)
INSERT INTO Test.dbo.addressbook (ID, firstname, lastname, email) VALUES (1,'Paul', 'Revere',
'paul@email.com')
INSERT INTO Test.dbo.addressbook (ID, firstname, lastname, email) VALUES (2,'Wade', 'Harvey',
'wade@email.com')
INSERT INTO Test.dbo.addressbook (ID, firstname, lastname, email) VALUES (3,'Jack', 'Powers',
'jack@email.com')
INSERT INTO Test.dbo.addressbook (ID, firstname, lastname, email) VALUES (4,'George', 'Washington',
'george@email.com')
INSERT INTO Test.dbo.addressbook (ID, firstname, lastname, email) VALUES (5,'George', 'dsfds',
'george@email.com')
ANY / SOME: This compares a single value against a set of data from a query. For ANY or SOME if anyone value is
present it will return the records. In the below example, both paul and George is present in both the table, so it
returned the value. Like = you can use >= or <= or > or <.
IS NULL / IS NOT NULL: If you want the records with a particular column value as NULL then use IS NULL. If you
want to see on a particular column not null records then use IS NOT NULL.
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (1,'Paul', NULL,
'AL', 0, 72)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (2,'Elgibeth',
'Revere', 'AL', 0, 72)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (3,'Peter',
'John', 'AL', 0, 34)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (4,'John',
'Lennon', 'NY', 0, 69)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (5,'Steve',
NULL, 'NY', 1, 75)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (6,'George',
'Washington', 'VA', 0, 75)
INSERT INTO Test.dbo.people (ID, firstname, lastname, statecode, alive, height) VALUES (6,'Patrick',
'Hamilton', 'VA', 0, 75)
TOP: This is most commonly used with SELECT STATEMENT and also can be used with the UPDATE STATEMENT.
This will select the top specified number of records. In the below query top 50 percent means, it will return 50% of
the entire records. Suppose there are 10 records it will return 5 records.
Sub Query
Subqueries are of 2 types:
1. Standard or Non Correlated Subqueries
2. Correlated Subqueries
Generally a subquery is a query that is nested inside a SELECT, UPDATE or DELETE statements, or inside another
subquery. A subquery can be used anywhere an expression is allowed. We can have upto 32 levels of subqueries.
Subqueries are slower than joins. A subquery can return a scalar value or a series of value.
Correlated subqueries
A correlated subquery is one where inner query and the outer query are related with each other. This means that
the subquery is executed repeatedly, once for each row that might be selected by the outer query. Inner query and
outer query are not independent to execute.
Clustered Index:
This is similar to the telephone directory, where the name is arranged in a sorted order and we directly located the
name and then the phone number in front of it. When a primary key is created on a table, by default clustered index
is created. There can be only one clustered index per table. The column on which index is created will be physically
sorted.
Index is made up of a set of pages called index nodes that are organized in a B-tree structure (Binary tree). This
structure is hierarchical in nature, with the root node at the top of the hierarchy and the leaf nodes at the bottom,
as shown in below figure.
When you see the execution plan, you see following few words:
Table Scan
Index Scan
Index Seek
RID Lookup
Key Lookup/ Book Mark lookup
Clustered Index Scan and Table Scan is almost same and expensive, because in case of Clustered index all
data resides in the leaf level of clustered index page and in case of Table scan all the data resides in data
pages. Suppose you have 100 columns and you are interested in 10 columns and you use only 10 columns
in your select query, in case of Clustered index scan even though you are interested in 10 columns the I/O it
takes is for all the columns because the leaf level has all 100 columns. In case of Table scan all data resides
in the data pages and will take time to I/O 100 columns even though you are interested in 10 columns.
Non Clustered Index scan is better than the clustered index scan. In case of non clustered index scan, the
index page will have only those columns which are defined while creating the index. So even though your
table has 100 columns the I/O it takes is for only those columns which are defined in the index.
Clustered Index Scan and Table Scan both are same. Suppose in our example below, we have only clustered
index on ID column and if we execute the below query, we get the Clustered index scan.Because here we
have index on ID but not on City. In the same query instead of city if we use the ID column to filter, you get
the clustered index seek.
In the above figure you can see that the clustered index is created on the ID column. The index page is structured in
to B-Tree. So the search value 3 falls between 1 to 25 at the leaf node. The search is shown with the arrow in the
figure. In case of clustered index the leaf node contains the data.
CASE 1 (RID Lookup): RID Lookup happens when your table has a NONCLUSTERED index without INCLUDING
any columns from the SELECT and has no CLUSTERED index. If we take our example below, for RID Lookup don’t
have Clustered index to point to the clustered index page.In this case SQL engine will have Row ID for each record
in the data page and same is mapped in the index page too. So using Row ID, table is being scanned to get the
required columns/data from the data page. This is more expensive than the key Lookup. InCase key lookup is
almost nearly equal to RID lookup.
In the above figure you can see that the Non Clustered index is created on the ID column. At the leaf index page you
can see the RID lookup. Using that lookup it will search the data page for the required columns like FirstName and
LastName. Here you can notice that the leaf index page do not include the FirstName and the LastName. So it is an
extra over head to look for those columns in the data page.
CASE 2(Key Lookup/Bookmark Lookup): Key Lookup happens when your table has a CLUSTERED INDEX and
NONCLUSTERED INDEX without including all the columns in the select. If we take our example we have clustered
index on ID column and Non Clustered index on City. FirstName is not included in index page and so when a city is
found at the Non clustered index page it finds for FirstName but its is not there in the non clustered index page so
using Key Lookup ID(which is a primary key value) it points to the Clustered index page and gets the remaining
column it needs.
CASE 3(Remove Lookup’s): To remove either of lookup INCLUDE all the required columns in the
NONCLUSTERED index. So that all the required columns reside in the index page itself and the data is retrieved at
the faster rate. No need to again look into the data page.
NOTE: Index works better on a column when the redundancy of data is less i.e. less repeating values.
UPDATE OneIndex
SET City='California'
WHERE City='Las Vegas'
GO
UPDATE OneIndex
SET City='Las Vegas'
WHERE ID =52
GO
Assume that you have a huge table which contains data for multiple departments and multiple regions. Now you
should make sure that each of the department has access to only those fields which are relevant to them. So what
you do is you create a view with only those columns which are required for that department and give user that
view instead of that table. Same way you can implement row level security.
Standard view
In case of standard view data is not stored on the disk. The data from the view is obtained only when the view is
executed i.e., just the definition of the view is stored in the database but not the data. A view is executed normally
like you select a table.
Index view
In case of indexed view data is stored on the disk. When you create an index on the view it becomes index view.
For indexed view there should be a unique clustered index. Without Creating UNIQUE CLUSTERED INDEX we
cannot create NON CLUSTERED INDEX on a view
In schema binding view if we create a view with the SCHEMABINDING option it will lock the tables being
referred by the view and restricts any kind of changes that may change the table schema (No Alter
command). While creating schema binding view, we can’t mention “SELECT * FROM TABLENAME” with the
query. We have to mention the entire column name for reference.
If you need to decrypt a view better have the scripts backup. Because if you lose the script you need to get some
third party tool to decrypt it. If you need to decrypt then simply remove the ENCRYPTION keyword and then
alter the view.
You can pass parameters to stored proc and return the value from stored proc as well i.e., you can provide both
input parameters and output parameters.
NOTE: Whenever you use GO statement in your stored proc it means it is the end of stored proc. So try to avoid GO
statement while creating the stored proc.
IF you want to do any modification then just use ALTER instead of CREATE
Use sp_helptext ‘Stored Proc ’ name to see the definition of stored proc.
sp_helptext usp_Test_Proc2
In stored proc you can create temporary table but in UDF you cannot create temporary table.
In UDF you cannot use PRINT command, but you can use in stored proc.
We can use insert, update and delete only on the table variable within the function.
TRY CATCH cannot be used in UDF, but can be used in stored proc.
We cannot call stored proc from the UDF.
You can call UDF in SELECT and HAVING statement, but you cannot call stored proc.
NOTE: always use dbo schema when calling a scalar function else you get below error.
Msg 195, Level 15, State 10, Line 1
'udf_Scalar_Example' is not a recognized built-in function name.
Inline table valued function: In the Inline table valued function, you can just select a table but you cannot
manipulate the data. So this just returns the table. You should always call the inline table valued function like a
table using SELECT * FROM
Multi statement table valued function: In the type of function, you can do manipulation on the table data,
but no on the actual table instead you take a copy of table data into a table variable and do the necessary
modification. Here you can do insert, update and delete over a table variable.
In this example the #CourseSales Table data is Pivoted so that the Course becomes the column headings.
In this example the #CourseSales Table data is Pivoted so that the Year becomes the column headings.
Transforming Sales Table data to a Quarterly aggregated sales data with Quarters as the Columns in the result set.
Transforming Sales Table data to a Monthly aggregated sales data with Months as the Columns in the result set.
UNPIVOT
UNPIVOT is the reversal of the PIVOT operation. It basically provides a mechanism for transforming columns into
rows.
Temporary table
These are the tables created physically in the tempdb. You can create this table same as the normal table and also
this table can have constraints, index like normal table. Again this is classified into two types:
Local Temporary table
Global Temporary table
Local temporary tables are created with single hash i.e. #. Ex: #Temp or #Anyname. This table exists for a
particular session. Now what is a session? Session is, when u open the management studio you open a query
window. Each query window you open is a session. So this table created in one session cannot be accessed in other
session.
Now go to another query window and execute the below query,the session id changes and u will get an error
message.
(1 row(s) affected)
(1 row(s) affected)
Msg 208, Level 16, State 1, Line 5
Invalid object name '#TempSample'.
So once the query window where u created the #temp table is closed #temp table gets dropped by its own. So
#temp exists for a particular session until that session exists.
Global temporary tables are created by double hash i.e. ## Ex: ##TempSample or ##Anyname. This table is
accessible in all the session untill the session the table was created is not closed. Once the query window where the
## table was created is closed the table gets dropped on its own.
Table variable
This is just like a variable. This table exists for a particular batch of execution. It gets dropped once it comes out of
batch. This table is created in tempdb but not the memory.
In the below example you can see that there is a GO after the first select * from sys.tables and then create the table
variable and then immediately again select * from sys.tables without GO. Since Go represents the batch the table
exists for a batch. So you notice that in the first select * from sys.tables there are 12 entries but in the second one
you notice 13 entries in sys.tables. So it means table variables are stored in the tempdb for that batch of execution
and later once batch execution is complete the table is dropped. Here the tempdb do not hold the table with its
original name instead you can see #BD763C6F.
Table variable allows to create primary key at the time of declaration as below:
DECLARE @TempSample TABLE (ID INT PRIMARY KEY, NAME VARCHAR(40))
CTE is a temporary named result set that you can reference within a SELECT, INSERT, UPDATE, or DELETE
statement.
SQL Server supports two types of CTEs—recursive and nonrecursive.
CTE is just like a view. In case if we don’t want to store the definition in the database, we can go with CTE.
When dealing with sub-queries, it is often required that you need to select a part of the data from a sub
query or even join data from a query with some other tables. In that case, either you have an option to
name your sub-queries with an alias or to use it directly. Gradually your requirement is getting more and
more complex and your query would look unmaintainable at any time. CTE allows you to define the sub
query at once, name it using an alias and later call the same data using the alias just like what you do with a
normal table.
CTE can also be used in the view.
The scope of the CTE is limited to very first SELECT statement
Use MAXRECURSION to prevent infinite loop in recursive CTE. The recursion level ranges from 0 and
32,767.
0 means max recursion.
Recursive CTE
Example 1:
;WITH CTE
AS
(
SELECT 1 AS val
UNION ALL
SELECT val+1
FROM CTE
WHERE val<=3
)
SELECT *
FROM CTE
SELECT 1
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4
Example 2:
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Emp]') AND type in
(N'U'))
BEGIN
--Create the table
CREATE TABLE dbo.Emp
(
EmpID int PRIMARY KEY,
EmpName varchar(30),
MgrID int FOREIGN KEY REFERENCES Emp(EmpID)
)
And so on……
Let’s see a simple example with the below given data set.
IF EXISTS(SELECT * FROM sys.tables WHERE name='tblEmployee')
DROP TABLE tblEmployee
We cannot join two tables with ON condition using CROSS APPLY. But we can use CROSS APPLY like
CROSS JOIN.
Now lets see how to use CROSS APPLY and OUTER APPLY. Before that lets create table valued function
which accepts an input deptid and return the department details.
Query to get the maximum value from date1, date2, date3, date4 for each of the product, where ProdId is
a unique column (Primary key column)
Example 1: Suppose there is a table with the same table structure in multiple databases, but the data
within in it is different. Instead of running the query multiple times in different databases, we will write a
dynamic query to pull the data from multiple databases with only one execution.
USE [Test]
GO
USE [Temp]
GO
USE [Demo]
GO
USE [Demo]
GO
SELECT @MaxCnt=COUNT(*) FROM #DB_List ---- get max number of database to be looped.
SET @cnt=1
WHILE (@cnt<=@MaxCnt)
BEGIN
Example 2: Suppose you need to create a stored proc which accepts the comma separated varchar
values, which in turn need to be passed to a scalar function. Results obtained from the scalar function
need to be used in the WHERE condition of a SQL query.
USE [Demo]
GO
SET @res=''
SET @len=LEN(@str)
SET @i=CHARINDEX(@del,@str)
WHILE @i>=1
BEGIN
SET @res=@res+','''+LEFT(@str,@i-1)+''''
SET @str=SUBSTRING(@str,@i+1,@len)
SET @i=CHARINDEX(@del,@str)
END
SET @res=@res+','''+@str+''''
SET @res=SUBSTRING(@res,2,LEN(@res))
RETURN @res
END
GO
EXEC (@SQL)
END
GO
DECLARE @SQL NVARCHAR(MAX) ----- Note that for parameter passing in dynamic sql always use NVARCHAR
DECLARE @cntOutput INT
IF OBJECT_ID('SalesHistory')>0
DROP TABLE SalesHistory;
GO
CREATE TABLE [dbo].[SalesHistory]
(
[SaleID] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
[Product] [varchar](10) NULL,
[SaleDate] [datetime] NULL,
[SalePrice] [money] NULL
)
GO
Step2: Create the Stored Procedure by passing the Table valued parameters.
NOTE: When a Table Type is passed as parameter it should always be READONLY.
Cannot perform DML operation on Table valued Parameter
Step4: Insert the Table data to Table Type Variable. Note that not exactly the below insert to be used
(This is for example). Inserting the record into Table Type variable can be based on your scenario.
DECLARE @i SMALLINT
SET @i = 1
SET @i = @i + 1
END
Merge
Merge is available in SQL Server 2008 and higher version. Merge combines INSERT, UPDATE and DELETE
in one single statement based on the conditions specified. Merge can be used for incremental inserts and
updates.
UPDATE dbo.SrcTableEmp
SET EmpLoc=''
WHERE EmpID='E003'
---Step4: Fetch
FETCH NEXT FROM Cur INTO @EmpID,@EmpName,@Salary
WHILE @@FETCH_STATUS=0
BEGIN
PRINT 'ID : '+ CONVERT(VARCHAR(20),@EmpID)+', Name : '+@EmpName+ ', Salary :
'+convert(VARCHAR(20),@Salary)
FETCH NEXT FROM Cur INTO @EmpID,@EmpName,@Salary
END
---Step5: Close
CLOSE Cur
---Step6: Deallocate
DEALLOCATE Cur
Since we say that cursor is an object, it should be available in the system tables like tables, views, objects
etc. Suppose you don’t close and deallocate the cursor, it will be available in the system tables until you
close and deallocate it.
By default the cursor is global. To make the cursor local, you need to define LOCAL while declaring the
cursor. If GLOBAL is set, it means that scope of the cursor is global to the connection. Simply it can be
referenced in any stored procedure or batch executed by same connection. If LOCAL is used, it is only for
the batch which it was created
In the below example notice that cursor is declared in one database and is used in another database. Even
though you don’t use GLOBAL it can be accessed in Test DB.
OPEN Cur
GO
WHILE @@FETCH_STATUS=0
BEGIN
PRINT 'ID : '+ CONVERT(VARCHAR(20),@EmpID)+', Name : '+@EmpName+ ', Salary :
'+convert(VARCHAR(20),@Salary)
FETCH NEXT FROM Cur INTO @EmpID,@EmpName,@Salary
END
CLOSE Cur
DEALLOCATE Cur
OPEN Cur
GO
WHILE @@FETCH_STATUS=0
BEGIN
PRINT 'ID : '+ CONVERT(VARCHAR(20),@EmpID)+', Name : '+@EmpName+ ', Salary :
'+convert(VARCHAR(20),@Salary)
FETCH NEXT FROM Cur INTO @EmpID,@EmpName,@Salary
END
CLOSE Cur
DEALLOCATE Cur
Once you execute above query you will get the below error message.
FORWARD_ONLY: Specifies that cursor can only fetch data sequentially from the first to the last row.
FETCH NEXT is the only fetch option supported. Note that by default the cursor is FORWARD_ONLY.
DECLARE @EmpID INT,
@EmpName VARCHAR (50),
@Salary INT
OPEN Cur
FETCH NEXT FROM Cur INTO @EmpID,@EmpName,@Salary
WHILE @@FETCH_STATUS=0
BEGIN
PRINT 'ID : '+ CONVERT(VARCHAR(20),@EmpID)+', Name : '+@EmpName+ ', Salary :
'+convert(VARCHAR(20),@Salary)
FETCH NEXT FROM Cur INTO @EmpID,@EmpName,@Salary
END
CLOSE Cur
DEALLOCATE Cur
SCROLL: The cursor can be scrolled back and forth with "FETCH NEXT", "FETCH PRIOR".
DECLARE @EmpID INT,
@EmpName VARCHAR (50),
@Salary INT
OPEN Cur
FETCH LAST FROM Cur INTO @EmpID,@EmpName,@Salary
WHILE @@FETCH_STATUS=0
BEGIN
PRINT 'ID : '+ CONVERT(VARCHAR(20),@EmpID)+', Name : '+@EmpName+ ', Salary :
'+convert(VARCHAR(20),@Salary)
FETCH PRIOR FROM Cur INTO @EmpID,@EmpName,@Salary
END
CLOSE Cur
DEALLOCATE Cur
STATIC: Specifies that cursor will use a temporary copy of the data instead of base tables. This cursor
does not allow modifications and modifications made to base tables are not reflected in the data returned
by fetches made to this cursor.
DYNAMIC: Specifies that cursor reflects all data changes made to the base tables as you scroll around the
cursor.
OPEN Cur
FETCH NEXT FROM Cur INTO @EmpID,@EmpName,@Salary
WHILE @@FETCH_STATUS=0
BEGIN
PRINT 'ID : '+ CONVERT(VARCHAR(20),@EmpID)+', Name : '+@EmpName+ ', Salary :
'+convert(VARCHAR(20),@Salary)
FETCH NEXT FROM Cur INTO @EmpID,@EmpName,@Salary
END
CLOSE Cur
DEALLOCATE Cur
-------
OPEN Cur
FETCH NEXT FROM Cur INTO @EmpID,@EmpName,@Salary
WHILE @@FETCH_STATUS=0
BEGIN
PRINT 'ID : '+ CONVERT(VARCHAR(20),@EmpID)+', Name : '+@EmpName+ ', Salary :
'+convert(VARCHAR(20),@Salary)
FETCH NEXT FROM Cur INTO @EmpID,@EmpName,@Salary
END
CLOSE Cur
DEALLOCATE Cur
For all the other cursor options and in depth knowledge please refer the below links.
http://www.databasejournal.com/features/mssql/article.php/1439731/Using-SQL-Server-Cursors.htm
http://www.dotnet-tricks.com/Tutorial/sqlserver/4L7I050512-SQL-Server-Basics-of-Cursors.html
While loop
It is also like cursor but not stored as an object. In case of cursor you no need to initialize the counter
explicitly for looping, but in case of while loop you have to set the counter explicitly.
We will take the above cursor example and try to convert it to while loop.
INSERT INTO #temp ----- Dump all the required data into a temp table
SELECT EmpID,EmpName,Salary FROM Employee
SELECT @MaxCnt=COUNT(*) FROM #temp ---- Get the maximum number of loop
SET @cnt=1 --- Initilize the counter
WHILE (@cnt<= @MaxCnt) ---- loop untill the counter reaches the maximum loop
BEGIN
XML PATH
What is XML?
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
If you notice above the tags are user defined, not like HTML which are predefined.
XML PATH
The normal SELECT statement will retrieve the record as rowset, but what if you need it in an XML
format. So you can go with FOR XML.
SELECT EmpID,EmpName,Salary
FROM Employee
FOR XML RAW ('Employee')
SELECT EmpID,EmpName,Salary
FROM Employee
FOR XML RAW ('Employee'),ROOT
<root>
<Employee EmpID="1" EmpName="Mohan" Salary="12000" />
<Employee EmpID="2" EmpName="Pavan" Salary="25000" />
<Employee EmpID="3" EmpName="Amit" Salary="22000" />
<Employee EmpID="4" EmpName="Sonu" Salary="22000" />
<Employee EmpID="5" EmpName="Deepak" Salary="28000" />
</root>
SELECT EmpID,EmpName,Salary
FROM Employee
FOR XML RAW ('Employee'),ROOT('Company')
<Company>
<Employee EmpID="1" EmpName="Mohan" Salary="12000" />
<Employee EmpID="2" EmpName="Pavan" Salary="25000" />
<Employee EmpID="3" EmpName="Amit" Salary="22000" />
<Employee EmpID="4" EmpName="Sonu" Salary="22000" />
<Employee EmpID="5" EmpName="Deepak" Salary="28000" />
</Company>
SELECT EmpID,EmpName,Salary
FROM Employee
FOR XML RAW ('Employee'),ROOT('Company'),ELEMENTS
<Company>
<Employee>
<EmpID>1</EmpID>
<EmpName>Mohan</EmpName>
<Salary>12000</Salary>
</Employee>
<Employee>
<EmpID>2</EmpID>
<EmpName>Pavan</EmpName>
<Salary>25000</Salary>
</Employee>
<Employee>
<EmpID>3</EmpID>
<EmpName>Amit</EmpName>
<Salary>22000</Salary>
</Employee>
<Employee>
<EmpID>4</EmpID>
<EmpName>Sonu</EmpName>
<Salary>22000</Salary>
</Employee>
<Employee>
<EmpID>5</EmpID>
<EmpName>Deepak</EmpName>
<Salary>28000</Salary>
</Employee>
</Company>
<Company xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Employee>
<EmpID>1</EmpID>
<EmpName>Mohan</EmpName>
<Salary>12000</Salary>
<Address>Noida</Address>
</Employee>
<Employee>
<EmpID>2</EmpID>
<EmpName>Pavan</EmpName>
<Salary>25000</Salary>
<Address>Delhi</Address>
</Employee>
<Employee>
<EmpID>3</EmpID>
<EmpName>Amit</EmpName>
<Salary>22000</Salary>
<Address xsi:nil="true" /> ---- since the address is NULL in the DB.
</Employee>
<Employee>
<EmpID>4</EmpID>
<EmpName>Sonu</EmpName>
<Salary>22000</Salary>
<Address>Noida</Address>
</Employee>
<Employee>
<EmpID>5</EmpID>
<EmpName>Deepak</EmpName>
<Salary>28000</Salary>
<Address>Gurgaon</Address>
</Employee>
</Company>
SELECT EmpID,EmpName,Salary,Address
FROM Employee
FOR XML AUTO
SELECT EmpID,EmpName,Salary,Address
FROM Employee
FOR XML AUTO, ROOT ('Employees')
<Employees>
<Employee EmpID="1" EmpName="Mohan" Salary="12000" Address="Noida" />
<Employee EmpID="2" EmpName="Pavan" Salary="25000" Address="Delhi" />
<Employee EmpID="3" EmpName="Amit" Salary="22000" />
<Employee EmpID="4" EmpName="Sonu" Salary="22000" Address="Noida" />
<Employee EmpID="5" EmpName="Deepak" Salary="28000" Address="Gurgaon" />
</Employees>
SELECT EmpID,EmpName,Salary,Address
FROM Employee
FOR XML AUTO, ROOT ('Employees'),ELEMENTS
<Employees>
<Employee>
<EmpID>1</EmpID>
<EmpName>Mohan</EmpName>
<Salary>12000</Salary>
<Address>Noida</Address>
</Employee>
<Employee>
<EmpID>2</EmpID>
<EmpName>Pavan</EmpName>
<Salary>25000</Salary>
<Address>Delhi</Address>
</Employee>
<Employee>
<EmpID>3</EmpID>
<EmpName>Amit</EmpName>
<Salary>22000</Salary> ---- Here Address Element is missing as it is NULL.
</Employee>
<Employee>
Sreehari Katageri, http://Skatageri.blogspot.com | XML PATH 131
T-SQL Concepts
<EmpID>4</EmpID>
<EmpName>Sonu</EmpName>
<Salary>22000</Salary>
<Address>Noida</Address>
</Employee>
<Employee>
<EmpID>5</EmpID>
<EmpName>Deepak</EmpName>
<Salary>28000</Salary>
<Address>Gurgaon</Address>
</Employee>
</Employees>
SELECT EmpID,EmpName,Salary,Address
FROM Employee
FOR XML AUTO, ROOT ('Employees'),ELEMENTS XSINIL
<Employees xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Employee>
<EmpID>1</EmpID>
<EmpName>Mohan</EmpName>
<Salary>12000</Salary>
<Address>Noida</Address>
</Employee>
<Employee>
<EmpID>2</EmpID>
<EmpName>Pavan</EmpName>
<Salary>25000</Salary>
<Address>Delhi</Address>
</Employee>
<Employee>
<EmpID>3</EmpID>
<EmpName>Amit</EmpName>
<Salary>22000</Salary>
<Address xsi:nil="true" />
</Employee>
<Employee>
<EmpID>4</EmpID>
<EmpName>Sonu</EmpName>
<Salary>22000</Salary>
<Address>Noida</Address>
</Employee>
<Employee>
<EmpID>5</EmpID>
<EmpName>Deepak</EmpName>
<Salary>28000</Salary>
<Address>Gurgaon</Address>
</Employee>
</Employees>
SELECT EmpID,EmpName,Salary,Address
FROM Employee
FOR XML PATH ('Employee'),ROOT('Company'), ELEMENTS XSINIL
<Company xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Employee>
<EmpID>1</EmpID>
<EmpName>Mohan</EmpName>
<Salary>12000</Salary>
<Address>Noida</Address>
</Employee>
<Employee>
<EmpID>2</EmpID>
<EmpName>Pavan</EmpName>
<Salary>25000</Salary>
<Address>Delhi</Address>
</Employee>
<Employee>
<EmpID>3</EmpID>
<EmpName>Amit</EmpName>
<Salary>22000</Salary>
<Address xsi:nil="true" />
</Employee>
<Employee>
<EmpID>4</EmpID>
<EmpName>Sonu</EmpName>
<Salary>22000</Salary>
<Address>Noida</Address>
</Employee>
<Employee>
<EmpID>5</EmpID>
<EmpName>Deepak</EmpName>
<Salary>28000</Salary>
<Address>Gurgaon</Address>
</Employee>
</Company>
<Company xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Employee>
<EmployeeDetails>
<EmpID>1</EmpID>
<EmpName>Mohan</EmpName>
<Address>Noida</Address>
</EmployeeDetails>
<SalaryDetails>
<Salary>12000</Salary>
</SalaryDetails>
</Employee>
<Employee>
<EmployeeDetails>
<EmpID>2</EmpID>
<EmpName>Pavan</EmpName>
<Address>Delhi</Address>
</EmployeeDetails>
<SalaryDetails>
<Salary>25000</Salary>
</SalaryDetails>
</Employee>
<Employee>
<EmployeeDetails>
<EmpID>3</EmpID>
<EmpName>Amit</EmpName>
<Address xsi:nil="true" />
</EmployeeDetails>
<SalaryDetails>
<Salary>22000</Salary>
</SalaryDetails>
</Employee>
<Employee>
<EmployeeDetails>
<EmpID>4</EmpID>
<EmpName>Sonu</EmpName>
<Address>Noida</Address>
</EmployeeDetails>
<SalaryDetails>
<Salary>22000</Salary>
</SalaryDetails>
</Employee>
<Employee>
<EmployeeDetails>
<EmpID>5</EmpID>
<EmpName>Deepak</EmpName>
<Address>Gurgaon</Address>
</EmployeeDetails>
<SalaryDetails>
<Salary>28000</Salary>
</SalaryDetails>
</Employee>
</Company>
http://blog.sqlauthority.com/2013/04/05/sql-server-group-by-rows-and-columns-using-xml-path-
efficient-concating-trick/
BEGIN TRY
…… SQL code
…… SQL code
…….
END TRY
BEGIN CATCH
…… Logic or message to handle error
…… Logic or message to handle error
END CATCH
So when ever any error occurs in try block, the control will move to catch block.
BEGIN TRY
SELECT 1/0
END TRY
BEGIN CATCH
PRINT 'ErrorNumber :'+CAST(ERROR_NUMBER() AS VARCHAR(10))+CHAR(13)+
'ErrorSeverity :'+CAST(ERROR_SEVERITY() AS VARCHAR(10))+CHAR(13)+
'ErrorState :'+CAST(ERROR_STATE() AS VARCHAR(100))+CHAR(13)+
'ErrorLine :'+CAST(ERROR_LINE() AS VARCHAR(100))+CHAR(13)+
'ErrorMessage :'+CAST(ERROR_MESSAGE() AS VARCHAR(MAX))+CHAR(13)
END CATCH
Here you see how TRY CATCH and TRANSACTION used in the query.
Below code is using transactions. If no error the transaction commits. If error occurs then transaction
rolled back.
TRUNCATE TABLE Employee
BEGIN TRY
BEGIN TRAN
INSERT INTO Employee (EmpID,EmpName,Salary,Address) VALUES(1,'Mohan',12000,'Noida')
INSERT INTO Employee (EmpID,EmpName,Salary,Address) VALUES(2,'Pavan',25000,'Delhi')
INSERT INTO Employee (EmpID,EmpName,Salary,Address) VALUES(3,'Amit',22000,NULL)
INSERT INTO Employee (EmpID,EmpName,Salary,Address) VALUES(4,'Sonu',22000,'Noida')
INSERT INTO Employee (EmpID,EmpName,Salary,Address) VALUES(5,'Deepak',28000,'Gurgaon')
INSERT INTO Employee (EmpID,EmpName,Salary,Address) VALUES(6,'Azar',12000,'Noida')
INSERT INTO Employee (EmpID,EmpName,Salary,Address) VALUES(7,'Akhul',25000,'Delhi')
INSERT INTO Employee (EmpID,EmpName,Salary,Address) VALUES(8,'Rohit',21000,'Noida')
INSERT INTO Employee (EmpID,EmpName,Salary,Address) VALUES(9,'Ranjan',null,'Noida')
INSERT INTO Employee (EmpID,EmpName,Salary,Address) VALUES(10,'Raghav',21570,'Delhi')
COMMIT TRAN
END TRY
BEGIN CATCH
ROLLBACK
END CATCH