Learning Microsoft SQL Server
Learning Microsoft SQL Server
#sql-server
www.dbooks.org
Table of Contents
About 1
Remarks 2
Versions 2
Examples 2
Joins 4
Table Aliases 5
Unions 5
Table Variables 6
PRINT 7
Comments in code 8
TRUNCATE TABLE 11
Examples 14
Introduction 16
Syntax 16
Examples 16
SUM() 16
AVG() 16
MAX() 17
MIN() 17
COUNT() 18
Introduction 20
Examples 20
Using AS 20
Using = 20
Without using AS 21
Examples 22
Scan vs Seek 22
Syntax 23
Parameters 23
Examples 23
Examples 25
Getting started 25
Create Database 25
Create Table 25
www.dbooks.org
Create View 26
Create Procedure 26
Introduction 28
Examples 28
Examples 29
BULK INSERT 29
Remarks 31
Examples 31
Examples 32
Syntax 34
Examples 34
Examples 36
Syntax 38
Remarks 38
Examples 38
Employee Hierarchy 38
Table Setup 38
Output: 39
Recursive CTE 41
Examples 44
Examples 46
TRY PARSE 46
TRY CONVERT 46
TRY CAST 47
Cast 47
Convert 48
Examples 49
CREATE VIEW 49
www.dbooks.org
CREATE VIEW With Encryption 49
Grouped VIEWs 51
UNION-ed VIEWs 51
Examples 52
Syntax 54
Remarks 54
Examples 54
Introduction 57
Examples 57
Exact Numerics 57
Approximate Numerics 59
Character Strings 59
Binary Strings 60
Remarks 61
Examples 61
Changing permissions 61
CREATE USER 61
CREATE ROLE 61
Changing role membership 61
Remarks 63
Examples 63
DELETE Snapshot 64
Syntax 65
Remarks 65
Examples 66
Examples 81
DBCC statement 83
Syntax 84
www.dbooks.org
Examples 84
Remarks 86
Examples 86
Basic Method 86
Introduction 87
Remarks 87
Examples 87
Drop tables 87
Drop Databases 88
Examples 90
Examples 92
Introduction 94
Examples 94
Parameters 96
Remarks 96
Examples 96
Encryption by certificate 96
Encryption of database 97
Encryption by passphrase 97
Syntax 98
Examples 98
Examples 99
Introduction 101
Examples 101
Example 101
Examples 102
FOR JSON clause without array wrapper (single object in output) 102
INCLUDE_NULL_VALUES 103
Remarks 105
Examples 105
www.dbooks.org
Specifying namespaces 105
Examples 108
Examples 110
Creating a full-text index with a search property list without populating it 110
Parameters 112
Remarks 112
Examples 112
Examples 114
HAVING 117
Examples 120
Examples 123
Examples 126
Show created .dll files and tables for Memory Optimized Tables 127
Examples 130
Introduction 131
Examples 131
www.dbooks.org
INSERT a single row of data 132
Examples 134
Introduction 134
Remarks 135
Examples 135
Introduction 137
Examples 137
Syntax 146
Parameters 146
Remarks 146
Examples 146
Join parent and child JSON entities using CROSS APPLY OPENJSON 147
Format one table row as a single JSON object using FOR JSON 149
Examples 151
SCOPE_IDENTITY() 151
@@IDENTITY 151
IDENT_CURRENT('tablename') 152
Introduction 153
Parameters 153
Remarks 153
Examples 153
Examples 155
CHOOSE 155
IIF 155
Examples 157
Introduction 159
Syntax 159
Remarks 160
Examples 160
www.dbooks.org
Merge Example - Synchronize Source And Target Table 161
Chapter 55: Microsoft SQL Server Management Studio Shortcut Keys 164
Examples 164
Examples 167
Examples 169
Insert new JSON array generated with FOR JSON query 170
Insert single JSON object generated with FOR JSON clause 170
Examples 172
Copy data into a table, creating that table on the fly 172
Examples 174
Introduction 177
Remarks 177
Examples 177
ISNULL() 179
COALESCE () 180
Examples 181
Remarks 185
Examples 185
Parameters 188
Remarks 188
Examples 188
Introduction 192
Syntax 192
Examples 192
www.dbooks.org
Pagination with OFFSET FETCH 193
SQL Server 2012/2014 using ORDER BY OFFSET and FETCH NEXT 194
Syntax 195
Parameters 195
Examples 195
PARSENAME 195
Examples 196
Retrieve partition table,column, scheme, function, total and min-max boundry values using 196
Examples 198
Introduction 199
Remarks 199
Examples 199
Syntax 201
Remarks 201
Examples 201
Remarks 206
Examples 206
Examples 208
Examples 209
Examples 212
Examples 215
www.dbooks.org
Enable query store on database 215
Examples 217
Row_Number() 217
Syntax 218
Parameters 218
Remarks 218
Examples 218
RANK() 219
DENSE_RANK () 219
Remarks 220
Examples 220
Remarks 222
Examples 222
Search and Return All Tables and Columns Containing a Specified Column Value 225
Get all schemas, tables, columns and indexes 227
Examples 231
General Information about Databases, Tables, Stored procedures and how to search them. 232
Examples 234
Introduction 237
Examples 237
Examples 239
Purpose 239
Syntax 240
Examples 240
www.dbooks.org
Introduction 241
Examples 241
Examples 244
Examples 246
1. Basics 246
3. Create basic service broker construction on database (single database communication) 246
Examples 250
Basics 250
Introduction 254
Examples 254
POINT 254
Chapter 90: SQL Server Evolution through different versions (2000 - 2016) 259
Introduction 259
Examples 259
Introduction 263
Examples 263
Remarks 264
Examples 264
Introduction 265
Syntax 265
Examples 265
www.dbooks.org
Examples 272
Examples 274
Remarks 275
Examples 276
Left 276
Right 276
Substring 277
ASCII 277
CharIndex 278
Char 278
Len 278
Concat 279
Lower 280
Upper 280
LTrim 281
RTrim 281
Unicode 281
NChar 281
Reverse 282
PatIndex 282
Space 282
Replicate 283
Replace 283
String_Split 284
Str 285
Quotename 285
Soundex 286
Difference 286
Format 286
String_escape 288
Examples 290
Subqueries 290
Examples 292
Remarks 293
Examples 293
Remarks 294
Examples 294
Creating a Memory-Optimized System-Versioned Temporal Table and cleaning up the SQL Server 296
Parameters 299
Examples 299
www.dbooks.org
Using FOR XML to Concatenate Values from Multiple Rows 299
Parameters 302
Examples 302
Syntax 303
Remarks 303
Examples 303
Snapshot 305
Serializable 305
Introduction 306
Examples 306
Remarks 308
Examples 308
Remarks 314
Examples 314
Introduction 316
Remarks 316
Examples 316
creating a UDT with a single int column that is also a primary key 316
Creating a UDT with a primary key and a column with a default value: 316
Syntax 318
Examples 318
Remarks 322
Examples 322
www.dbooks.org
Remarks 324
Examples 324
Examples 325
Find the single most recent item in a list of timestamped events 325
Examples 327
Credits 329
About
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: microsoft-sql-server
It is an unofficial and free Microsoft SQL Server ebook created for educational purposes. All the
content is extracted from Stack Overflow Documentation, which is written by many hardworking
individuals at Stack Overflow. It is neither affiliated with Stack Overflow nor official Microsoft SQL
Server.
The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to [email protected]
https://riptutorial.com/ 1
www.dbooks.org
Chapter 1: Getting started with Microsoft SQL
Server
Remarks
This is a set of examples highlighting basic usage of SQL Server.
Versions
Examples
INSERT / SELECT / UPDATE / DELETE: the basics of Data Manipulation
Language
Data Manipulation Language (DML for short) includes operations such as INSERT, UPDATE and
DELETE:
https://riptutorial.com/ 2
SELECT * FROM HelloWorld
-- Selecting rows from the table (see how the Description has changed after the update?)
SELECT * FROM HelloWorld
USE Northwind;
GO
SELECT TOP 10 * FROM Customers
ORDER BY CompanyName
will select the first 10 records of the Customer table, ordered by the column CompanyName from the
database Northwind (which is one of Microsoft's sample databases, it can be downloaded from
here):
Note that Use Northwind; changes the default database for all subsequent queries. You can still
reference the database by using the fully qualified syntax in the form of
[Database].[Schema].[Table]:
https://riptutorial.com/ 3
www.dbooks.org
SELECT TOP 10 * FROM Northwind.dbo.Customers
ORDER BY CompanyName
This is useful if you're querying data from different databases. Note that dbo, specified "in between"
is called a schema and needs to be specified while using the fully qualified syntax. You can think
of it as a folder within your database. dbo is the default schema. The default schema may be
omitted. All other user defined schemas need to be specified.
If the database table contains columns which are named like reserved words, e.g. Date, you need
to enclose the column name in brackets, like this:
-- descending order
SELECT TOP 10 [Date] FROM dbo.MyLogTable
ORDER BY [Date] DESC
The same applies if the column name contains spaces in its name (which is not recommended).
An alternative syntax is to use double quotes instead of square brackets, e.g.:
-- descending order
SELECT top 10 "Date" from dbo.MyLogTable
order by "Date" desc
is equivalent but not so commonly used. Notice the difference between double quotes and single
quotes: Single quotes are used for strings, i.e.
-- descending order
SELECT top 10 "Date" from dbo.MyLogTable
where UserId='johndoe'
order by "Date" desc
is a valid syntax. Notice that T-SQL has a N prefix for NChar and NVarchar data types, e.g.
returns all companies having a company name starting with AL (% is a wild card, use it as you
would use the asterisk in a DOS command line, e.g. DIR AL*). For LIKE, there are a couple of
wildcards available, look here to find out more details.
Joins
Joins are useful if you want to query fields which don't exist in one single table, but in multiple
tables. For example: You want to query all columns from the Region table in the Northwind
database. But you notice that you require also the RegionDescription, which is stored in a different
table, Region. However, there is a common key, RgionID which you can use to combine this
https://riptutorial.com/ 4
information in a single query as follows (Top 5 just returns the first 5 rows, omit it to get all rows):
will show all columns from Territories plus the RegionDescription column from Region. The result is
ordered by TerritoryDescription.
Table Aliases
When your query requires a reference to two or more tables, you may find it useful to use a Table
Alias. Table aliases are shorthand references to tables that can be used in place of a full table
name, and can reduce typing and editing. The syntax for using an alias is:
Where as is an optional keyword. For example, the previous query can be rewritten as:
Aliases must be unique for all tables in a query, even if you use the same table twice. For
example, if your Employee table included a SupervisorId field, you can use this query to return an
employee and his supervisor's name:
SELECT e.*,
s.Name as SupervisorName -- Rename the field for output
FROM Employee e
INNER JOIN Employee s
ON e.SupervisorId = s.EmployeeId
WHERE e.EmployeeId = 111
Unions
As we have seen before, a Join adds columns from different table sources. But what if you want to
combine rows from different sources? In this case you can use a UNION. Suppose you're planning
a party and want to invite not only employees but also the customers. Then you could run this
query to do it:
https://riptutorial.com/ 5
www.dbooks.org
SELECT ContactName, Address, City FROM Customers
It will return names, addresses and cities from the employees and customers in one single table.
Note that duplicate rows (if there should be any) are automatically eliminated (if you don't want
this, use a UNION ALL instead). The column number, column names, order and data type must
match across all the select statements that are part of the union - this is why the first SELECT
combines FirstName and LastName from Employee into ContactName.
Table Variables
It can be useful, if you need to deal with temporary data (especially in a stored procedure), to use
table variables: The difference between a "real" table and a table variable is that it just exists in
memory for temporary processing.
Example:
creates a table in memory. In this case the @ prefix is mandatory because it is a variable. You can
perform all DML operations mentioned above to insert, delete and select rows, e.g.
which would read the filtered values from the real table dbo.Region and insert it into the memory
table @Region - where it can be used for further processing. For example, you could use it in a join
like
which would in this case return all Northern and Southern territories. More detailed information can
be found here. Temporary tables are discussed here, if you are interested to read more about that
topic.
NOTE: Microsoft only recommends the use of table variables if the number of rows of data in the
table variable are less than 100. If you will be working with larger amounts of data, use a
temporary table, or temp table, instead.
https://riptutorial.com/ 6
PRINT
Display a message to the output console. Using SQL Server Management Studio, this will be
displayed in the messages tab, rather than the results tab:
Syntax:
SELECT *
FROM table_name
Using the asterisk operator * serves as a shortcut for selecting all the columns in the table. All
rows will also be selected because this SELECT statement does not have a WHERE clause, to specify
any filtering criteria.
This would also work the same way if you added an alias to the table, for instance e in this case:
SELECT *
FROM Employees AS e
Or if you wanted to select all from a specific table you can use the alias + " .* ":
This is not necessarily recommended, as changing the server and/or database names would
cause the queries using fully-qualified names to no longer execute due to invalid object names.
Note that the fields before table_name can be omitted in many cases if the queries are executed on
a single server, database and schema, respectively. However, it is common for a database to
have multiple schema, and in these cases the schema name should not be omitted when possible.
Warning: Using SELECT * in production code or stored procedures can lead to problems later on
(as new columns are added to the table, or if columns are rearranged in the table), especially if
your code makes simple assumptions about the order of columns, or number of columns returned.
So it's safer to always explicitly specify column names in SELECT statements for production code.
https://riptutorial.com/ 7
www.dbooks.org
Select rows that match a condition
For example:
UPDATE HelloWorlds
SET HelloWorld = 'HELLO WORLD!!!'
WHERE Id = 5
The above code updates the value of the field "HelloWorld" with "HELLO WORLD!!!" for the record
where "Id = 5" in HelloWorlds table.
Note: In an update statement, It is advised to use a "where" clause to avoid updating the whole
table unless and until your requirement is different.
A simple form of updating is incrementing all the values in a given field of the table. In order to do
so, we need to define the field and the increment value
The following is an example that increments the Score field by 1 (in all rows):
UPDATE Scores
SET score = score + 1
This can be dangerous since you can corrupt your data if you accidentally make an UPDATE for a
specific Row with an UPDATE for All rows in the table.
Comments in code
Transact-SQL supports two forms of comment writing. Comments are ignored by the database
engine, and are meant for people to read.
https://riptutorial.com/ 8
Comments are preceded by -- and are ignored until a new line is encountered:
-- This is a comment
SELECT *
FROM MyTable -- This is another comment
WHERE Id = 1;
Slash star comments begin with /* and end with */. All text between those delimiters is
considered as a comment block.
/* This is
a multi-line
comment block. */
SELECT Id = 1, [Message] = 'First row'
UNION ALL
SELECT 2, 'Second row'
/* This is a one liner */
SELECT 'More';
Slash star comments have the advantage of keeping the comment usable if the SQL Statement
loses new line characters. This can happen when SQL is captured during troubleshooting.
Slash star comments can be nested and a starting /* inside a slash star comment needs to be
ended with a */ to be valid. The following code will result in an error
/*
SELECT *
FROM CommentTable
WHERE Comment = '/*'
*/
The slash star even though inside the quote is considered as the start of a comment. Hence it
needs to be ended with another closing star slash. The correct way would be
/*
SELECT *
FROM CommentTable
WHERE Comment = '/*'
*/ */
SELECT @@VERSION
SELECT @@SERVERNAME
https://riptutorial.com/ 9
www.dbooks.org
SELECT @@SERVICENAME
Returns the name of the Windows service MS SQL Server is running as.
SELECT serverproperty('ComputerNamePhysicalNetBIOS');
Returns the physical name of the machine where SQL Server is running. Useful to identify the
node in a failover cluster.
In a failover cluster returns every node where SQL Server can run on. It returns nothing if not a
cluster.
Whenever you change data, in a Data Manipulation Language(DML) command, you can wrap
your changes in a transaction. DML includes UPDATE, TRUNCATE, INSERT and DELETE. One of the ways
that you can make sure that you're changing the right data would be to use a transaction.
DML changes will take a lock on the rows affected. When you begin a transaction, you must end
the transaction or all objects being changed in the DML will remain locked by whoever began the
transaction. You can end your transaction with either ROLLBACK or COMMIT. ROLLBACK returns
everything within the transaction to its original state. COMMIT places the data into a final state where
you cannot undo your changes without another DML statement.
Example:
INSERT INTO
dbo.test_transaction
( column_1 )
VALUES
( 'a' )
UPDATE dbo.test_transaction
SET column_1 = 'B'
OUTPUT INSERTED.*
WHERE column_1 = 'A'
SELECT * FROM dbo.test_transaction --View the table after your changes have been run
https://riptutorial.com/ 10
DROP TABLE dbo.test_transaction
Notes:
• This is a simplified example which does not include error handling. But any database
operation can fail and hence throw an exception. Here is an example how such a required
error handling might look like. You should never use transactions without an error handler,
otherwise you might leave the transaction in an unknown state.
• Depending on the isolation level, transactions are putting locks on the data being queried or
changed. You need to ensure that transactions are not running for a long time, because they
will lock records in a database and can lead to deadlocks with other parallel running
transactions. Keep the operations encapsulated in transactions as short as possible and
minimize the impact with the amount of data you're locking.
DELETE
FROM Helloworlds
This will delete all the data from the table. The table will contain no rows after you run this code.
Unlike DROP TABLE, this preserves the table itself and its structure and you can continue to insert
new rows into that table.
Restrictions Of TRUNCATE
[sic]
TRUNCATE TABLE
https://riptutorial.com/ 11
www.dbooks.org
This code will delete all the data from the table Helloworlds. Truncate table is almost similar to
Delete from Table code. The difference is that you can not use where clauses with Truncate.
Truncate table is considered better than delete because it uses less transaction log spaces.
Note that if an identity column exists, it is reset to the initial seed value (for example, auto-
incremented ID will restart from 1). This can lead to inconsistency if the identity columns is used as
a foreign key in another table.
Creates a new table with structure of old table and inserts all rows into the new table.
Some Restrictions
1. You cannot specify a table variable or table-valued parameter as the new table.
2. You cannot use SELECT…INTO to create a partitioned table, even when the
source table is partitioned. SELECT...INTO does not use the partition scheme of
the source table; instead, the new table is created in the default filegroup. To
insert rows into a partitioned table, you must first create the partitioned table and
then use the INSERT INTO...SELECT FROM statement.
3. Indexes, constraints, and triggers defined in the source table are not transferred
to the new table, nor can they be specified in the SELECT...INTO statement. If
these objects are required, you can create them after executing the
SELECT...INTO statement.
4. Specifying an ORDER BY clause does not guarantee the rows are inserted in the
specified order. When a sparse column is included in the select list, the sparse
column property does not transfer to the column in the new table. If this property
is required in the new table, alter the column definition after executing the
SELECT...INTO statement to include this property.
5. When a computed column is included in the select list, the corresponding column
in the new table is not a computed column. The values in the new column are the
values that were computed at the time SELECT...INTO was executed.
[sic]
The following example can be used to find the total row count for a specific table in a database if
table_name is replaced by the the table you wish to query:
It is also possible to get the row count for all tables by joining back to the table's partition based off
the tables' HEAP (index_id = 0) or cluster clustered index (index_id = 1) using the following script:
https://riptutorial.com/ 12
SELECT [Tables].name AS [TableName],
SUM( [Partitions].[rows] ) AS [TotalRowCount]
FROM sys.tables AS [Tables]
JOIN sys.partitions AS [Partitions]
ON [Tables].[object_id] = [Partitions].[object_id]
AND [Partitions].index_id IN ( 0, 1 )
--WHERE [Tables].name = N'table name' /* uncomment to look for a specific table */
GROUP BY [Tables].name;
This is possible as every table is essentially a single partition table, unless extra partitions are
added to it. This script also has the benefit of not interfering with read/write operations to the
tables rows'.
https://riptutorial.com/ 13
www.dbooks.org
Chapter 2: Advanced options
Examples
Enable and show advanced options
The server must be restarted before the change can take effect.
USE master;
GO
-- Set recovery every 3 min
EXEC sp_configure 'recovery interval', '3';
RECONFIGURE WITH OVERRIDE;
USE master
EXEC sp_configure 'max server memory (MB)', 64
RECONFIGURE WITH OVERRIDE
https://riptutorial.com/ 14
Set number of checkpoint tasks
https://riptutorial.com/ 15
www.dbooks.org
Chapter 3: Aggregate Functions
Introduction
Aggregate functions in SQL Server run calculations on sets of values, returning a single value.
Syntax
• AVG([ALL|DISTINCT]expression)
• COUNT([ALL|DISTINCT]expression)
• MAX([ALL|DISTINCT]expression)
• MIN([ALL|DISTINCT]expression)
• SUM([ALL|DISTINCT]expression)
Examples
SUM()
We have table as shown in figure that will be used to perform different aggregate functions. The
table name is Marksheet.
The sum function doesn't consider rows with NULL value in the field used as parameter
AVG()
We have table as shown in figure that will be used to perform different aggregate functions. The
https://riptutorial.com/ 16
table name is Marksheet.
The average function doesn't consider rows with NULL value in the field used as parameter
MAX()
We have table as shown in figure that will be used to perform different aggregate functions. The
table name is Marksheet.
MIN()
We have table as shown in figure that will be used to perform different aggregate functions. The
table name is Marksheet.
https://riptutorial.com/ 17
www.dbooks.org
Select MIN(MarksObtained) From Marksheet
COUNT()
We have table as shown in figure that will be used to perform different aggregate functions. The
table name is Marksheet.
The count function doesn't consider rows with NULL value in the field used as parameter. Usually
the count parameter is * (all fields) so only if all fields of row are NULLs this row will not be
considered
NOTE
The function COUNT(*) returns the number of rows in a table. This value can also be obtained by
using a constant non-null expression that contains no column references, such as COUNT(1).
Example
Most of the time we like to get the total number of occurrence of a column value in a table for
example:
ReportName ReportPrice
Test 10.00 $
https://riptutorial.com/ 18
ReportName ReportPrice
Test 10.00 $
Test 10.00 $
Test 2 11.00 $
Test 10.00 $
Test 3 14.00 $
Test 3 14.00 $
Test 4 100.00 $
SELECT
ReportName AS REPORT NAME,
COUNT(ReportName) AS COUNT
FROM
REPORTS
GROUP BY
ReportName
Test 4
Test 2 1
Test 3 2
Test 4 1
https://riptutorial.com/ 19
www.dbooks.org
Chapter 4: Alias Names in Sql Server
Introduction
Here is some of different ways to provide alias names to columns in Sql Server
Examples
Using AS
This is ANSI SQL method works in all the RDBMS. Widely used approach.
Using =
This is my preferred approach. Nothing related to performance just a personal choice. It makes the
code to look clean. You can see the resulting column names easily instead of scrolling the code if
you have a big expression.
This is a weird approach most of the people don't know this even exist.
SELECT *
FROM (SELECT firstname + ' ' + lastname
FROM AliasNameDemo) a (fullname)
• Demo
https://riptutorial.com/ 20
Without using AS
This syntax will be similar to using AS keyword. Just we don't have to use AS keyword
https://riptutorial.com/ 21
www.dbooks.org
Chapter 5: Analyzing a Query
Examples
Scan vs Seek
When viewing an execution plan, you may see that SQL Server decided to do a Seek or a Scan.
A Seek occurs when SQL Server knows where it needs to go and only grab specific items. This
typically occurs when good filters on put in a query, such as where name = 'Foo'.
A Scan is when SQL Server doesn't know exactly where all of the data it needs is, or decided that
the Scan would be more efficient than a Seek if enough of the data is selected.
Seeks are typically faster since they are only grabbing a sub-section of the data, whereas Scans
are selecting a majority of the data.
https://riptutorial.com/ 22
Chapter 6: Backup and Restore Database
Syntax
• BACKUP DATABASE database TO backup_device [ ,...n ] WITH with_options [ ,...o ]
• RESTORE DATABASE database FROM backup_device [ ,...n ] WITH with_options [ ,...o ]
Parameters
Parameter Details
The device to backup or restore the database from, Like {DISK or TAPE}.
backup_device
Can be separated by commas ( , )
Various options which can be used while performing the operation. Like
with_options formatting the disk where the backup is to be placed or restoring the
database with replace option.
Examples
Basic Backup to disk with no options
The following command backs up the 'Users' database to 'D:\DB_Backup' file. Its better to not give
an extension.
The following command restores the 'Users' database from 'D:\DB_Backup' file.
When you try to restore database from another server you might get the following error:
Error 3154: The backup set holds a backup of a database other than the existing
database.
In that case you should use WITH REPLACE option to replace database with the database from
backup:
https://riptutorial.com/ 23
www.dbooks.org
RESTORE DATABASE WWIDW
FROM DISK = 'C:\Backup\WideWorldImportersDW-Full.bak'
WITH REPLACE
Even in this case you might get the errors saying that files cannot be located on some path:
Msg 3156, Level 16, State 3, Line 1 File 'WWI_Primary' cannot be restored to
'D:\Data\WideWorldImportersDW.mdf'. Use WITH MOVE to identify a valid location for
the file.
This error happens probably because your files were not placed on the same folder path that exist
on new server. In that case you should move individual database files to new location:
With this statement you can replace database with all database files moved to new location.
https://riptutorial.com/ 24
Chapter 7: Basic DDL Operations in MS SQL
Server
Examples
Getting started
This section describes some basic DDL (="Data Definition Language") commands to create a
database, a table within a database, a view and finally a stored procedure.
Create Database
The following SQL command creates a new database Northwind on the current server, using path
C:\Program Files\Microsoft SQL Server\MSSQL11.INSTSQL2012\MSSQL\DATA\:
USE [master]
GO
Note: A T-SQL database consists of two files, the database file *.mdf, and its transaction log *.ldf.
Both need to be specified when a new database is created.
Create Table
The following SQL command creates a new table Categories in the current database, using
schema dbo (you can switch database context with Use <DatabaseName>):
https://riptutorial.com/ 25
www.dbooks.org
CREATE TABLE dbo.Categories(
CategoryID int IDENTITY NOT NULL,
CategoryName nvarchar(15) NOT NULL,
Description ntext NULL,
Picture image NULL,
CONSTRAINT PK_Categories PRIMARY KEY CLUSTERED
(
CategoryID ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON PRIMARY
) ON PRIMARY TEXTIMAGE_ON PRIMARY
Create View
The following SQL command creates a new view Summary_of_Sales_by_Year in the current database,
using schema dbo (you can switch database context with Use <DatabaseName>):
This will join tables Orders and [Order Subtotals] to display the columns ShippedDate, OrderID and
Subtotal. Because table [Order Subtotals] has a blank in its name in the Northwind database, it
needs to be enclosed in square brackets.
Create Procedure
The following SQL command creates a new stored procedure CustOrdersDetail in the current
database, using schema dbo (you can switch database context with Use <DatabaseName>):
This stored procedure, after it has been created, can be invoked as follows:
which will return all order details with @OrderId=10248 (and quantity >=0 as default). Or you can
specify the optional parameter
https://riptutorial.com/ 26
exec dbo.MyCustOrdersDetail 10248, 10
which will return only orders with a minimum quantity of 10 (or more).
https://riptutorial.com/ 27
www.dbooks.org
Chapter 8: bcp (bulk copy program) Utility
Introduction
The bulk copy program utility (bcp) bulk copies data between an instance of Microsoft SQL Server
and a data file in a user-specified format. The bcp utility can be used to import large numbers of
new rows into SQL Server tables or to export data out of tables into data files.
Examples
Example to Import Data without a Format File(using Native Format )
https://riptutorial.com/ 28
Chapter 9: BULK Import
Examples
BULK INSERT with options
You can customize parsing rules using different options in WITH clause:
In this example, CODEPAGE specifies that a source file in UTF-8 file, and TERMINATORS are
coma and new line.
BULK INSERT
BULK INSERT command can be used to import file into SQL Server:
BULK INSERT command will map columns in files with columns in target table.
You can read content of file using OPENROWSET(BULK) function and store content in some
table:
SINGLE_BLOB option will read entire content from a file as single cell.
Yu can define format of the file that will be imported using FORMATFILE option:
https://riptutorial.com/ 29
www.dbooks.org
The format file, format_file.fmt, describes the columns in values.txt:
9.0
2
1 SQLCHAR 0 10 "\t" 1 ID SQL_Latin1_General_Cp437_BIN
2 SQLCHAR 0 40 "\r\n" 2 Description SQL_Latin1_General_Cp437_BIN
You can use OPENROWSET to read content of file and pass it to some other function that will
parse results.
The following example shows hot to read entire content of JSON file using OPENROWSET(BULK)
and then provide BulkColumn to OPENJSON function that will parse JSON and return columns:
SELECT book.*
FROM OPENROWSET (BULK 'C:\JSON\Books\books.json', SINGLE_CLOB) as j
CROSS APPLY OPENJSON(BulkColumn)
WITH( id nvarchar(100), name nvarchar(100), price float,
pages int, author nvarchar(100)) AS book
https://riptutorial.com/ 30
Chapter 10: CASE Statement
Remarks
Above example is just to show the syntax for using case statements in SQL Server with day of
week example. Although same can output can be achieved by using "SELECT
DATENAME(WEEKDAY, GETDATE())" as well.
Examples
Simple CASE statement
In a simple case statement, one value or variable is checked against multiple possible answers.
The code below is an example of a simple case statement:
In a Searched Case statement, each option can test one or more values independently. The code
below is an example of a searched case statement:
SELECT CASE
WHEN LEFT(@FirstName, 1) IN ('a','e','i','o','u')
THEN 'First name starts with a vowel'
WHEN LEFT(@LastName, 1) IN ('a','e','i','o','u')
THEN 'Last name starts with a vowel'
ELSE
'Neither name starts with a vowel'
END
https://riptutorial.com/ 31
www.dbooks.org
Chapter 11: CLUSTERED COLUMNSTORE
Examples
Table with CLUSTERED COLUMNSTORE index
If you want to have a table organized in column-store format instead of row store, add INDEX cci
CLUSTERED COLUMNSTORE in definition of table:
COLUMSTORE tables are better for tables where you expect full scans and reports, while row
store tables are better for tables where you will read or update smaller sets of rows.
Clustered column store index can be rebuilt if you have a lot of deleted rows:
Rebuilding CLUSTERED COLUMNSTORE will "reload" data from the current table into new one
and apply compression again, remove deleted rows, etc.
https://riptutorial.com/ 32
You can rebuild one or more partitions.
https://riptutorial.com/ 33
www.dbooks.org
Chapter 12: COALESCE
Syntax
• COALESCE([Column1],[Column2]....[ColumnN]
Examples
Using COALESCE to Build Comma-Delimited String
We can get a comma delimited string from multiple rows using coalesce as shown below.
Since table variable is used, we need to execute whole query once. So to make easy to
understand, I have added BEGIN and END block.
BEGIN
--Used COLESCE function, so it will concatenate comma seperated FirstName into @Names
varible
SELECT @Names = COALESCE(@Names + ',', '') + FirstName
FROM @Table
COALESCE() returns the first NON NULL value in a list of arguments. Suppose we had a table
containing phone numbers, and cell phone numbers and wanted to return only one for each user.
In order to only obtain one, we can get the first NON NULL value.
https://riptutorial.com/ 34
SELECT
UserID,
COALESCE(PhoneNumber, CellNumber)
FROM
@Table
https://riptutorial.com/ 35
www.dbooks.org
Chapter 13: Common Language Runtime
Integration
Examples
Enable CLR on database
CLR procedures are not enabled by default. You need to run the following queries to enable CLR:
In addition, if some CLR module need external access, you should set TRUSTWORTHY property
to ON in your database:
Procedures, functions, triggers, and types written in .Net languages are stored in .dll files. Once
you create .dll file containing CLR procedures you should import it into SQL Server:
PERMISSION_SET is Safe by default meaning that code in .dll don't need permission to access
external resources (e.g. files, web sites, other servers), and that it will not use native code that can
access memory.
you can find information about current CLR assembly files in sys.assemblies view:
SELECT *
FROM sys.assemblies asms
WHERE is_user_defined = 1
https://riptutorial.com/ 36
If you have created .Net function, compiled it into .dll, and imported it into SQL server as an
assembly, you can create user-defined function that references function in that assembly:
You need to specify name of the function and signature with input parameters and return values
that match .Net function. In AS EXTERNAL NAME clause you need to specify assembly name,
namespace/class name where this function is placed and name of the method in the class that
contains the code that will be exposed as function.
You can find information about the CLR functions using the following query:
If you have create .Net class that represents some user-defined type, compiled it into .dll, and
imported it into SQL server as an assembly, you can create user-defined function that references
this class:
You need to specify name of the type that will be used in T-SQL queries. In EXTERNAL NAME
clause you need to specify assembly name, namespace, and class name.
If you have created .Net method in some class, compiled it into .dll, and imported it into SQL
server as an assembly, you can create user-defined stored procedure that references method in
that assembly:
You need to specify name of the procedure and signature with input parameters that match .Net
method. In AS EXTERNAL NAME clause you need to specify assembly name, namespace/class
name where this procedure is placed and name of the method in the class that contains the code
that will be exposed as procedure.
https://riptutorial.com/ 37
www.dbooks.org
Chapter 14: Common Table Expressions
Syntax
• WITH cte_name [(column_name_1, column_name_2, ...)] AS (cte_expression)
Remarks
It is necessary to separate a CTE from the previous statement with a semi-colon (;) character.
A CTE's scope is a single batch, and only downstream of its definition. A batch may contain
multiple CTEs, and a CTE may reference another CTE defined earlier in the batch, but a CTE may
not reference another CTE that is defined later in the batch.
Examples
Employee Hierarchy
Table Setup
CREATE TABLE dbo.Employees
(
EmployeeID INT NOT NULL PRIMARY KEY,
FirstName NVARCHAR(50) NOT NULL,
LastName NVARCHAR(50) NOT NULL,
ManagerID INT NULL
)
GO
https://riptutorial.com/ 38
(
SELECT EmployeeID, FirstName, LastName, ManagerID, 1
FROM Employees
WHERE ManagerID IS NULL
UNION ALL
SELECT
FirstName + ' ' + LastName AS FullName,
EmpLevel,
(SELECT FirstName + ' ' + LastName FROM Employees WHERE EmployeeID =
cteReports.SupervisorID) AS ManagerName
FROM cteReports
ORDER BY EmpLevel, SupervisorID
Output:
FullName EmpLevel ManagerName
Employees table :
https://riptutorial.com/ 39
www.dbooks.org
| 2 | Arifur | Rahman | Male | 60000 |
| 3 | Oli | Ahammed | Male | 45000 |
| 4 | Sima | Sultana | Female | 70000 |
| 5 | Sudeepta | Roy | Male | 80000 |
+------+-----------+----------+--------+--------+
WITH RESULT AS
(
SELECT SALARY,
DENSE_RANK() OVER (ORDER BY SALARY DESC) AS DENSERANK
FROM EMPLOYEES
)
SELECT TOP 1 SALARY
FROM RESULT
WHERE DENSERANK = 1
To find 2nd highest salary simply replace N with 2. Similarly, to find 3rd highest salary, simply
replace N with 3.
Employees table :
WITH EmployeesCTE AS
(
SELECT *, ROW_NUMBER()OVER(PARTITION BY ID ORDER BY ID) AS RowNumber
FROM Employees
)
DELETE FROM EmployeesCTE WHERE RowNumber > 1
Execution result :
https://riptutorial.com/ 40
Generate a table of dates using CTE
WITH CTE_DatesTable
AS
(
SELECT CAST(@startdate as date) AS [date]
UNION ALL
SELECT DATEADD(dd, 1, [date])
FROM CTE_DatesTable
WHERE DATEADD(dd, 1, [date]) <= DateAdd(DAY, @numberDays-1, @startdate)
)
OPTION (MAXRECURSION 0)
This example returns a single-column table of dates, starting with the date specified in the
@startdate variable, and returning the next @numberDays worth of dates.
Recursive CTE
This example shows how to get every year from this year to 2011 (2012 - 1).
WITH yearsAgo
(
myYear
)
AS
(
-- Base Case: This is where the recursion starts
SELECT DATEPART(year, GETDATE()) AS myYear
-- Recursive Section: This is what we're doing with the recursive call
SELECT yearsAgo.myYear - 1
FROM yearsAgo
WHERE yearsAgo.myYear >= 2012
)
SELECT myYear FROM yearsAgo; -- A single SELECT, INSERT, UPDATE, or DELETE
myYear
2016
2015
2014
2013
https://riptutorial.com/ 41
www.dbooks.org
myYear
2012
2011
You can control the recursion (think stack overflow in code) with MAXRECURSION as a query
option that will limit the number of recursive calls.
WITH yearsAgo
(
myYear
)
AS
(
-- Base Case
SELECT DATEPART(year , GETDATE()) AS myYear
UNION ALL
-- Recursive Section
SELECT yearsAgo.myYear - 1
FROM yearsAgo
WHERE yearsAgo.myYear >= 2002
)
SELECT * FROM yearsAgo
OPTION (MAXRECURSION 10);
Msg 530, Level 16, State 1, Line 2The statement terminated. The maximum recursion
10 has been exhausted before statement completion.
;WITH cte_query_1
AS
(
SELECT *
FROM database.table1
),
cte_query_2
AS
(
SELECT *
FROM database.table2
)
SELECT *
FROM cte_query_1
WHERE cte_query_one.fk IN
(
SELECT PK
FROM cte_query_2
)
With common table expressions, it is possible to create multiple queries using comma-separated
AS statements. A query can then reference any or all of those queries in many different ways,
even joining them.
https://riptutorial.com/ 42
Read Common Table Expressions online: https://riptutorial.com/sql-server/topic/1343/common-
table-expressions
https://riptutorial.com/ 43
www.dbooks.org
Chapter 15: Computed Columns
Examples
A column is computed from an expression
A computed column is computed from an expression that can use other columns in the same
table. The expression can be a noncomputed column name, constant, function, and any
combination of these connected by one or more operators.
Value is computed and stored in the computed column automatically on inserting other values.
https://riptutorial.com/ 44
This gives run difference in minutes for runtime which will be very handy..
https://riptutorial.com/ 45
www.dbooks.org
Chapter 16: Converting data types
Examples
TRY PARSE
For example, source data is string type and we need to covert to date type. If conversion attempt
fails it returns NULL value.
TRY CONVERT
It converts value to specified data type and if conversion fails it returns NULL. For example, source
value in string format and we need date/integer format. Then this will help us to achieve the same.
TRY_CONVERT() returns a value cast to the specified data type if the cast succeeds; otherwise,
returns null.
Data_type - The datatype into which to convert. Here length is an optional parameter which helps
to get result in specified length.
Expression - The value to be convert
https://riptutorial.com/ 46
Style - It is an optional parameter which determines formatting. Suppose you want date format like
“May, 18 2013” then you need pass style as 111.
TRY CAST
It converts value to specified data type and if conversion fails it returns NULL. For example, source
value in string format and we need it in double/integer format. Then this will help us in achieving it.
TRY_CAST() returns a value cast to the specified data type if the cast succeeds; otherwise,
returns null.
Cast
The Cast() function is used to convert a data type variable or data from one data type to another
data type.
Syntax
The data type to which you are casting an expression is the target type. The data type of the
expression from which you are casting is the source type.
DECLARE @A varchar(2)
DECLARE @B varchar(2)
set @A='25a'
set @B='15'
https://riptutorial.com/ 47
www.dbooks.org
--'25a' is casted to 25 (string to int)
--'15' is casted to 15 (string to int)
--Result
--40
Convert
When you convert expressions from one type to another, in many cases there will be a need within
a stored procedure or other routine to convert data from a datetime type to a varchar type. The
Convert function is used for such things. The CONVERT() function can be used to display
date/time data in various formats. Syntax
Style - style values for datetime or smalldatetime conversion to character data. Add 100 to a style
value to get a four-place year that includes the century (yyyy).
select convert(varchar(20),GETDATE(),108)
13:27:16
https://riptutorial.com/ 48
Chapter 17: CREATE VIEW
Examples
CREATE VIEW
SELECT FirstName
FROM view_EmployeeInfo
You may also create a view with a calculated column. We can modify the view above as follows by
adding a calculated column:
This view adds an additional column that will appear when you SELECT rows from it. The values in
this additional column will be dependent on the fields FirstName and LastName in the table Employee
and will automatically update behind-the-scenes when those fields are updated.
https://riptutorial.com/ 49
www.dbooks.org
AS
SELECT P.LastName,
P.FirstName,
E.JobTitle
FROM Employee AS E
INNER JOIN Person AS P
ON P.BusinessEntityID = E.BusinessEntityID
GO
Views can use joins to select data from numerous sources like tables, table functions, or even
other views. This example uses the FirstName and LastName columns from the Person table and
the JobTitle column from the Employee table.
This view can now be used to see all corresponding rows for Managers in the database:
SELECT *
FROM view_PersonEmployee
WHERE JobTitle LIKE '%Manager%'
To create a view with an index, the view must be created using the WITH SCHEMABINDING keywords:
• The view definition can reference one or more tables in the same database.
• Once the unique clustered index is created, additional nonclustered indexes can be created
against the view.
• You can update the data in the underlying tables – including inserts, updates, deletes, and
even truncates.
• You can’t modify the underlying tables and columns. The view is created with the WITH
https://riptutorial.com/ 50
SCHEMABINDING option.
• It can’t contain COUNT, MIN, MAX, TOP, outer joins, or a few other keywords or elements.
For more information about creating indexed Views you can read this MSDN article
Grouped VIEWs
A grouped VIEW is based on a query with a GROUP BY clause. Since each of the groups may
have more than one row in the base from which it was built, these are necessarily read-only
VIEWs. Such VIEWs usually have one or more aggregate functions and they are used for
reporting purposes. They are also handy for working around weaknesses in SQL. Consider a
VIEW that shows the largest sale in each state. The query is straightforward:
https://www.simple-talk.com/sql/t-sql-programming/sql-view-beyond-the-basics/
UNION-ed VIEWs
VIEWs based on a UNION or UNION ALL operation are read-only because there is no single way
to map a change onto just one row in one of the base tables. The UNION operator will remove
duplicate rows from the results. Both the UNION and UNION ALL operators hide which table the
rows came from. Such VIEWs must use a , because the columns in a UNION [ALL] have no
names of their own. In theory, a UNION of two disjoint tables, neither of which has duplicate rows
in itself should be updatable.
https://www.simple-talk.com/sql/t-sql-programming/sql-view-beyond-the-basics/
https://riptutorial.com/ 51
www.dbooks.org
Chapter 18: cross apply
Examples
Join table rows with dynamically generated rows from a cell
CROSS APPLY enables you to "join" rows from a table with dynamically generated rows returned
by some table-value function.
Imagine that you have a Company table with a column that contains an array of products
(ProductList column), and a function that parse these values and returns a set of products. You
can select all rows from a Company table, apply this function on a ProductList column and "join"
generated results with parent Company row:
SELECT *
FROM Companies c
CROSS APPLY dbo.GetProductList( c.ProductList ) p
For each row, value of ProductList cell will be provided to the function, and the function will return
those products as a set of rows that can be joined with the parent row.
CROSS APPLY enables you to "join" rows from a table with collection of JSON objects stored in a
column.
Imagine that you have a Company table with a column that contains an array of products
(ProductList column) formatted as JSON array. OPENJSON table value function can parse these
values and return the set of products. You can select all rows from a Company table, parse JSON
products with OPENJSON and "join" generated results with parent Company row:
SELECT *
FROM Companies c
CROSS APPLY OPENJSON( c.ProductList )
WITH ( Id int, Title nvarchar(30), Price money)
For each row, value of ProductList cell will be provided to OPENJSON function that will transform
JSON objects to rows with the schema defined in WITH clause.
If you store a list of tags in a row as coma separated values, STRING_SPLIT function enables you
to transform list of tags into a table of values. CROSS APPLY enables you to "join" values parsed
by STRING_SPLIT function with a parent row.
Imagine that you have a Product table with a column that contains an array of comma separated
tags (e.g. promo,sales,new). STRING_SPLIT and CROSS APPLY enable you to join product rows
https://riptutorial.com/ 52
with their tags so you can filter products by tags:
SELECT *
FROM Products p
CROSS APPLY STRING_SPLIT( p.Tags, ',' ) tags
WHERE tags.value = 'promo'
For each row, value of Tags cell will be provided to STRING_SPLIT function that will return tag
values. Then you can filter rows by these values.
https://riptutorial.com/ 53
www.dbooks.org
Chapter 19: Cursors
Syntax
• DECLARE cursor_name CURSOR [ LOCAL | GLOBAL ]
[ FORWARD_ONLY | SCROLL ]
○
Remarks
Normally you would want to avoid using cursors as they can have negative impacts on
performance. However in some special cases you may need to loop through your data record by
record and perform some action.
Examples
Basic Forward Only Cursor
Normally you would want to avoid using cursors as they can have negative impacts on
performance. However in some special cases you may need to loop through your data record by
record and perform some action.
-- here we are creating our cursor, as a local cursor and only allowing
-- forward operations
DECLARE rowCursor CURSOR LOCAL FAST_FORWARD FOR
-- this is the query that we want to loop through record by record
SELECT [OrderId]
FROM [dbo].[Orders]
-- now we will initialize the cursor by pulling the first row of data, in this example the
[OrderId] column,
-- and storing the value into a variable called @orderId
FETCH NEXT FROM rowCursor INTO @orderId
-- start our loop and keep going until we have no more records to loop through
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @orderId
https://riptutorial.com/ 54
-- this is important, as it tells SQL Server to get the next record and store the
[OrderId] column value into the @orderId variable
FETCH NEXT FROM rowCursor INTO @orderId
END
/* @@FETCH_STATUS global variable will be 1 / true until there are no more rows to fetch */
WHILE @@FETCH_STATUS = 0
BEGIN
/* Write operations to perform in a loop here. Simple SELECT used for example */
SELECT Id, Val
FROM @test_table
WHERE Id = @myId;
/* Set variable(s) to the next value returned from iterator; this is needed otherwise the
cursor will loop infinitely. */
FETCH NEXT FROM myCursor INTO @myId;
END
/* After all is done, clean up */
CLOSE myCursor;
DEALLOCATE myCursor;
Results from SSMS. Note that these are all separate queries, they are in no way unified. Notice
how the query engine processes each iteration one by one instead of as a set.
https://riptutorial.com/ 55
www.dbooks.org
Id Val
1 Foo
(1 row(s) affected)
Id Val
2 Bar
(1 row(s) affected)
Id Val
3 Baz
(1 row(s) affected)
https://riptutorial.com/ 56
Chapter 20: Data Types
Introduction
This section discusses the data types that SQL Server can use, including their data range, length,
and limitations (if any.)
Examples
Exact Numerics
There are two basic classes of exact numeric data types - Integer, and Fixed Precision and
Scale.
• bit
• tinyint
• smallint
• int
• bigint
Integers are numeric values that never contain a fractional portion, and always use a fixed amount
of storage. The range and storage sizes of the integer data types are shown in this table:
Data
Range Storage
type
bit 0 or 1 1 bit **
• numeric
• decimal
• smallmoney
• money
https://riptutorial.com/ 57
www.dbooks.org
These data types are useful for representing numbers exactly. As long as the values can fit within
the range of the values storable in the data type, the value will not have rounding issues. This is
useful for any financial calculations, where rounding errors will result in clinical insanity for
accountants.
Note that decimal and numeric are synonyms for the same data type.
Decimal [(p [, s])] or Numeric [(p [, s])] -10^38 + 1 to 10^38 - 1 See Precision table
When defining a decimal or numeric data type, you may need to specify the Precision [p] and
Scale [s].
Precision is the number of digits that can be stored. For example, if you needed to store values
between 1 and 999, you would need a Precision of 3 (to hold the three digits in 100). If you do not
specify a precision, the default precision is 18.
Scale is the number of digits after the decimal point. If you needed to store a number between
0.00 and 999.99, you would need to specify a Precision of 5 (five digits) and a Scale of 2 (two
digits after the decimal point). You must specify a precision to specify a scale. The default scale is
zero.
The Precision of a decimal or numeric data type defines the number of bytes required to store the
value, as shown below:
Precision Table
1-9 5
10-19 9
20-28 13
29-38 17
These data types are intended specifically for accounting and other monetary data. These type
have a fixed Scale of 4 - you will always see four digits after the decimal place. For most systems
working with most currencies, using a numeric value with a Scale of 2 will be sufficient. Note that
no information about the type of currency represented is stored with the value.
https://riptutorial.com/ 58
Data type Range Storage
Approximate Numerics
• float [(n)]
• real
These data types are used to store floating point numbers. Since these types are intended to hold
approximate numeric values only, these should not be used in cases where any rounding error is
unacceptable. However, if you need to handle very large numbers, or numbers with an
indeterminate number of digits after the decimal place, these may be your best option.
Data
Range Size
type
n value table for float numbers. If no value is specified in the declaration of the float, the default
value of 53 will be used. Note that float(24) is the equivalent of a real value.
• datetime
• smalldatetime
These types are in all versions of SQL Server after SQL Server 2012
• date
• datetimeoffset
• datetime2
• time
Character Strings
https://riptutorial.com/ 59
www.dbooks.org
• char
• varchar
• text
• nchar
• nvarchar
• ntext
Binary Strings
• binary
• varbinary
• image
• cursor
• timestamp
• hierarchyid
• uniqueidentifier
• sql_variant
• xml
• table
• Spatial Types
https://riptutorial.com/ 60
Chapter 21: Database permissions
Remarks
Basic Syntax:
Examples
Changing permissions
CREATE USER
--implicitly map this user to a login of the same name as the user
CREATE USER [aUser];
CREATE ROLE
https://riptutorial.com/ 61
www.dbooks.org
-- SQL 2005+
exec sp_addrolemember @rolename = 'myRole', @membername = 'aUser';
exec sp_droprolemember @rolename = 'myRole', @membername = 'aUser';
-- SQL 2008+
ALTER ROLE [myRole] ADD MEMBER [aUser];
ALTER ROLE [myRole] DROP MEMBER [aUser];
Note: role members can be any database-level principal. That is, you can add a role as a member
in another role. Also, adding/dropping role members is idempotent. That is, attempting to add/drop
will result in their presence/absence (respectively) in the role regardless of the current state of
their role membership.
https://riptutorial.com/ 62
Chapter 22: Database Snapshots
Remarks
A database snapshot is a read-only, static view of a SQL Server database which is transactionally
consistent with the source database as of the moment of the snapshot's creation.
A database snapshot always resides on the same server instance as its source database. As the
source database is updated, the database snapshot is updated.
A snapshot differs from a backup since the process of snapshot creation is instantaneous and the
snapshot occupies space only as changes in the source database are applied. A backup on the
other hand stores a full copy of the data as on the time of backup creation.
Additionally, a snapshot gives an instant read only copy of the database, while a backup needs to
be restored to a server in order to be readable (and once restored can be written to as well)
Database snapshots are only available in the Enterprise and Developer editions.
Examples
Create a database snapshot
A database snapshot is a read-only, static view of a SQL Server database (the source database).
It is similar to backup, but it is available as any other database so client can query snapshot
database.
If data in a source database becomes damaged or some wrong data is written into database, in
some cases, reverting the database to a database snapshot that predates the damage might be
https://riptutorial.com/ 63
www.dbooks.org
an appropriate alternative to restoring the database from a backup.
Warning: This will delete all changes made to the source database since the snapshot
was taken!
DELETE Snapshot
You can delete existing snapshots of database using DELETE DATABASE statement:
https://riptutorial.com/ 64
Chapter 23: Dates
Syntax
• EOMONTH (start_date [, month_to_add ] )
Remarks
as per https://msdn.microsoft.com/en-us/library/ms187819.aspx, DateTimes are only precise to
3ms.
Rounding of datetime Fractional Second Precision datetime values are rounded to increments of
.000, .003, or .007 seconds, as shown in the following table.
------ ------
01/01/98 23:59:59.996
01/01/98 23:59:59.997
01/01/98 23:59:59.998
------ ------
01/01/98 23:59:59.993
01/01/98 23:59:59.994
------ ------
01/01/98 23:59:59.991
------ ------
https://riptutorial.com/ 65
www.dbooks.org
Examples
Date & Time Formatting using CONVERT
You can use the CONVERT function to cast a datetime datatype to a formatted string.
You can also use some built-in codes to convert into a specific format. Here are the options built
into SQL Server:
@convert_code Result
101 "07/21/2016"
102 "2016.07.21"
103 "21/07/2016"
104 "21.07.2016"
105 "21-07-2016"
108 "07:57:05"
110 "07-21-2016"
111 "2016/07/21"
112 "20160721"
114 "07:57:59:553"
https://riptutorial.com/ 66
@convert_code Result
126 "2016-07-21T07:58:34.340"
127 "2016-07-21T07:58:34.340"
Using this you can transform your DATETIME fields to your own custom VARCHAR format.
Example
Arguments
Given the DATETIME being formatted is 2016-09-05 00:01:02.333, the following chart shows what their
output would be for the provided argument.
https://riptutorial.com/ 67
www.dbooks.org
Argument Output
yyyy 2016
yy 16
MMMM September
MM 09
M 9
dddd Monday
ddd Mon
dd 05
d 5
HH 00
H 0
hh 12
h 12
mm 01
m 1
ss 02
s 2
tt AM
t A
fff 333
ff 33
f 3
You can also supply a single argument to the FORMAT() function to generate a pre-formatted output:
https://riptutorial.com/ 68
Monday, September 05, 2016 4:01:02 AM
d 9/5/2016
G 9/5/2016 12:01:02 AM
g 9/5/2016 12:01 AM
M September 05
O 2016-09-05T00:01:02.3330000
s 2016-09-05T00:01:02
T 12:01:02 AM
t 12:01 AM
u 2016-09-05 00:01:02Z
Y September, 2016
Note: The above list is using the en-US culture. A different culture can be specified for the FORMAT()
via the third parameter:
201695 4:01:02
The built-in functions GETDATE and GETUTCDATE each return the current date and time without a time
zone offset.
The return value of both functions is based on the operating system of the computer on which the
instance of SQL Server is running.
https://riptutorial.com/ 69
www.dbooks.org
The return value of GETDATE represents the current time in the same timezone as operating
system. The return value of GETUTCDATE represents the current UTC time.
Either function can be included in the SELECT clause of a query or as part of boolean expression in
the WHERE clause.
Examples:
-- example query that selects the current time in both the server time zone and UTC
SELECT GETDATE() as SystemDateTime, GETUTCDATE() as UTCDateTime
There are a few other built-in functions that return different variations of the current date-time:
SELECT
GETDATE(), --2016-07-21 14:27:37.447
GETUTCDATE(), --2016-07-21 18:27:37.447
CURRENT_TIMESTAMP, --2016-07-21 14:27:37.447
SYSDATETIME(), --2016-07-21 14:27:37.4485768
SYSDATETIMEOFFSET(),--2016-07-21 14:27:37.4485768 -04:00
SYSUTCDATETIME() --2016-07-21 18:27:37.4485768
General syntax:
To add a time measure, the number must be positive. To subtract a time measure, the number must
be negative.
Examples
NOTE: DATEADD also accepts abbreviations in the datepart parameter. Use of these abbreviations is
generally discouraged as they can be confusing (m vs mi, ww vs w, etc.).
These are the datepart values available to date & time functions:
https://riptutorial.com/ 70
datepart Abbreviations
quarter qq, q
month mm, m
dayofyear dy, y
day dd, d
week wk, ww
weekday dw, w
hour hh
minute mi, n
second ss, s
millisecond ms
microsecond mcs
nanosecond ns
General syntax:
It will return a positive number if datetime_expr is in the past relative to datetime_expr2, and a
negative number otherwise.
Examples
https://riptutorial.com/ 71
www.dbooks.org
SELECT DATEDIFF(HOUR, @oneYearAgo, @now) --8784
SELECT DATEDIFF(MINUTE, @oneYearAgo, @now) --527040
SELECT DATEDIFF(SECOND, @oneYearAgo, @now) --31622400
NOTE: DATEDIFF also accepts abbreviations in the datepart parameter. Use of these abbreviations
is generally discouraged as they can be confusing (m vs mi, ww vs w, etc.).
DATEDIFF can also be used to determine the offset between UTC and the local time of the SQL
Server. The following statement can be used to calculate the offset between UTC and local time
(including timezone).
DATEPART returns the specified datepart of the specified datetime expression as a numeric value.
DATENAME returns a character string that represents the specified datepart of the specified date. In
practice DATENAME is mostly useful for getting the name of the month or the day of the week.
There are also some shorthand functions to get the year, month or day of a datetime expression,
which behave like DATEPART with their respective datepart units.
Syntax:
Examples:
NOTE: DATEPART and DATENAME also accept abbreviations in the datepart parameter. Use of these
https://riptutorial.com/ 72
abbreviations is generally discouraged as they can be confusing (m vs mi, ww vs w, etc.).
Using the DATEADD and DATEDIFF functions, it's possible to return the last date of a month.
The EOMONTH function provides a more concise way to return the last date of a month, and has an
optional parameter to offset the month.
This function will take 2 datetime parameters, the DOB, and a date to check the age at
RETURN @age
https://riptutorial.com/ 73
www.dbooks.org
END
SELECT dbo.Calc_Age('2000-01-01',Getdate())
In Transact SQL , you may define an object as Date (or DateTime) using the [DATEFROMPARTS][1] (or
[DATETIMEFROMPARTS][1]) function like following:
The parameters you provide are Year, Month, Day for the DATEFROMPARTS function and, for the
DATETIMEFROMPARTS function you will need to provide year, month, day, hour, minutes, seconds and
milliseconds.
These methods are useful and worth being used because using the plain string to build a date(or
datetime) may fail depending on the host machine region, location or date format settings.
Sample
Date Format SQL Statement
Output
SELECT RIGHT(CONVERT(VARCHAR(10),
SYSDATETIME(), 20), 8) AS [YY-MM-DD]
YY-MM-DD 11-06-08
SELECT REPLACE(CONVERT(VARCHAR(8),
SYSDATETIME(), 11), '/', '-') AS [YY-MM-DD]
SELECT RIGHT(CAST(YEAR(SYSDATETIME()) AS
YY-M-D VARCHAR(4)), 2) + '-' + CAST(MONTH(SYSDATETIME()) AS 11-6-8
VARCHAR(2)) + '-' + CAST(DAY(SYSDATETIME()) AS
https://riptutorial.com/ 74
Sample
Date Format SQL Statement
Output
VARCHAR(2)) AS [YY-M-D]
SELECT RIGHT(CAST(YEAR(SYSDATETIME()) AS
YY-M VARCHAR(4)), 2) + '-' + CAST(MONTH(SYSDATETIME()) AS 11-6
VARCHAR(2)) AS [YY-M]
SELECT RIGHT(CONVERT(VARCHAR(10),
MM-YYYY 06-2011
SYSDATETIME(), 105), 7) AS [MM-YYYY]
https://riptutorial.com/ 75
www.dbooks.org
Sample
Date Format SQL Statement
Output
https://riptutorial.com/ 76
Sample
Date Format SQL Statement
Output
SELECT RIGHT(CAST(YEAR(SYSDATETIME()) AS
VARCHAR(4)), 2) + '/' + CAST(MONTH(SYSDATETIME()) AS
YY/M/D 11/6/8
VARCHAR(2)) + '/' + CAST(DAY(SYSDATETIME()) AS
VARCHAR(2)) AS [YY/M/D]
SELECT RIGHT(CONVERT(VARCHAR(10),
MM/YYYY 06/2011
SYSDATETIME(), 103), 7) AS [MM/YYYY]
SELECT RIGHT(CAST(YEAR(SYSDATETIME()) AS
YY/M VARCHAR(4)), 2) + '/' + CAST(MONTH(SYSDATETIME()) AS 11/6
VARCHAR(2)) AS [YY/M]
https://riptutorial.com/ 77
www.dbooks.org
Sample
Date Format SQL Statement
Output
SELECT REPLACE(CONVERT(VARCHAR(10),
MM.DD.YYYY 06.08.2011
SYSDATETIME(), 101), '/', '.') AS [MM.DD.YYYY]
SELECT REPLACE(CONVERT(VARCHAR(8),
MM.DD.YY 06.08.11
SYSDATETIME(), 1), '/', '.') AS [MM.DD.YY]
SELECT RIGHT(CAST(YEAR(SYSDATETIME()) AS
VARCHAR(4)), 2) + '.' + CAST(MONTH(SYSDATETIME()) AS
YY.M.D 11.6.8
VARCHAR(2)) + '.' + CAST(DAY(SYSDATETIME()) AS
VARCHAR(2)) AS [YY.M.D]
SELECT RIGHT(CONVERT(VARCHAR(10),
MM.YYYY 06.2011
SYSDATETIME(), 104), 7) AS [MM.YYYY]
https://riptutorial.com/ 78
Sample
Date Format SQL Statement
Output
4), 5) AS [MM.YY]
SELECT RIGHT(CAST(YEAR(SYSDATETIME()) AS
YY.M VARCHAR(4)), 2) + '.' + CAST(MONTH(SYSDATETIME()) AS 11.6
VARCHAR(2)) AS [YY.M]
SELECT REPLACE(CONVERT(VARCHAR(10),
MMDDYYYY 06082011
SYSDATETIME(), 101), '/', '') AS [MMDDYYYY]
SELECT REPLACE(CONVERT(VARCHAR(8),
MMDDYY 060811
SYSDATETIME(), 1), '/', '') AS [MMDDYY]
SELECT REPLACE(CONVERT(VARCHAR(10),
DDMMYYYY 08062011
SYSDATETIME(), 103), '/', '') AS [DDMMYYYY]
SELECT REPLACE(CONVERT(VARCHAR(8),
DDMMYY 080611
SYSDATETIME(), 3), '/', '') AS [DDMMYY]
SELECT RIGHT(REPLACE(CONVERT(VARCHAR(10),
MMYYYY 062011
SYSDATETIME(), 103), '/', ''), 6) AS [MMYYYY]
SELECT RIGHT(REPLACE(CONVERT(VARCHAR(8),
MMYY 0611
SYSDATETIME(), 3), '/', ''), 4) AS [MMYY]
https://riptutorial.com/ 79
www.dbooks.org
Sample
Date Format SQL Statement
Output
SELECT REPLACE(RIGHT(CONVERT(VARCHAR(9),
Mon-YY Jun-08
SYSDATETIME(), 6), 6), ' ', '-') AS [Mon-YY]
SELECT REPLACE(RIGHT(CONVERT(VARCHAR(11),
Mon-YYYY Jun-2011
SYSDATETIME(), 106), 8), ' ', '-') AS [Mon-YYYY]
SELECT REPLACE(CONVERT(VARCHAR(9),
DD-Mon-YY 08-Jun-11
SYSDATETIME(), 6), ' ', '-') AS [DD-Mon-YY]
https://riptutorial.com/ 80
Chapter 24: DBCC
Examples
DBCC maintenance commands
DBCC commands enable user to maintain space in database, clean caches, shrink databases and
tables.
Examples are:
DBCC DROPCLEANBUFFERS
Removes all clean buffers from the buffer pool, and columnstore objects from the columnstore
object pool.
DBCC FREEPROCCACHE
-- or
DBCC FREEPROCCACHE (0x060006001ECA270EC0215D05000000000000000000000000);
Removes all SQL query in plan cache. Every new plan will be recompiled: You can specify plan
handle, query handle to clean plans for the specific query plan or SQL statement.
Cleans all cached entries created by system. It can clean entries o=in all or some specified
resource pool (myresourcepool in the example above)
DBCC FLUSHAUTHCACHE
Empties the database authentication cache containing information about logins and firewall rules.
Shrinks database MyDB to 10%. Second parameter is optional. You can use database id instead
of name.
Shrinks data file named DataFile1 in the current database. Target size is 7 MB (tis parameter is
optional).
https://riptutorial.com/ 81
www.dbooks.org
Reclaims a space from specified table
ALTER TABLE Table1 WITH NOCHECK ADD CONSTRAINT chkTab1 CHECK (Col1 > 100);
GO
DBCC CHECKCONSTRAINTS(Table1);
--OR
DBCC CHECKCONSTRAINTS ('Table1.chkTable1');
Check constraint is added with nocheck options, so it will not be checked on existing data. DBCC
will trigger constraint check.
DBCC PROCCACHE
Returns the current output buffer in hexadecimal and ASCII format for the specified session_id
(and optional request_id).
Displays the last statement sent from a client to an instance of Microsoft SQL Server.
Trace flags in SQL Server are used to modify behavior of SQL server, turn on/off some features.
DBCC commands can control trace flags:
The following example switches on trace flag 3205 globally and 3206 for the current session:
https://riptutorial.com/ 82
DBCC TRACEON (3205, -1);
DBCC TRACEON (3206);
The following example switches off trace flag 3205 globally and 3206 for the current session:
The following example displays the status of trace flags 2528 and 3205:
DBCC statement
DBCC statements act as Database Console Commands for SQL Server. To get the syntax
information for the specified DBCC command use DBCC HELP (...) statement.
The following example returns all DBCC statements for which Help is available:
https://riptutorial.com/ 83
www.dbooks.org
Chapter 25: DBMAIL
Syntax
• sp_send_dbmail [ [ @profile_name = ] 'profile_name' ] [ , [ @recipients = ] 'recipients [ ; ...n ]'
] [ , [ @copy_recipients = ] 'copy_recipient [ ; ...n ]' ] [ , [ @blind_copy_recipients = ]
'blind_copy_recipient [ ; ...n ]' ] [ , [ @from_address = ] 'from_address' ] [ , [ @reply_to = ]
'reply_to' ] [ , [ @subject = ] 'subject' ] [ , [ @body = ] 'body' ] [ , [ @body_format = ]
'body_format' ] [ , [ @importance = ] 'importance' ] [ , [ @sensitivity = ] 'sensitivity' ] [ , [
@file_attachments = ] 'attachment [ ; ...n ]' ] [ , [ @query = ] 'query' ] [ , [
@execute_query_database = ] 'execute_query_database' ] [ , [
@attach_query_result_as_file = ] attach_query_result_as_file ] [ , [
@query_attachment_filename = ] query_attachment_filename ] [ , [ @query_result_header =
] query_result_header ] [ , [ @query_result_width = ] query_result_width ] [ , [
@query_result_separator = ] 'query_result_separator' ] [ , [ @exclude_query_output = ]
exclude_query_output ] [ , [ @append_query_error = ] append_query_error ] [ , [
@query_no_truncate = ] query_no_truncate ] [ , [@query_result_no_padding = ]
@query_result_no_padding ] [ , [ @mailitem_id = ] mailitem_id ] [ OUTPUT ]
Examples
Send simple email
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'The Profile Name',
@recipients = '[email protected]',
@body = 'This is a simple email sent from SQL Server.',
@subject = 'Simple email'
This attaches the results of the query SELECT * FROM Users and sends it to [email protected]
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'The Profile Name',
@recipients = '[email protected]',
@query = 'SELECT * FROM Users',
@subject = 'List of users',
@attach_query_result_as_file = 1;
https://riptutorial.com/ 84
DECLARE @html VARCHAR(MAX);
SET @html = CONCAT
(
'<html><body>',
'<h1>Some Header Text</h1>',
'<p>Some paragraph text</p>',
'</body></html>'
)
Then use the @html variable with the @body argument. The HTML string can also be passed directly
to @body, although it may make the code harder to read.
EXEC msdb.dbo.sp_send_dbmail
@recipients='[email protected]',
@subject = 'Some HTML content',
@body = @html,
@body_format = 'HTML';
https://riptutorial.com/ 85
www.dbooks.org
Chapter 26: Delimiting special characters and
reserved words
Remarks
Generally speaking, it is best not to use T-SQL Reserved Words as table names, column names,
programming object names, alias etc. So the method to escape these keywords should only be
applied if you are inheriting a database design that cannot be changed.
For reserved words, usage of the square brackets is not mandatory. When using a tool such as
SQL Server Management Studio, the reserved words will be highlighted to bring attention to the
fact that they are reserved.
Examples
Basic Method
The basic method to escape reserved words for SQL Server is the use of the square brackets ([
and ]). For example, Description and Name are reserved words; however, if there is an object
using both as names, the syntax used is:
SELECT [Description]
FROM dbo.TableName
WHERE [Name] = 'foo'
The only special character for SQL Server is the single quote ' and it is escaped by doubling its
usage. For example, to find the name O'Shea in the same table, the following syntax would be
used:
SELECT [Description]
FROM dbo.TableName
WHERE [Name] = 'O''Shea'
https://riptutorial.com/ 86
Chapter 27: Drop Keyword
Introduction
The Drop keyword can be used with various SQL objects, this topic provides quick examples of
different usage with database objects.
Remarks
Links to MSDN.
Examples
Drop tables
The DROP TABLE command remove the table definitions and all data, indexes, triggers,
constraints and related permissions.
Before you drop a table, you should check if there are any object (views, stored procedures, other
tables) that reference the table.
You cannot drop a table referenced by another table by FOREIGN KEY. You must first drop the
FOREIGN KEY referencing it.
You can drop a table referenced by a view or stored procedure, but after dropping the table, the
view or stored procedure is no longer usable.
The Syntax
Examples
Remove the table with name TABLE_1 from current database and default schema dbo
https://riptutorial.com/ 87
www.dbooks.org
DROP TABLE Table_1;
Remove the table with TABLE_1 from database HR and default schema dbo
Remove the table with TABLE_1 from database HR and schema external
Drop Databases
The DROP DATABASE command removes a database catalog, regardless of its state (offline,
read-only, suspect, etc.), from the current SQL Server instance.
A database cannot be dropped if there are any database snapshots associated with it, as the
database snapshots must be dropped first.
A database drop removes all of the physical disk files (unless it's offline) used by the database
unless you use the Stored Procedure 'sp_detach_db'.
A database snapshot drop deletes the snapshot from the SQL Server instance and deletes the
physical files also used by it.
A dropped database can only be re-created by restoring a backup (not from a database snapshot
either).
The Syntax
Examples
Removing a snapshot
https://riptutorial.com/ 88
DROP DATABASE Database1_snapshot17;
1. ##GlobalTempTable is a type of temporary table that is sheered between all user's sessions.
2. #LocalTempTable temp tab - it is a type of temporary table that only exists in current scope
(only in actual process - you can get id of your current process by SELECT @@SPID)
https://riptutorial.com/ 89
www.dbooks.org
Chapter 28: Dynamic data masking
Examples
Mask email address using Dynamic data masking
If you have email column you can mask it with email() mask:
When user tries to select emails from Company table, he will get something like the following
values:
You can add partial mask on the column that will show few characters from te beginning and the
end of the string and show mask instead of the characters in the middle:
In the parameters of the partial function you can specify how many values from the beginning will
be shown, how many values from the end will be shown, and what woudl be the pattern that is
shown in the middle.
When user tries to select emails from Company table, he will get something like the following
values:
(381)XXXXXXX39
(360)XXXXXXX01
(415)XXXXXXX05
Random mask will show a rundom number from the specified range instead of the actual value:
https://riptutorial.com/ 90
Note that is some cases displayed value might match actual value in column (if randomly selected
number matches value in the cell).
If you add default mask on the column, instead of actual value in SELECT statement will be shown
mask:
You can grant in-privileged users right to see unmasked values using the following statement:
If some user already has unmask permission, you can revoke this permission:
https://riptutorial.com/ 91
www.dbooks.org
Chapter 29: Dynamic SQL
Examples
Execute SQL statement provided as string
In some cases, you would need to execute SQL query placed in string. EXEC, EXECUTE, or
system procedure sp_executesql can execute any SQL query provided as string:
This procedure will return the same result-set as SQL query provided as statement text.
sp_executesql can execute SQL query provided as string literal, variable/parameter, or even
expression:
You need QUOTENAME function to escape special characters in @table variable. Without this
function you would get syntax error if @table variable contains something like spaces, brackets, or
any other special character.
You can execute SQL query as different user using AS USER = 'name of database user'
SQL query will be executed under dbo database user. All permission checks applicable to dbo
user will be checked on SQL query.
SET @sql = N'SELECT COUNT(*) FROM AppUsers WHERE Username = ''' + @user + ''' AND Password =
''' + @pass + ''''
EXEC(@sql)
https://riptutorial.com/ 92
If value of user variable is myusername'' OR 1=1 -- the following query will be executed:
SELECT COUNT(*)
FROM AppUsers
WHERE Username = 'myusername' OR 1=1 --' AND Password = ''
Comment at the end of value of variable @username will comment-out trailing part of the query
and condition 1=1 will be evaluated. Application that checks it there at least one user returned by
this query will return count greater than 0 and login will succeed.
Using this approach attacker can login into application even if he don't know valid username and
password.
In order to avoid injection and escaping problems, dynamic SQL queries should be executed with
parameters, e.g.:
SET @sql = N'SELECT COUNT(*) FROM AppUsers WHERE Username = @user AND Password = @pass
EXEC sp_executesql @sql, '@user nvarchar(50), @pass nvarchar(50)', @username, @password
Second parameter is a list of parameters used in query with their types, after this list are provided
variables that will be used as parameter values.
https://riptutorial.com/ 93
www.dbooks.org
Chapter 30: Dynamic SQL Pivot
Introduction
This topic covers how to do a dynamic pivot in SQL Server.
Examples
Basic Dynamic SQL Pivot
DECLARE
@cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
https://riptutorial.com/ 94
Read Dynamic SQL Pivot online: https://riptutorial.com/sql-server/topic/10751/dynamic-sql-pivot
https://riptutorial.com/ 95
www.dbooks.org
Chapter 31: Encryption
Parameters
Optional
Details
Parameters
Remarks
Creation of a DER certificate will work fine. When a Base64 certificate is used however, SQL
server will complain with the cryptic message:
Import your Base64 certificate to your OS's certificate store to be able to re-export it into DER
binary format.
Another important thing to do is having an Encryption Hierarchy so that one protects the other, all
the way to OS level. See the article on 'Encryption of database/TDE'
Examples
Encryption by certificate
https://riptutorial.com/ 96
SELECT EncryptByCert(Cert_ID('My_New_Cert'),
'This text will get encrypted') encryption_test
Usually, you would encrypt with a symmetric key, that key would get encrypted by the asymmetric
key (public key) from your certificate.
Also, note that encryption is limited to certain lengths depending on key length and returns NULL
otherwise. Microsoft writes: "The limits are: a 512 bit RSA key can encrypt up to 53 bytes, a 1024
bit key can encrypt up to 117 bytes, and a 2048 bit key can encrypt up to 245 bytes."
EncryptByAsymKey has the same limits. For UNICODE this would be divided by 2 (16 bits per
character), so 58 characters for a 1024 bit key.
Encryption of database
USE TDE
CREATE DATABASE ENCRYPTION KEY
WITH ALGORITHM = AES_256
ENCRYPTION BY SERVER CERTIFICATE My_New_Cert
GO
-- Encrypt
SELECT EncryptByKey(Key_GUID('SSN_Key_01'), 'This text will get encrypted');
Encryption by passphrase
This will also encrypt but then by passphrase instead of asymmetric(certificate) key or by an
explicit symmetric key.
https://riptutorial.com/ 97
www.dbooks.org
Chapter 32: Export data in txt file by using
SQLCMD
Syntax
• sqlcmd -S SHERAZM-E7450\SQL2008R2 -d Baseline_DB_Aug_2016 -o c:\employee.txt -Q
"select * from employee"
Examples
By using SQLCMD on Command Prompt
Command Structure is
https://riptutorial.com/ 98
Chapter 33: File Group
Examples
Create filegroup in database
We can create it by two way. First from database properties designer mode:
USE master;
GO
-- Create the database with the default data
-- filegroup and a log file. Specify the
-- growth increment and the max size for the
https://riptutorial.com/ 99
www.dbooks.org
-- primary data file.
go
ALTER DATABASE TestDB MODIFY FILEGROUP TestDB_FG1 DEFAULT;
go
https://riptutorial.com/ 100
Chapter 34: Filestream
Introduction
FILESTREAM integrates the SQL Server Database Engine with an NTFS file system by storing
varbinary(max) binary large object (BLOB) data as files on the file system. Transact-SQL
statements can insert, update, query, search, and back up FILESTREAM data. Win32 file system
interfaces provide streaming access to the data.
Examples
Example
https://riptutorial.com/ 101
www.dbooks.org
Chapter 35: FOR JSON
Examples
FOR JSON PATH
Formats results of SELECT query as JSON text. FOR JSON PATH clause is added after query:
Column names will be used as keys in JSON, and cell values will be generated as JSON values.
Result of the query would be an array of JSON objects:
[
{"object_id":3,"name":"sysrscols","type":"S "},
{"object_id":5,"name":"sysrowsets","type":"S "},
{"object_id":6,"name":"sysclones","type":"S "}
]
NULL values in principal_id column will be ignored (they will not be generated).
FOR JSON PATH enables you to control format of the output JSON using column aliases:
Column alias will be used as a key name. Dot-separated column aliases (data.name and
data.type) will be generated as nested objects. If two column have the same prefix in dot notation,
they will be grouped together in single object (data in this example):
[
{"id":3,"data":{"name":"sysrscols","type":"S "}},
{"id":5,"data":{"name":"sysrowsets","type":"S "}},
{"id":6,"data":{"name":"sysclones","type":"S "}}
]
https://riptutorial.com/ 102
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
{"object_id":3,"name":"sysrscols","type":"S "}
INCLUDE_NULL_VALUES
FOR JSON clause ignores NULL values in cells. If you want to generate "key": null pairs for cells
that contain NULL values, add INCLUDE_NULL_VALUES option in the query:
[
{"object_id":3,"name":"sysrscols","type":"S ","principal_id":null},
{"object_id":5,"name":"sysrowsets","type":"S ","principal_id":null},
{"object_id":6,"name":"sysclones","type":"S ","principal_id":null}
]
Wraps returned JSON array in additional root object with specified key:
Result of the query would be array of JSON objects inside the wrapper object:
{
"data":[
{"object_id":3,"name":"sysrscols","type":"S "},
{"object_id":5,"name":"sysrowsets","type":"S "},
{"object_id":6,"name":"sysclones","type":"S "}
]
}
Automatically nests values from the second table as a nested sub-array of JSON objects:
https://riptutorial.com/ 103
www.dbooks.org
[
{
"object_id":3,
"name":"sysrscols",
"c":[
{"column_id":12,"name":"bitpos"},
{"column_id":6,"name":"cid"}
]
},
{
"object_id":5,
"name":"sysrowsets",
"c":[
{"column_id":13,"name":"colguid"},
{"column_id":3,"name":"hbcolid"},
{"column_id":8,"name":"maxinrowlen"}
]
}
]
If you need some complex JSON structure that cannot be created using FOR JSON PATH or FOR
JSON AUTO, you can customize your JSON output by putting FOR JSON sub-queries as column
expressions:
Each sub-query will produce JSON result that will be included in the main JSON content.
https://riptutorial.com/ 104
Chapter 36: FOR XML PATH
Remarks
There are also several other FOR XML modes:
Examples
Hello World XML
<example>Hello World</example>
Specifying namespaces
WITH XMLNAMESPACES (
DEFAULT 'http://www.w3.org/2000/svg',
'http://www.w3.org/1999/xlink' AS xlink
)
SELECT
'example.jpg' AS 'image/@xlink:href',
'50px' AS 'image/@width',
'50px' AS 'image/@height'
FOR XML PATH('svg')
SELECT
'XPath example' AS 'head/title',
'This example demonstrates ' AS 'body/p',
'https://www.w3.org/TR/xpath/' AS 'body/p/a/@href',
'XPath expressions' AS 'body/p/a'
FOR XML PATH('html')
<html>
https://riptutorial.com/ 105
www.dbooks.org
<head>
<title>XPath example</title>
</head>
<body>
<p>This example demonstrates <a href="https://www.w3.org/TR/xpath/">XPath
expressions</a></p>
</body>
</html>
In FOR XML PATH, columns without a name become text nodes. NULL or '' therefore become empty
text nodes. Note: you can convert a named column to an unnamed one by using AS *
<row>
<LIN NUM="1">
<FLD NAME="REF">100001</FLD>
<FLD NAME="DES">Normal</FLD>
<FLD NAME="QTY">1</FLD>
</LIN>
<LIN NUM="2">
<FLD NAME="REF">100002</FLD>
<FLD NAME="DES">Foobar</FLD>
<FLD NAME="QTY">1</FLD>
</LIN>
<LIN NUM="3">
<FLD NAME="REF">100003</FLD>
<FLD NAME="DES">Hello World</FLD>
<FLD NAME="QTY">2</FLD>
</LIN>
</row>
Using (empty) text nodes helps to separate the previously output node from the next one, so that
SQL Server knows to start a new element for the next column. Otherwise, it gets confused when
the attribute already exists on what it thinks is the "current" element.
For example, without the the empty strings between the element and the attribute in the SELECT
statement, SQL Server gives an error:
Also note that this example also wrapped the XML in a root element named row, specified by
ROOT('row')
https://riptutorial.com/ 106
Using FOR XML PATH to concatenate values
The FOR XML PATH can be used for concatenating values into string. The example below
concatenates values into a CSV string:
SELECT STUFF
(
(
SELECT ',' + [FirstName]
FROM @DataSource
ORDER BY [rowID] DESC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1
,1
,''
);
• the ORDER BY clause can be used to order the values in a preferred way
• if a longer value is used as the concatenation separator, the STUFF function parameter must
be changed too;
SELECT STUFF
(
(
SELECT '---' + [FirstName]
FROM @DataSource
ORDER BY [rowID] DESC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1
,3 -- the "3" could also be represented as: LEN('---') for clarity
,''
);
• as the TYPE option and .value function are used, the concatenation works with NVARCHAR(MAX)
string
https://riptutorial.com/ 107
www.dbooks.org
Chapter 37: Foreign Keys
Examples
Foreign key relationship/constraint
Foreign keys enables you to define relationship between two tables. One (parent) table need to
have primary key that uniquely identifies rows in the table. Other (child) table can have value of
the primary key from the parent in one of the columns. FOREIGN KEY REFERENCES constraint
ensures that values in child table must exist as a primary key value in the parent table.
In this example we have parent Company table with CompanyId primary key, and child Employee
table that has id of the company where this employee works.
foreign key references ensures that values inserted in Employee.CompanyId column must also
exist in Company.CompanyId column. Also, nobody can delete company in company table if there
is ate least one employee with a matching companyId in child table.
FOREIGN KEY relationship ensures that rows in two tables cannot be "unlinked".
Let's assume that we have one row in Company table with companyId 1. We can insert row in
employee table that has companyId 1:
Msg 547, Level 16, State 0, Line 12 The INSERT statement conflicted with the FOREIGN KEY
constraint "FK__Employee__Compan__1EE485AA". The conflict occurred in database "MyDb",
table "dbo.Company", column 'CompanyId'. The statement has been terminated.
Also, we cannot delete parent row in company table as long as there is at least one child row in
https://riptutorial.com/ 108
employee table that references it.
Msg 547, Level 16, State 0, Line 14 The DELETE statement conflicted with the REFERENCE
constraint "FK__Employee__Compan__1EE485AA". The conflict occurred in database "MyDb",
table "dbo.Employee", column 'CompanyId'. The statement has been terminated.
Foreign key relationship ensures that Company and employee rows will not be "unlinked".
FOREIGN KEY constraint can be added on existing tables that are still not in relationship. Imagine
that we have Company and Employee tables where Employee table CompanyId column but don't
have foreign key relationship. ALTER TABLE statement enables you to add foreign key constraint
on an existing column that references some other table and primary key in that table:
FOREIGN KEY columns with constraint can be added on existing tables that are still not in
relationship. Imagine that we have Company and Employee tables where Employee table don't
have CompanyId column. ALTER TABLE statement enables you to add new column with foreign
key constraint that references some other table and primary key in that table:
sys.foreignkeys system view returns information about all foreign key relationships in database:
select name,
OBJECT_NAME(referenced_object_id) as [parent table],
OBJECT_NAME(parent_object_id) as [child table],
delete_referential_action_desc,
update_referential_action_desc
from sys.foreign_keys
https://riptutorial.com/ 109
www.dbooks.org
Chapter 38: Full-Text Indexing
Examples
A. Creating a unique index, a full-text catalog, and a full-text index
The following example creates a unique index on the JobCandidateID column of the
HumanResources.JobCandidate table of the AdventureWorks2012 sample database. The
example then creates a default full-text catalog, ft. Finally, the example creates a full-text index on
the Resume column, using the ft catalog and the system stoplist.
USE AdventureWorks2012;
GO
CREATE UNIQUE INDEX ui_ukJobCand ON HumanResources.JobCandidate(JobCandidateID);
CREATE FULLTEXT CATALOG ft AS DEFAULT;
CREATE FULLTEXT INDEX ON HumanResources.JobCandidate(Resume)
KEY INDEX ui_ukJobCand
WITH STOPLIST = SYSTEM;
GO
https://www.simple-talk.com/sql/learn-sql-server/understanding-full-text-indexing-in-sql-server/
https://msdn.microsoft.com/en-us/library/cc879306.aspx
https://msdn.microsoft.com/en-us/library/ms142571.aspx
USE AdventureWorks2012;
GO
CREATE FULLTEXT CATALOG production_catalog;
GO
CREATE FULLTEXT INDEX ON Production.ProductReview
(
ReviewerName
Language 1033,
EmailAddress
Language 1033,
Comments
Language 1033
)
KEY INDEX PK_ProductReview_ProductReviewID
ON production_catalog;
GO
USE AdventureWorks2012;
GO
CREATE FULLTEXT INDEX ON Production.Document
https://riptutorial.com/ 110
(
Title
Language 1033,
DocumentSummary
Language 1033,
Document
TYPE COLUMN FileExtension
Language 1033
)
KEY INDEX PK_Document_DocumentID
WITH STOPLIST = SYSTEM, SEARCH PROPERTY LIST = DocumentPropertyList, CHANGE_TRACKING
OFF, NO POPULATION;
GO
Full-Text Search
SELECT product_id
FROM products
WHERE CONTAINS(product_description, ”Snap Happy 100EZ” OR FORMSOF(THESAURUS,’Snap Happy’) OR
‘100EZ’)
AND product_cost < 200 ;
SELECT candidate_name,SSN
FROM candidates
WHERE CONTAINS(candidate_resume,”SQL Server”) AND candidate_division =DBA;
https://riptutorial.com/ 111
www.dbooks.org
Chapter 39: Generating a range of dates
Parameters
Parameter Details
Remarks
Most experts seem to recommend creating a Dates table instead of generating a sequence on the
fly. See http://dba.stackexchange.com/questions/86435/filling-in-date-holes-in-grouped-by-date-
sql-data
Examples
Generating Date Range With Recursive CTE
The default MaxRecursion setting is 100. Generating more than 100 dates using this method will
require the Option (MaxRecursion N) segment of the query, where N is the desired MaxRecursion
setting. Setting this to 0 will remove the MaxRecursion limitation altogether.
Another way you can generate a range of dates is by utilizing a Tally Table to create the dates
between the range:
https://riptutorial.com/ 112
;With
E1(N) As (Select 1 From (Values (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) DT(N)),
E2(N) As (Select 1 From E1 A Cross Join E1 B),
E4(N) As (Select 1 From E2 A Cross Join E2 B),
E6(N) As (Select 1 From E4 A Cross Join E2 B),
Tally(N) As
(
Select Row_Number() Over (Order By (Select Null))
From E6
)
Select DateAdd(Day, N - 1, @FromDate) Date
From Tally
Where N <= DateDiff(Day, @FromDate, @ToDate) + 1
https://riptutorial.com/ 113
www.dbooks.org
Chapter 40: GROUP BY
Examples
Simple Grouping
Orders Table
1 2 5 100
1 3 2 200
1 4 1 500
2 1 4 50
3 5 6 700
When grouping by a specific column, only unique values of this column are returned.
SELECT customerId
FROM orders
GROUP BY customerId;
Return value:
customerId
Aggregate functions like count() apply to each group and not to the complete table:
SELECT customerId,
COUNT(productId) as numberOfProducts,
sum(price) as totalPrice
FROM orders
GROUP BY customerId;
Return value:
https://riptutorial.com/ 114
customerId numberOfProducts totalPrice
1 3 800
2 1 50
3 1 700
18 luke 3
21 luke 2
18 matt 1
21 matt 2
Group by is often used with join statement. Let's assume we have two tables. The first one is the
table of students:
1 Matt Jones 20
2 Frank Blue 21
https://riptutorial.com/ 115
www.dbooks.org
Id Full Name Age
3 Anthony Angel 18
Subject_Id Subject
1 Maths
2 P.E.
3 Physics
And because one student can attend many subjects and one subject can be attended by many
students (therefore N:N relationship) we need to have third "bounding" table. Let's call the table
Students_subjects:
Subject_Id Student_Id
1 1
2 2
2 1
3 2
1 3
1 1
Now lets say we want to know the number of subjects each student is attending. Here the
standalone GROUP BY statement is not sufficient as the information is not available through single
table. Therefore we need to use GROUP BY with the JOIN statement:
FullName SubjectNumber
Matt Jones 3
Frank Blue 2
https://riptutorial.com/ 116
FullName SubjectNumber
Anthony Angel 1
For an even more complex example of GROUP BY usage, let's say student might be able to
assign the same subject to his name more than once (as shown in table Students_Subjects). In
this scenario we might be able to count number of times each subject was assigned to a student
by GROUPing by more than one column:
HAVING
Because the WHERE clause is evaluated before GROUP BY, you cannot use WHERE to pare down results
of the grouping (typically an aggregate function, such as COUNT(*)). To meet this need, the HAVING
clause can be used.
https://riptutorial.com/ 117
www.dbooks.org
( 10, 'John' ),
( 11, 'Luke' )
If we want to get the number of orders each person has placed, we would use
and get
Name Orders
Matt 2
John 5
Luke 4
However, if we want to limit this to individuals who have placed more than two orders, we can add
a HAVING clause.
will yield
Name Orders
John 5
Luke 4
Note that, much like GROUP BY, the columns put in HAVING must exactly match their counterparts in
the SELECT statement. If in the above example we had instead said
The ROLLUP operator is useful in generating reports that contain subtotals and totals.
https://riptutorial.com/ 118
• CUBE generates a result set that shows aggregates for all combinations of values in the
selected columns.
• ROLLUP generates a result set that shows aggregates for a hierarchy of values in the
selected columns.
(7 row(s) affected)
If the ROLLUP keyword in the query is changed to CUBE, the CUBE result set is the same, except
these two additional rows are returned at the end:
https://technet.microsoft.com/en-us/library/ms189305(v=sql.90).aspx
https://riptutorial.com/ 119
www.dbooks.org
Chapter 41: IF...ELSE
Examples
Single IF statement
Like most of the other programming languages, T-SQL also supports IF..ELSE statements.
For example in the example below 1 = 1 is the expression, which evaluates to True and the control
enters the BEGIN..END block and the Print statement prints the string 'One is equal to One'
Multiple IF Statements
We can use multiple IF statement to check multiple expressions totally independent from each
other.
In the example below, each IF statement's expression is evaluated and if it is true the code inside
the BEGIN...END block is executed. In this particular example, the First and Third expressions are
true and only those print statements will be executed.
In a single IF..ELSE statement, if the expression evaluates to True in the IF statement the control
enters the first BEGIN..END block and only the code inside that block gets executed , Else block is
simply ignored.
On the other hand if the expression evaluates to False the ELSE BEGIN..END block gets executed and
the control never enters the first BEGIN..END Block.
https://riptutorial.com/ 120
In the Example below the expression will evaluate to false and the Else block will be executed
printing the string 'First expression was not true'
If we have Multiple IF...ELSE IF statements but we also want also want to execute some piece of
code if none of expressions are evaluated to True , then we can simple add a final ELSE block
which only gets executed if none of the IF or ELSE IF expressions are evaluated to true.
In the example below none of the IF or ELSE IF expression are True hence only ELSE block is
executed and prints 'No other expression is true'
IF ( 1 = 1 + 1 )
BEGIN
PRINT 'First If Condition'
END
ELSE IF (1 = 2)
BEGIN
PRINT 'Second If Else Block'
END
ELSE IF (1 = 3)
BEGIN
PRINT 'Third If Else Block'
END
ELSE
BEGIN
PRINT 'No other expression is true' --<-- Only this statement will be printed
END
More often than not we need to check multiple expressions and take specific actions based on
those expressions. This situation is handled using multiple IF...ELSE IF statements.
In this example all the expressions are evaluated from top to bottom. As soon as an expression
evaluates to true, the code inside that block is executed. If no expression is evaluated to true,
nothing gets executed.
IF (1 = 1 + 1)
BEGIN
PRINT 'First If Condition'
END
ELSE IF (1 = 2)
BEGIN
https://riptutorial.com/ 121
www.dbooks.org
PRINT 'Second If Else Block'
END
ELSE IF (1 = 3)
BEGIN
PRINT 'Third If Else Block'
END
ELSE IF (1 = 1) --<-- This is True
BEGIN
PRINT 'Last Else Block' --<-- Only this statement will be printed
END
https://riptutorial.com/ 122
Chapter 42: Index
Examples
Create Clustered index
With a clustered index the leaf pages contain the actual table rows. Therefore, there can be only
one clustered index.
Non-clustered indexes have a structure separate from the data rows. A non-clustered index
contains the non-clustered index key values and each key value entry has a pointer to the data
row that contains the key value. There can be maximum 999 non-clustered index on SQL Server
2008/ 2012.
SP_HELPINDEX tableName
Index on view
https://riptutorial.com/ 123
www.dbooks.org
CREATE VIEW View_Index02
WITH SCHEMABINDING
AS
SELECT c.CompanyName, o.OrderDate, o.OrderID, od.ProductID
FROM dbo.Customers C
INNER JOIN dbo.orders O ON c.CustomerID=o.CustomerID
INNER JOIN dbo.[Order Details] od ON o.OrderID=od.OrderID
GO
Drop index
sys.dm_db_index_physical_stats (
{ database_id | NULL | 0 | DEFAULT }
, { object_id | NULL | 0 | DEFAULT }
, { index_id | NULL | 0 | -1 | DEFAULT }
, { partition_number | NULL | 0 | DEFAULT }
, { mode | NULL | DEFAULT }
)
Sample :
>30% REBUILD
https://riptutorial.com/ 124
ALTER INDEX All ON tableName REBUILD;
This drops the index and recreates it, removing fragementation, reclaims disk space and reorders
index pages.
which will use minimal system resources and defragments the leaf level of clustered and
nonclustered indexes on tables and views by physically reordering the leaf-level pages to match
the logical, left to right, order of the leaf nodes
Index investigations
You could use "SP_HELPINDEX Table_Name", but Kimberly Tripp has a stored procedure (that
can be found here), which is better example, as it shows more about the indexes, including
columns and filter definition, for example:
Usage:
USE Adventureworks
EXEC sp_SQLskills_SQL2012_helpindex 'dbo.Product'
Alternatively, Tibor Karaszi has a stored procedure (found here). The later will show information on
index usage too, and optionally provide a list of index suggestions. Usage:
USE Adventureworks
EXEC sp_indexinfo 'dbo.Product'
https://riptutorial.com/ 125
www.dbooks.org
Chapter 43: In-Memory OLTP (Hekaton)
Examples
Create Memory Optimized Table
use SQL2016_Demo
go
CONSTRAINT CHK_soSessionC_SpidFilter
https://riptutorial.com/ 126
CHECK ( SpidFilter = @@spid ),
)
WITH
(MEMORY_OPTIMIZED = ON,
DURABILITY = SCHEMA_AND_DATA); --or DURABILITY = SCHEMA_ONLY
go
Show created .dll files and tables for Memory Optimized Tables
SELECT
OBJECT_ID('MemOptTable1') AS MemOptTable1_ObjectID,
OBJECT_ID('MemOptTable2') AS MemOptTable2_ObjectID
GO
SELECT
name,description
FROM sys.dm_os_loaded_modules
WHERE name LIKE '%XTP%'
GO
SELECT
name,type_desc,durability_desc,Is_memory_Optimized
FROM sys.tables
WHERE Is_memory_Optimized = 1
GO
To memory-optimize this table type simply add the option memory_optimized=on, and add an index if
there is none on the original type:
https://riptutorial.com/ 127
www.dbooks.org
)WITH (MEMORY_OPTIMIZED=ON);
1. Create a new SCHEMA_ONLY memory-optimized table with the same schema as the global
##temp table
• Ensure the new table has at least one index
2. Change all references to ##temp in your Transact-SQL statements to the new memory-
optimized table temp
3. Replace the DROP TABLE ##temp statements in your code with DELETE FROM temp, to clean up the
contents
4. Remove the CREATE TABLE ##temp statements from your code – these are now redundant
more informations
For faster performance you can memory-optimize your table variable. Here is the T-SQL for a
traditional table variable:
To define memory-optimized variables, you must first create a memory-optimized table type and
then declare a variable from it:
https://riptutorial.com/ 128
Col1 INT NOT NULL INDEX ix1,
Col2 CHAR(10)
)
WITH
(MEMORY_OPTIMIZED = ON);
Result:
Col1 Col2
1 1
2 2
3 3
4 4
5 5
6 6
more informations
https://riptutorial.com/ 129
www.dbooks.org
Chapter 44: Insert
Examples
Add a row to a table named Invoices
• Column names are required if the table you are inserting into contains a column with the
IDENTITY attribute.
https://riptutorial.com/ 130
Chapter 45: INSERT INTO
Introduction
The INSERT INTO statement is used to insert new records in a table.
Examples
INSERT Hello World INTO table
To do an insert on specific columns (as opposed to all of them) you must specify the columns you
want to update.
This will only work if the columns that you did not list are nullable, identity, timestamp data type or
computed columns; or columns that have a default value constraint. Therefore, if any of them are
non-nullable, non-identity, non-timestamp, non-computed, non-default valued columns...then
attempting this kind of insert will trigger an error message telling you that you have to provide a
value for the applicable field(s).
To insert multiple rows of data in earlier versions of SQL Server, use "UNION ALL" like so:
https://riptutorial.com/ 131
www.dbooks.org
INSERT INTO USERS (FIRST_NAME, LAST_NAME)
SELECT 'James', 'Bond' UNION ALL
SELECT 'Miss', 'Moneypenny' UNION ALL
SELECT 'Raoul', 'Silva'
Note, the "INTO" keyword is optional in INSERT queries. Another warning is that SQL server only
supports 1000 rows in one INSERT so you have to split them in batches.
Or
Note that the second insert statement only allows the values in exactly the same order as the table
columns whereas in the first insert, the order of the values can be changed like:
When INSERTing, you can use OUTPUT INSERTED.ColumnName to get values from the newly inserted
row, for example the newly generated Id - useful if you have an IDENTITY column or any sort of
default or calculated value.
When programatically calling this (e.g., from ADO.net) you would treat it as a normal query and
read the values as if you would've made a SELECT-statement.
-- CREATE TABLE OutputTest ([Id] INT NOT NULL PRIMARY KEY IDENTITY, [Name] NVARCHAR(50))
If the ID of the recently added row is required inside the same set of query or stored procedure.
-- CREATE a table variable having column with the same datatype of the ID
https://riptutorial.com/ 132
SELECT id FROM @LastId
Note, 'student' in SELECT is a string constant that will be inserted in each row.
If required, you can select and insert data from/into the same table
https://riptutorial.com/ 133
www.dbooks.org
Chapter 46: Installing SQL Server on
Windows
Examples
Introduction
These are the available editions of SQL Server, as told by the Editions Matrix:
After downloading/acquiring SQL Server, the installation gets executed with SQLSetup.exe, which
is available as a GUI or a command-line program.
Installing via either of these will require you to specify a product key and run some initial
configuration that includes enabling features, separate services and setting the initial parameters
for each of them. Additional services and features can be enabled at any time by running the
SQLSetup.exe program in either the command-line or the GUI version.
https://riptutorial.com/ 134
Chapter 47: Isolation levels and locking
Remarks
I found this link - it's useful as a reference: "Isolation Levels"
Examples
Examples of setting the isolation level
1. READ UNCOMMITTED - means that a query in the current transaction can't access the modified
data from another transaction that is not yet committed - no dirty reads! BUT, nonrepeatable
reads and phantom reads are possible, because data can still be modified by other
transactions.
2. REPEATABLE READ - means that a query in the the current transaction can't access the modified
data from another transaction that is not yet committed - no dirty reads! No other
transactions can modify data being read by the current transaction until it is completed,
which eliminates NONREPEATABLE reads. BUT, if another transaction inserts NEW ROWS
and the query is executed more then once, phantom rows can appear starting the second
read (if it matches the where statement of the query).
3. SNAPSHOT - only able to return data that exists at the beginning of the query. Ensures
consistency of the data. It prevents dirty reads, nonrepeatable reads and phantom reads. To
use that - DB configurationis required:
4. READ COMMITTED - default isolation of the SQL server. It prevents reading the data that is
changed by another transaction until committed. It uses shared locking and row versioning
on the tables which prevents dirty reads. It depends on DB configuration
READ_COMMITTED_SNAPSHOT - if enabled - row versioning is used. to enable - use this:
5. SERIALIZABLE - uses physical locks that are acquired and held until end of the transaction,
which prevents dirty reads, phantom reads, nonrepeatable reads. BUT, it impacts on the
performance of the DataBase, because the concurrent transactions are serialized and are
https://riptutorial.com/ 135
www.dbooks.org
being executed one by one.
https://riptutorial.com/ 136
Chapter 48: Join
Introduction
In Structured Query Language (SQL), a JOIN is a method of linking two data tables in a single
query, allowing the database to return a set that contains data from both tables at once, or using
data from one table to be used as a Filter on the second table. There are several types of JOINs
defined within the ANSI SQL standard.
Examples
Inner Join
Inner join returns only those records/rows that match/exists in both the tables based on one or
more conditions (specified using ON keyword). It is the most common type of join. The general
syntax for inner join is:
SELECT *
FROM table_1
INNER JOIN table_2
ON table_1.column_name = table_2.column_name
SELECT *
FROM table_1
JOIN table_2
ON table_1.column_name = table_2.column_name
Example
/* Sample data. */
DECLARE @Animal table (
AnimalId Int IDENTITY,
Animal Varchar(20)
);
https://riptutorial.com/ 137
www.dbooks.org
/* Sample data prepared. */
SELECT
*
FROM
@Animal
JOIN @AnimalSound
ON @Animal.AnimalId = @AnimalSound.AnimalId;
Using inner join with left outer join (Substitute for Not exists)
This query will return data from table 1 where fields matching with table2 with a key and data not
in Table 1 when comparing with Table2 with a condition and key
select *
from Table1 t1
inner join Table2 t2 on t1.ID_Column = t2.ID_Column
left join Table3 t3 on t1.ID_Column = t3.ID_Column
where t2.column_name = column_value
and t3.ID_Column is null
order by t1.column_name;
Cross Join
A cross join is a Cartesian join, meaning a Cartesian product of both the tables. This join does not
need any condition to join two tables. Each row in the left table will join to each row of the right
table. Syntax for a cross join:
Example:
/* Sample data. */
DECLARE @Animal table (
AnimalId Int IDENTITY,
Animal Varchar(20)
);
https://riptutorial.com/ 138
INSERT INTO @AnimalSound (AnimalId, Sound) VALUES (1, 'Barks');
INSERT INTO @AnimalSound (AnimalId, Sound) VALUES (2, 'Meows');
INSERT INTO @AnimalSound (AnimalId, Sound) VALUES (3, 'Trumpet');
/* Sample data prepared. */
SELECT
*
FROM
@Animal
CROSS JOIN @AnimalSound;
Results:
Note that there are other ways that a CROSS JOIN can be applied. This is a an "old style" join
(deprecated since ANSI SQL-92) with no condition, which results in a cross/Cartesian join:
SELECT *
FROM @Animal, @AnimalSound;
This syntax also works due to an "always true" join condition, but is not recommended and should
be avoided, in favor of explicit CROSS JOIN syntax, for the sake of readability.
SELECT *
FROM
@Animal
JOIN @AnimalSound
ON 1=1
Outer Join
LEFT JOIN returns all rows from the left table, matched to rows from the right table where the ON
clause conditions are met. Rows in which the ON clause is not met have NULL in all of the right
table's columns. The syntax of a LEFT JOIN is:
https://riptutorial.com/ 139
www.dbooks.org
RIGHT JOINreturns all rows from the right table, matched to rows from the left table where the ON
clause conditions are met. Rows in which the ON clause is not met have NULL in all of the left table's
columns. The syntax of a RIGHT JOIN is:
FULL JOINcombines LEFT JOIN and RIGHT JOIN. All rows are returned from both tables, regardless of
whether the conditions in the ON clause are met. Rows that do not satisfy the ON clause are
returned with NULL in all of the opposite table's columns (that is, for a row in the left table, all
columns in the right table will contain NULL, and vice versa). The syntax of a FULL JOIN is:
Examples
SELECT *
FROM @Animal As t1
LEFT JOIN @AnimalSound As t2 ON t1.AnimalId = t2.AnimalId;
https://riptutorial.com/ 140
2 Cat 2 2 Meows
3 Elephant 3 3 Trumpet
4 Frog NULL NULL NULL
SELECT *
FROM @Animal As t1
RIGHT JOIN @AnimalSound As t2 ON t1.AnimalId = t2.AnimalId;
SELECT *
FROM @Animal As t1
FULL JOIN @AnimalSound As t2 ON t1.AnimalId = t2.AnimalId;
Update the SomeSetting column of the Preferences table filtering by a predicate on the Users table as
follows:
https://riptutorial.com/ 141
www.dbooks.org
UPDATE p
SET p.SomeSetting = 1
FROM Users u
JOIN Preferences p ON u.UserId = p.UserId
WHERE u.AccountId = 1234
p is an alias for Preferences defined in the FROM clause of the statement. Only rows with a matching
AccountId from the Users table will be updated.
Update t
SET t.Column1=100
FROM Table1 t LEFT JOIN Table12 t2
ON t2.ID=t.ID
UPDATE t1
SET t1.field1 = t2.field2Sum
FROM table1 t1
INNER JOIN (select field3, sum(field2) as field2Sum
from table2
group by field3) as t2
on t2.field3 = t1.field3
Join on a Subquery
Joining on a subquery is often used when you want to get aggregate data (such as Count, Avg,
Max, or Min) from a child/details table and display that along with records from the parent/header
table. For example, you may want to retrieve the top/first child row based on Date or Id or maybe
you want a Count of all Child Rows or an Average.
This example uses aliases which makes queries easier to read when you have multiple tables
involved. In this case we are retrieving all rows from the parent table Purchase Orders and
retrieving only the last (or most recent) child row from the child table PurchaseOrderLineItems.
This example assumes the child table uses incremental numeric Id's.
Self Join
A table can be joined onto itself in what is known as a self join, combining records in the table with
other records in the same table. Self joins are typically used in queries where a hierarchy in the
https://riptutorial.com/ 142
table's columns is defined.
ID Name Boss_ID
1 Bob 3
2 Jim 1
3 Sam 2
Each employee's Boss_ID maps to another employee's ID. To retrieve a list of employees with their
respective boss' name, the table can be joined on itself using this mapping. Note that joining a
table in this manner requires the use of an alias (Bosses in this case) on the second reference to
the table to distinguish itself from the original table.
SELECT Employees.Name,
Bosses.Name AS Boss
FROM Employees
INNER JOIN Employees AS Bosses
ON Employees.Boss_ID = Bosses.ID
Name Boss
Bob Sam
Jim Bob
Sam Jim
We can delete rows from the Preferences table, filtering by a predicate on the Users table as
follows:
https://riptutorial.com/ 143
www.dbooks.org
DELETE p
FROM Users u
INNER JOIN Preferences p ON u.UserId = p.UserId
WHERE u.AccountId = 1234
Here p is an alias for Preferences defined in the FROM clause of the statement and we only delete
rows that have a matching AccountId from the Users table.
Outer joins return all the rows from one or both tables, plus matching rows.
Table People
PersonID FirstName
1 Alice
2 Bob
3 Eve
Table Scores
PersonID Subject Score
1 Math 100
2 Math 54
2 Science 98
Returns:
If you wanted to return all the people, with any applicable math scores, a common mistake is to
write:
This would remove Eve from your results, in addition to removing Bob's science score, as Subject
is NULL for her.
The correct syntax to remove non-Math records while retaining all individuals in the People table
would be:
https://riptutorial.com/ 144
Select * from People a
left join Scores b
on a.PersonID = b.PersonID
and b.Subject = 'Math'
https://riptutorial.com/ 145
www.dbooks.org
Chapter 49: JSON in Sql Server
Syntax
• JSON_VALUE(expression , path) -- extract a scalar value from a JSON string.
• JSON_QUERY( expression [ , path ] ) -- Extracts an object or an array from a JSON string.
• OPENJSON( jsonExpression [ , path ] ) -- table-value function that parses JSON text and
returns objects and properties in JSON as rows and columns.
• ISJSON( expression ) -- Tests whether a string contains valid JSON.
• JSON_MODIFY( expression , path , newValue ) -- Updates the value of a property in a
JSON string and returns the updated JSON string.
Parameters
Parameters Details
expression Typically the name of a variable or a column that contains JSON text.
A JSON path expression that specifies the property to update. path has the
path
following syntax: [append] [ lax | strict ] $.<json path>
Remarks
The OPENJSON function is only available under compatibility level 130. If your database
compatibility level is lower than 130, SQL Server will not be able to find and execute OPENJSON
function. Currently all Azure SQL databases are set to 120 by default. You can change the
compatibility level of a database using the following command:
Examples
Format Query Results as JSON with FOR JSON
Id Name Age
1 John 23
2 Jane 31
https://riptutorial.com/ 146
Query
Result
[
{"Id":1,"Name":"John","Age":23},
{"Id":2,"Name":"Jane","Age":31}
]
JSON_VALUE and JSON_QUERY functions parse JSON text and return scalar values or
objects/arrays on the path in JSON text.
SELECT
JSON_VALUE(@json, '$.id') AS Id,
JSON_VALUE(@json, '$.user.name') AS Name,
JSON_QUERY(@json, '$.user') AS UserObject,
JSON_QUERY(@json, '$.skills') AS Skills,
JSON_VALUE(@json, '$.skills[0]') AS Skill0
Result
Join parent and child JSON entities using CROSS APPLY OPENJSON
Join parent objects with their child entities, for example we want a relational table of each person
and their hobbies
https://riptutorial.com/ 147
www.dbooks.org
{"name": "Programming"},
{"name": "Running"}
]
}
]'
Query
SELECT
JSON_VALUE(person.value, '$.id') as Id,
JSON_VALUE(person.value, '$.user.name') as PersonName,
JSON_VALUE(hobbies.value, '$.name') as Hobby
FROM OPENJSON (@json) as person
CROSS APPLY OPENJSON(person.value, '$.hobbies') as hobbies
SELECT
Id, person.PersonName, Hobby
FROM OPENJSON (@json)
WITH(
Id int '$.id',
PersonName nvarchar(100) '$.user.name',
Hobbies nvarchar(max) '$.hobbies' AS JSON
) as person
CROSS APPLY OPENJSON(Hobbies)
WITH(
Hobby nvarchar(100) '$.name'
)
Result
Id PersonName Hobby
1 John Reading
1 John Surfing
2 Jane Programming
2 Jane Running
When storing JSON documents in SQL Server, We need to be able to efficiently filter and sort
query results on properties of the JSON documents.
https://riptutorial.com/ 148
)
Given the above table If we want to find the row with the name = 'Adam', we would execute the
following query.
SELECT *
FROM JsonTable Where
JSON_VALUE(jsonInfo, '$.Name') = 'Adam'
However this will require SQL server to perform a full table which on a large table is not efficent.
To speed this up we would like to add an index, however we cannot directly reference properties
in the JSON document. The solution is to add a computed column on the JSON path $.Name, then
add an index on the computed column.
Now when we execute the same query, instead of a full table scan SQL server uses an index to
seek into the non-clustered index and find the rows that satisfy the specified conditions.
Note: For SQL server to use the index, you must create the computed column with the same
expression that you plan to use in your queries - in this example JSON_VALUE(jsonInfo, '$.Name'),
however you can also use the name of computed column vName
Format one table row as a single JSON object using FOR JSON
WITHOUT_ARRAY_WRAPPER option in FOR JSON clause will remove array brackets from the
JSON output. This is useful if you are returning single row in the query.
Note: this option will produce invalid JSON output if more than one row is returned.
Id Name Age
1 John 23
2 Jane 31
https://riptutorial.com/ 149
www.dbooks.org
Query
Result
{"Id":1,"Name":"John","Age":23}
OPENJSON function parses JSON text and returns multiple outputs. Values that should be
returned are specified using the paths defined in the WITH clause. If a path is not specified for
some column, the column name is used as a path. This function casts returned values to the SQL
types defined in the WITH clause. AS JSON option must be specified in the column definition if
some object/array should be returned.
SELECT *
FROM OPENJSON (@json)
WITH(Id int '$.id',
Name nvarchar(100) '$.user.name',
UserObject nvarchar(max) '$.user' AS JSON,
Skills nvarchar(max) '$.skills' AS JSON,
Skill0 nvarchar(20) '$.skills[0]')
Result
https://riptutorial.com/ 150
Chapter 50: Last Inserted Identity
Examples
SCOPE_IDENTITY()
SELECT SCOPE_IDENTITY();
This will return the most recently added identity value produced on the same connection, within
the current scope. In this case, 1, for the first row in the dbo.person table.
@@IDENTITY
SELECT @@IDENTITY;
This will return the most recently-added identity on the same connection, regardless of scope. In
this case, whatever the current value of the identity column on logging_table is, assuming no other
activity is occurring on the instance of SQL Server and no other triggers fire from this insert.
https://riptutorial.com/ 151
www.dbooks.org
IDENT_CURRENT('tablename')
SELECT IDENT_CURRENT('dbo.person');
This will select the most recently-added identity value on the selected table, regardless of
connection or scope.
SELECT MAX(Id) FROM Employees -- Display the value of Id in the last row in Employees table.
GO
INSERT INTO Employees (FName, LName, PhoneNumber) -- Insert a new row
VALUES ('John', 'Smith', '25558696525')
GO
SELECT @@IDENTITY
GO
SELECT MAX(Id) FROM Employees -- Display the value of Id of the newly inserted row.
GO
https://riptutorial.com/ 152
Chapter 51: Limit Result Set
Introduction
As database tables grow, it's often useful to limit the results of queries to a fixed number or
percentage. This can be achieved using SQL Server's TOP keyword or OFFSET FETCH clause.
Parameters
Parameter Details
Remarks
If ORDER BY clause is used, limiting applies to the ordered result set.
Examples
Limiting With TOP
https://riptutorial.com/ 153
www.dbooks.org
FETCH is generally more useful for pagination, but can be used as an alternative to TOP:
SELECT *
FROM table_name
ORDER BY 1
OFFSET 0 ROWS
FETCH NEXT 50 ROWS ONLY
https://riptutorial.com/ 154
Chapter 52: Logical Functions
Examples
CHOOSE
Returns the item at the specified index from a list of values. If index exceeds the bounds of values
then NULL is returned.
Parameters:
chosen_result
-------------
apples
IIF
Returns one of two values, depending on whether a given Boolean expression evaluates to true or
false.
Parameters:
SELECT IIF (42 > 23, 'I knew that!', 'That is not true.') AS iif_result
iif_result
------------
I knew that!
SELECT CASE WHEN 42 > 23 THEN 'I knew that!' ELSE 'That is not true.' END AS iif_result
iif_result
------------
https://riptutorial.com/ 155
www.dbooks.org
I knew that!
https://riptutorial.com/ 156
Chapter 53: Managing Azure SQL Database
Examples
Find service tier information for Azure SQL Database
You can find version, edition (basic, standard, or premium), and service objective (S0,S1,P4,P11,
etc.) of SQL Database that is running as a service in Azure using the following statements:
select @@version
SELECT DATABASEPROPERTYEX('Wwi', 'EDITION')
SELECT DATABASEPROPERTYEX('Wwi', 'ServiceObjective')
You can scale-up or scale-down Azure SQL database using ALTER DATABASE statement:
If you try to change service level while changing service level of the current database is still in
progress you wil get the following error:
Msg 40802, Level 16, State 1, Line 1 A service objective assignment on server '......'
and database '.......' is already in progress. Please wait until the service objective
assignment state for the database is marked as 'Completed'.
You can create a secondary replica of database with the same name on another Azure SQL
Server, making the local database primary, and begins asynchronously replicating data from the
primary to the new secondary.
Target server may be in another data center (usable for geo-replication). If a database with the
same name already exists on the target server, the command will fail. The command is executed
on the master database on the server hosting the local database that will become the primary.
https://riptutorial.com/ 157
www.dbooks.org
When ALLOW_CONNECTIONS is set to ALL (it is set to NO by default), secondary replica will be
a read-only database that will allow all logins with the appropriate permissions to connect.
Secondary database replica might be promoted to primary using the following command:
You can put your azure SQL Database in SQL elastic pool:
You can create copy of an existing database and place it in some elastic pool:
https://riptutorial.com/ 158
Chapter 54: MERGE
Introduction
Starting with SQL Server 2008, it is possible to perform insert, update, or delete operations in a
single statement using the MERGE statement.
The MERGE statement allows you to join a data source with a target table or view, and then
perform multiple actions against the target based on the results of that join.
Syntax
• As per MSDN - https://msdn.microsoft.com/en-us/library/bb510625.aspx [ WITH
<common_table_expression> [,...n] ] 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> ] THEN
<merge_matched> ] [ ...n ] [ WHEN NOT MATCHED [ BY TARGET ] [ AND
<clause_search_condition> ] THEN <merge_not_matched> ] [ WHEN NOT MATCHED BY
SOURCE [ AND <clause_search_condition> ] THEN <merge_matched> ] [ ...n ] [
<output_clause> ] [ OPTION ( <query_hint> [ ,...n ] ) ] ; <target_table> ::= { [ database_name
. schema_name . | schema_name . ] target_table } <merge_hint>::= { { [ <table_hint_limited>
[ ,...n ] ] [ [ , ] INDEX ( index_val [ ,...n ] ) ] } } <table_source> ::= { table_or_view_name [ [ AS
] table_alias ] [ <tablesample_clause> ] [ WITH ( table_hint [ [ , ]...n ] ) ] | rowset_function [ [
AS ] table_alias ] [ ( bulk_column_alias [ ,...n ] ) ] | user_defined_function [ [ AS ] table_alias ]
| OPENXML <openxml_clause> | derived_table [ AS ] table_alias [ ( column_alias [ ,...n ] ) ] |
<joined_table> | <pivoted_table> | <unpivoted_table> } <merge_search_condition> ::=
<search_condition> <merge_matched>::= { UPDATE SET <set_clause> | DELETE }
<set_clause>::= SET { column_name = { expression | DEFAULT | NULL } | {
udt_column_name.{ { property_name = expression | field_name = expression } |
method_name ( argument [ ,...n ] ) } } | column_name { .WRITE ( expression , @Offset ,
@Length ) } | @variable = expression | @variable = column = expression | column_name {
+= | -= | *= | /= | %= | &= | ^= | |= } expression | @variable { += | -= | *= | /= | %= | &= | ^= | |= }
expression | @variable = column { += | -= | *= | /= | %= | &= | ^= | |= } expression } [ ,...n ]
<merge_not_matched>::= { INSERT [ ( column_list ) ] { VALUES ( values_list ) | DEFAULT
VALUES } } <clause_search_condition> ::= <search_condition> ::= { [ NOT ] | (
<search_condition> ) } [ { AND | OR } [ NOT ] { | ( <search_condition> ) } ] [ ,...n ] ::= {
expression { = | < > | ! = |
https://riptutorial.com/ 159
www.dbooks.org
<dml_select_list> INTO { @table_variable | output_table } [ (column_list) ] ] [
OUTPUT <dml_select_list> ] } <dml_select_list>::= { <column_name> |
scalar_expression } [ [AS] column_alias_identifier ] [ ,...n ] <column_name> ::= {
DELETED | INSERTED | from_table_name } . { * | column_name } | $action
Remarks
Performs insert, update, or delete operations on a target table based on the results of a join with a
source table. For example, you can synchronize two tables by inserting, updating, or deleting rows
in one table based on differences found in the other table.
Examples
MERGE to Insert / Update / Delete
USING sourceTable
ON (targetTable.PKID = sourceTable.PKID)
Description:
Comments:
https://riptutorial.com/ 160
If a specific action is not needed then omit the condition e.g. removing WHEN NOT MATCHED THEN
INSERT will prevent records from being inserted
Restrictions:
WITH SourceTableCTE AS
(
SELECT * FROM SourceTable
)
MERGE
TargetTable AS target
USING SourceTableCTE AS source
ON (target.PKID = source.PKID)
WHEN MATCHED THEN
UPDATE SET target.ColumnA = source.ColumnA
WHEN NOT MATCHED THEN
INSERT (ColumnA) VALUES (Source.ColumnA);
1. dbo.Product : This table contains information about the product that company is currently
selling
2. dbo.ProductNew: This table contains information about the product that the company will
sell in the future.
The following T-SQL will create and populate these two tables
https://riptutorial.com/ 161
www.dbooks.org
CREATE TABLE dbo.Product (
ProductID INT PRIMARY KEY,
ProductName NVARCHAR(64),
PRICE MONEY
)
Now, Suppose we want to synchoronize the dbo.Product Target Table with the dbo.ProductNew
table. Here is the criterion for this task:
1. Product that exist in both the dbo.ProductNew source table and the dbo.Product target table
are updated in the dbo.Product target table with new new Products.
2. Any product in the dbo.ProductNew source table that do not exist in the dob.Product target
table are inserted into the dbo.Product target table.
3. Any Product in the dbo.Product target table that do not exist in the dbo.ProductNew source
table must be deleted from the dbo.Product target table. Here is the MERGE statement to
perform this task.
https://riptutorial.com/ 162
Merge using EXCEPT
https://riptutorial.com/ 163
www.dbooks.org
Chapter 55: Microsoft SQL Server
Management Studio Shortcut Keys
Examples
Shortcut Examples
On the right side you can see some shortcuts which are by default in SSMS. Now if you need to
add a new one, just click on any column under Stored Procedure column.
https://riptutorial.com/ 164
Click OK. Now please go to a query window and select the stored procedure then press CTRL+3,
it will show the stored procedure result.
Now if you need to select all the records from a table when you select the table and press
CTRL+5(You can select any key). You can make the shortcut as follows.
https://riptutorial.com/ 165
www.dbooks.org
Now go ahead and select the table name from the query window and press CTRL+4(The key we
selected), it will give you the result.
Read Microsoft SQL Server Management Studio Shortcut Keys online: https://riptutorial.com/sql-
server/topic/7749/microsoft-sql-server-management-studio-shortcut-keys
https://riptutorial.com/ 166
Chapter 56: Migration
Examples
How to generate migration scripts
1. Click Right Mouse on Database you want to migrate then -> Tasks -> Generate Scripts...
2. Wizard will open click Next then chose objects you want to migrate and click Next again, then
click Advanced scroll a bit down and in Types of data to script choose Schema and data (unless
you want only structures)
https://riptutorial.com/ 167
www.dbooks.org
3. Click couple more times Next and Finish and you should have your database scripted in .sql
file.
4. run .sql file on your new server, and you should be done.
https://riptutorial.com/ 168
Chapter 57: Modify JSON text
Examples
Modify value in JSON text on the specified path
JSON_MODIFY function uses JSON text as input parameter, and modifies a value on the
specified path using third argument:
As a result, we will have new JSON text with "Price":39.99 and other value will not be changed. If
object on the specified path does not exists, JSON_MODIFY will insert key:value pair.
JSON_MODIFY will by default delete key if it does not have value so you can use it to delete a
key.
If array on the specified path does not exists, JSON_MODIFY(append) will create new array with a
single element:
JSON_MODIFY function enables you to insert JSON objects into JSON text:
https://riptutorial.com/ 169
www.dbooks.org
print @json
-- Output: {"Id":1,"Name":"Toy Car","Price":{"Min":34.99,"Recommended":45.49}}
Since third parameter is text you need to wrap it with JSON_QUERY function to "cast" text to
JSON. Without this "cast", JSON_MODIFY will treat third parameter as plain text and escape
characters before inserting it as string value. Without JSON_QUERY results will be:
{"Id":1,"Name":"Toy Car","Price":'{\"Min\":34.99,\"Recommended\":45.49}'}
JSON_MODIFY will insert this object if it does not exist, or delete it if value of third parameter is
NULL.
You can generate JSON object using standard SELECT query with FOR JSON clause and insert it
into JSON text as third parameter:
(1 row(s) affected)
{"Id":1,"Name":"master","tables":[{"name":"Colors"},{"name":"Colors_Archive"},{"name":"OrderLines"},{"n
JSON_MODIFY will know that select query with FOR JSON clause generates valid JSON array
and it will just insert it into JSON text.
You can use all FOR JSON options in SELECT query, except
WITHOUT_ARRAY_WRAPPER, which will generate single object instead of JSON
array. See other example in this topic to see how insert single JSON object.
You can generate JSON object using standard SELECT query with FOR JSON clause and
WITHOUT_ARRAY_WRAPPER option, and insert it into JSON text as a third parameter:
(1 row(s) affected)
{"Id":17,"Name":"WWI","table":{"name":"Colors","create_date":"2016-06-
02T10:04:03.280","schema_id":13}}
https://riptutorial.com/ 170
FOR JSON with WITHOUT_ARRAY_WRAPPER option may generate invalid JSON text if
SELECT query returns more than one result (you should use TOP 1 or filter by primary key in this
case). Therefore, JSON_MODIFY will assume that returned result is just a plain text and escape it
like any other text if you don't wrap it with JSON_QUERY function.
https://riptutorial.com/ 171
www.dbooks.org
Chapter 58: Move and copy data around
tables
Examples
Copy data from one table to another
This code selects data out of a table and displays it in the query tool (usually SSMS)
This code creates a new table called MyNewTable and puts that data into it
To move data you first insert it into the target, then delete whatever you inserted from the source
table. This is not a normal SQL operation but it may be enlightening
What did you insert? Normally in databases you need to have one or more columns that you can
use to uniquely identify rows so we will assume that and make use of it.
https://riptutorial.com/ 172
Now assuming records in both tables are unique on Key1,Key2, we can use that to find and delete
data out of the source table
DELETE MyTable
WHERE EXISTS (
SELECT * FROM TargetTable
WHERE TargetTable.Key1 = SourceTable.Key1
AND TargetTable.Key2 = SourceTable.Key2
);
This will only work correctly if Key1, Key2 are unique in both tables
Lastly, we don't want the job half done. If we wrap this up in a transaction then either all data will
be moved, or nothing will happen. This ensures we don't insert the data in then find ourselves
unable to delete the data out of the source.
BEGIN TRAN;
DELETE MyTable
WHERE EXISTS (
SELECT * FROM TargetTable
WHERE TargetTable.Key1 = SourceTable.Key1
AND TargetTable.Key2 = SourceTable.Key2
);
COMMIT TRAN;
https://riptutorial.com/ 173
www.dbooks.org
Chapter 59: Natively compiled modules
(Hekaton)
Examples
Natively compiled stored procedure
In a procedure with native compilation, T-SQL code is compiled to dll and executed as native C
code. To create a Native Compiled stored Procedure you need to:
Instead of standard BEGIN END block, you need to use BEGIN ATOMIC block:
BEGIN ATOMIC
WITH (TRANSACTION ISOLATION LEVEL=SNAPSHOT, LANGUAGE='us_english')
-- T-Sql code goes here
END
Example:
Code in natively compiled function will be transformed into C code and compiled as dll. To create
a Native Compiled scalar function you need to:
https://riptutorial.com/ 174
• Use SCHEMABINDING option in function definition
Instead of standard BEGIN END block, you need to use BEGIN ATOMIC block:
BEGIN ATOMIC
WITH (TRANSACTION ISOLATION LEVEL=SNAPSHOT, LANGUAGE='us_english')
-- T-Sql code goes here
END
Example:
RETURN (@ReturnValue);
END
-- usage sample:
SELECT dbo.udfMultiply(10, 12)
Native compiled table value function returns table as result. Code in natively compiled function will
be transformed into C code and compiled as dll. Only inline table valued functions are supported in
version 2016. To create a native table value function you need to:
Instead of standard BEGIN END block, you need to use BEGIN ATOMIC block:
BEGIN ATOMIC
WITH (TRANSACTION ISOLATION LEVEL=SNAPSHOT, LANGUAGE='us_english')
-- T-Sql code goes here
END
Example:
https://riptutorial.com/ 175
www.dbooks.org
RETURN
(
SELECT BusinessDocNo,
ProductCode,
UnitID,
ReasonID,
PriceID,
RunDate,
ReturnPercent,
Qty,
RewardAmount,
ModifyDate,
UserID
FROM dbo.[BusinessDocDetail_11]
WHERE RunDate >= @RunDate
);
https://riptutorial.com/ 176
Chapter 60: NULLs
Introduction
In SQL Server, NULL represents data that is missing, or unknown. This means that NULL is not really
a value; it's better described as a placeholder for a value. This is also the reason why you can't
compare NULL with any value, and not even with another NULL.
Remarks
SQL Server provides other methods to handle nulls, such as IS NULL, IS NOT NULL, ISNULL(),
COALESCE() and others.
Examples
NULL comparison
id someVal
----
0 NULL
1 1
2 2
With a query:
SELECT id
FROM table
WHERE someVal = 1
would return id 1
SELECT id
FROM table
WHERE someVal <> 1
would return id 2
SELECT id
FROM table
WHERE someVal IS NULL
would return id 0
https://riptutorial.com/ 177
www.dbooks.org
SELECT id
FROM table
WHERE someVal IS NOT NULL
If you wanted NULLs to be "counted" as values in a =, <> comparison, it must first be converted to
a countable data type:
SELECT id
FROM table
WHERE ISNULL(someVal, -1) <> 1
OR
SELECT id
FROM table
WHERE someVal IS NULL OR someVal <> 1
returns 0 and 2
ANSI NULLS
From MSDN
ANSI NULLS being set to off allows for a =/<> comparison of null values.
id someVal
----
0 NULL
1 1
2 2
SELECT id
FROM table
WHERE someVal = NULL
would produce no results. However the same query, with ANSI NULLS off:
https://riptutorial.com/ 178
set ansi_nulls off
SELECT id
FROM table
WHERE someVal = NULL
Would return id 0.
ISNULL()
The IsNull() function accepts two parameters, and returns the second parameter if the first one is
null.
Parameters:
The IsNull() function returns the same data type as the check expression.
DECLARE @MyInt int -- All variables are null until they are set with values.
Since null is not a value, you can't use comparison operators with nulls.
To check if a column or variable holds null, you need to use is null:
The following statement will select the value 6, since all comparisons with null values evaluates to
false or unknown:
Setting the content of the @Date variable to null and try again, the following statement will return
5:
SET @Date = NULL -- Note that the '=' here is an assignment operator!
https://riptutorial.com/ 179
www.dbooks.org
SELECT CASE WHEN @Date = NULL THEN 1
WHEN @Date <> NULL THEN 2
WHEN @Date > NULL THEN 3
WHEN @Date < NULL THEN 4
WHEN @Date IS NULL THEN 5
WHEN @Date IS NOT NULL THEN 6
COALESCE ()
COALESCE () Evaluates the arguments in order and returns the current value of the first expression
that initially does not evaluate to NULL.
SET @MyInt3 = 3
Although ISNULL() operates similarly to COALESCE(), the ISNULL() function only accepts two
parameters - one to check, and one to use if the first parameter is NULL. See also ISNULL, below
While handling not in sub-query with null in the sub-query we need to eliminate NULLS to get your
expected results
While handling not in sub-query with null be cautious with your expected output
https://riptutorial.com/ 180
Chapter 61: OPENJSON
Examples
Get key:value pairs from JSON text
OPENJSON function parse JSON text and returns all key:value pairs at the first level of JSON:
Name Joe 1
age 27 2
skills ["C#","SQL"] 4
Column type describe the type of value, i.e. null(0), string(1), number(2), boolean(3), array(4), and
object(5).
OPENJSON function parses collection of JSON objects and returns values from JSON text as set
of rows.
SELECT *
FROM OPENJSON (@json)
WITH (
Number varchar(200),
Date datetime,
Customer varchar(200),
Quantity int
)
In the WITH clause is specified return schema of OPENJSON function. Keys in the JSON objects
are fetched by column names. If some key in JSON is not specified in the WITH clause (e.g. Price
in this example) it will be ignored. Values are automatically converted into specified types.
https://riptutorial.com/ 181
www.dbooks.org
Number Date Customer Quantity
OPENJSON function parses collection of JSON objects and returns values from JSON text as set
of rows. If the values in input object are nested, additional mapping parameter can be specified in
each column in WITH clause:
SELECT *
FROM OPENJSON (@json)
WITH (
Number varchar(200) '$.data.num',
Date datetime '$.data.date',
Customer varchar(200) '$.info.customer',
Quantity int '$.info.qty',
)
In the WITH clause is specified return schema of OPENJSON function. After the type is specified
path to the JSON nodes where returned value should be found. Keys in the JSON objects are
fetched by these paths. Values are automatically converted into specified types.
OPENJSON can extract fragments of JSON objects inside the JSON text. In the column definition
that references JSON sub-object set the type nvarchar(max) and AS JSON option:
SELECT *
FROM OPENJSON (@json)
https://riptutorial.com/ 182
WITH (
Number varchar(200),
Date datetime,
Info nvarchar(max) '$.info' AS JSON
)
JSON may have complex structure with inner arrays. In this example, we have array of orders with
nested sub array of OrderItems.
"Items":[{"Price":21.99,"Quantity":3},{"Price":22.99,"Quantity":2},{"Price":23.99,"Quantity":2}]}
]'
We can parse root level properties using OPENJSON that will return Items array AS JSON
fragment. Then we can apply OPENJSON again on Items array and open inner JSON table. First
level table and inner table will be "joined" like in the JOIN between standard tables:
SELECT *
FROM
OPENJSON (@json)
WITH ( Number varchar(200), Date datetime,
Items nvarchar(max) AS JSON )
CROSS APPLY
OPENJSON (Items)
WITH ( Price float, Quantity int)
Results:
2011-05-31
SO43659 [{"Price":11.99,"Quantity":1},{"Price":12.99,"Quantity":5}]
00:00:00.000
2011-05-31
SO43659 [{"Price":11.99,"Quantity":1},{"Price":12.99,"Quantity":5}]
00:00:00.000
https://riptutorial.com/ 183
www.dbooks.org
Number Date Items
2011-06-01
SO43661 [{"Price":21.99,"Quantity":3},{"Price":22.99,"Quantity":2},{"Price":23.99,"Quan
00:00:00.000
2011-06-01
SO43661 [{"Price":21.99,"Quantity":3},{"Price":22.99,"Quantity":2},{"Price":23.99,"Quan
00:00:00.000
2011-06-01
SO43661 [{"Price":21.99,"Quantity":3},{"Price":22.99,"Quantity":2},{"Price":23.99,"Quan
00:00:00.000
https://riptutorial.com/ 184
Chapter 62: ORDER BY
Remarks
The purpose of the ORDER BY clause is to sort the data returned by a query.
It's important to note that the order of rows returned by a query is undefined unless there is
an ORDER BY clause.
Examples
Simple ORDER BY clause
Using the Employees Table, below is an example to return the Id, FName and LName columns in
(ascending) LName order:
Returns:
Id FName LName
2 John Johnson
1 James Smith
4 Johnathon Smith
3 Michael Williams
To sort in descending order add the DESC keyword after the field parameter, e.g. the same query
in LName descending order is:
Multiple fields can be specified for the ORDER BY clause, in either ASCending or DESCending order.
https://riptutorial.com/ 185
www.dbooks.org
sorts by SaleDate in ascending order, and Quantity in descending order.
Note that the ASC keyword is optional, and results are sorted in ascending order of a given field by
default.
If we want to order the data differently for per group, we can add a CASE syntax to the ORDER BY. In
this example, we want to order employees from Department 1 by last name and employees from
Department 2 by salary.
01-01-
1 James Smith 1234567890 NULL 1 1000
2002
23-03-
2 John Johnson 2468101214 1 1 400
2005
12-05-
3 Michael Williams 1357911131 1 2 600
2009
24-07-
4 Johnathon Smith 1212121212 2 1 500
2016
25-03-
5 Sam Saxon 1372141312 2 2 400
2015
Custom Ordering
If you want to order by a column using something other than alphabetical/numeric ordering, you
can use case to specify the order you want.
Group Count
Not Retired 6
Retired 4
https://riptutorial.com/ 186
Group Count
Total 10
order by case group when 'Total' then 1 when 'Retired' then 2 else 3 end returns:
Group Count
Total 10
Retired 4
Not Retired 6
https://riptutorial.com/ 187
www.dbooks.org
Chapter 63: OVER Clause
Parameters
Parameter Details
PARTITION The field(s) that follows PARTITION BY is the one that the 'grouping' will be
BY based on
Remarks
The OVER clause determines a windows or a subset of row within a query result set. A window
function can be applied to set and compute a value for each row in the set. The OVER clause can
be used with:
• Ranking functions
• Aggregate functions
so someone can compute aggregated values such as moving averages, cumulative aggregates,
running totals, or a top N per group results.
In a very abstract way we can say that OVER behaves like GROUP BY. However OVER is applied
per field / column and not to the query as whole as GROUP BY does.
Note#1: In SQL Server 2008 (R2) ORDER BY Clause cannot be used with aggregate window
functions (link).
Examples
Using Aggregation functions with OVER
Using the Cars Table, we will calculate the total, max, min and average amount of money each
costumer spent and haw many times (COUNT) she brought a car for repairing.
SELECT CustomerId,
SUM(TotalCost) OVER(PARTITION BY CustomerId) AS Total,
AVG(TotalCost) OVER(PARTITION BY CustomerId) AS Avg,
COUNT(TotalCost) OVER(PARTITION BY CustomerId) AS Count,
MIN(TotalCost) OVER(PARTITION BY CustomerId) AS Min,
MAX(TotalCost) OVER(PARTITION BY CustomerId) AS Max
FROM CarsTable
WHERE Status = 'READY'
Beware that using OVER in this fashion will not aggregate the rows returned. The above query will
https://riptutorial.com/ 188
return the following:
The duplicated row(s) may not be that useful for reporting purposes.
If you wish to simply aggregate data, you will be better off using the GROUP BY clause along with
the appropriate aggregate functions Eg:
SELECT CustomerId,
SUM(TotalCost) AS Total,
AVG(TotalCost) AS Avg,
COUNT(TotalCost) AS Count,
MIN(TotalCost) AS Min,
MAX(TotalCost) AS Max
FROM CarsTable
WHERE Status = 'READY'
GROUP BY CustomerId
Cumulative Sum
Using the Item Sales Table, we will try to find out how the sales of our items are increasing
through dates. To do so we will calculate the Cumulative Sum of total sales per Item order by the
sale date.
Using the Library Database, we try to find the last book added to the database for each author. For
this simple example we assume an always incrementing Id for each record added.
Instead of RANK, two other functions can be used to order. In the previous example the result will
be the same, but they give different results when the ordering gives multiple rows for each rank.
https://riptutorial.com/ 189
www.dbooks.org
• RANK():
duplicates get the same rank, the next rank takes the number of duplicates in the
previous rank into account
• DENSE_RANK(): duplicates get the same rank, the next rank is always one higher than the
previous
• ROW_NUMBER(): will give each row a unique 'rank', 'ranking' the duplicates randomly
For example, if the table had a non-unique column CreationDate and the ordering was done based
on that, the following query:
SELECT Authors.Name,
Books.Title,
Books.CreationDate,
RANK() OVER (PARTITION BY Authors.Id ORDER BY Books.CreationDate DESC) AS RANK,
DENSE_RANK() OVER (PARTITION BY Authors.Id ORDER BY Books.CreationDate DESC) AS
DENSE_RANK,
ROW_NUMBER() OVER (PARTITION BY Authors.Id ORDER BY Books.CreationDate DESC) AS
ROW_NUMBER,
FROM Authors
JOIN Books ON Books.AuthorId = Authors.Id
Let's say that you have exam scores for several exams and you want to divide them into quartiles
per exam.
-- Setup data:
declare @values table(Id int identity(1,1) primary key, [Value] float, ExamId int)
insert into @values ([Value], ExamId) values
(65, 1), (40, 1), (99, 1), (100, 1), (90, 1), -- Exam 1 Scores
(91, 2), (88, 2), (83, 2), (91, 2), (78, 2), (67, 2), (77, 2) -- Exam 2 Scores
https://riptutorial.com/ 190
Value, Id
from @values
order by ExamId, Quartile
ntile works great when you really need a set number of buckets and each filled to approximately
the same level. Notice that it would be trivial to separate these scores into percentiles by simply
using ntile(100).
https://riptutorial.com/ 191
www.dbooks.org
Chapter 64: Pagination
Introduction
Row Offset and Paging in Various Versions of SQL Server
Syntax
• SELECT * FROM TableName ORDER BY id OFFSET 10 ROWS FETCH NEXT 10 ROWS
ONLY;
Examples
Pagination using ROW_NUMBER with a Common Table Expression
The ROW_NUMBER function can assign an incrementing number to each row in a result set. Combined
with a Common Table Expression that uses a BETWEEN operator, it is possible to create 'pages' of
result sets. For example: page one containing results 1-10, page two containing results 11-20,
page three containing results 21-30, and so on.
WITH data
AS
(
SELECT ROW_NUMBER() OVER (ORDER BY name) AS row_id,
object_id,
name,
type,
create_date
FROM sys.objects
)
SELECT *
FROM data
WHERE row_id BETWEEN 41 AND 50
SELECT object_id,
name,
type,
create_date
FROM sys.objects
WHERE ROW_NUMBER() OVER (ORDER BY name) BETWEEN 41 AND 50
Although this would be more convenient, SQL server will return the following error in this case:
https://riptutorial.com/ 192
Windowed functions can only appear in the SELECT or ORDER BY clauses.
The OFFSET FETCH clause implements pagination in a more concise manner. With it, it's possible to
skip N1 rows (specified in OFFSET) and return the next N2 rows (specified in FETCH):
SELECT *
FROM sys.objects
ORDER BY object_id
OFFSET 40 ROWS FETCH NEXT 10 ROWS ONLY
In earlier versions of SQL Server, developers had to use double sorting combined with the TOP
keyword to return rows in a page:
SELECT TOP 10 *
FROM
(
SELECT
TOP 50 object_id,
name,
type,
create_date
FROM sys.objects
ORDER BY name ASC
) AS data
ORDER BY name DESC
The inner query will return the first 50 rows ordered by name. Then the outer query will reverse the
order of these 50 rows and select the top 10 rows (these will be last 10 rows in the group before
the reversal).
https://riptutorial.com/ 193
www.dbooks.org
SQL Server 2005/2008/R2
SELECT * FROM TableName ORDER BY id OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;
https://riptutorial.com/ 194
Chapter 65: Parsename
Syntax
• PARSENAME ( 'object_name' , object_piece )
Parameters
'object_name' object_piece
Examples
PARSENAME
SELECT
PARSENAME(@ObjectName, 4) as Server
,PARSENAME(@ObjectName, 3) as DB
,PARSENAME(@ObjectName, 2) as Owner
,PARSENAME(@ObjectName, 1) as Object
Returns:
Server DB
HeadofficeSQL1 Northwind
Owner Object
dbo Authors
https://riptutorial.com/ 195
www.dbooks.org
Chapter 66: Partitioning
Examples
Retrieve Partition Boundary Values
FROM sys.partition_schemes ps
INNER JOIN sys.destination_data_spaces dds
ON dds.partition_scheme_id = ps.data_space_id
INNER JOIN sys.filegroups fg
ON dds.data_space_id = fg.data_space_id
INNER JOIN sys.partition_functions f
ON f.function_id = ps.function_id
INNER JOIN sys.partition_range_values prv
ON f.function_id = prv.function_id
AND dds.destination_id = prv.boundary_id
Switching Partitions
Partitioning data enables you to manage and access subsets of your data quickly and
efficiently while maintaining the integrity of the entire data collection.
When you call the following query the data is not physically moved; only the metadata about the
location of the data changes.
The tables must have the same columns with the same data types and NULL settings, they need
to be in the same file group and the new target table must be empty. See the page link above for
more info on switching partitions.
SELECT DISTINCT
object_name(i.object_id) AS [Object Name],
c.name AS [Partition Column],
s.name AS [Partition Scheme],
pf.name AS [Partition Function],
https://riptutorial.com/ 196
prv.tot AS [Partition Count],
prv.miVal AS [Min Boundry Value],
prv.maVal AS [Max Boundry Value]
FROM sys.objects o
INNER JOIN sys.indexes i ON i.object_id = o.object_id
INNER JOIN sys.columns c ON c.object_id = o.object_id
INNER JOIN sys.index_columns ic ON ic.object_id = o.object_id
AND ic.column_id = c.column_id
AND ic.partition_ordinal = 1
INNER JOIN sys.partition_schemes s ON i.data_space_id = s.data_space_id
INNER JOIN sys.partition_functions pf ON pf.function_id = s.function_id
OUTER APPLY(SELECT
COUNT(*) tot, MIN(value) miVal, MAX(value) maVal
FROM sys.partition_range_values prv
WHERE prv.function_id = pf.function_id) prv
--WHERE object_name(i.object_id) = 'table_name'
ORDER BY OBJECT_NAME(i.object_id)
Just un-comment where clause and replace table_name with actual table name to view the detail of
desired object.
https://riptutorial.com/ 197
www.dbooks.org
Chapter 67: Permissions and Security
Examples
Assign Object Permissions to a user
In Production its good practice to secure your data and only allow operations on it to be
undertaken via Stored Procedures. This means your application can't directly run CRUD
operations on your data and potentially cause problems. Assigning permissions is a time-
consuming, fiddly and generally onerous task. For this reason its often easier to harness some of
the (considerable) power contained in the INFORMATION_SCHEMA er schema which is
contained in every SQL Server database.
Instead individually assigning permissions to a user on a piece-meal basis, just run the script
below, copy the output and then run it in a Query window.
https://riptutorial.com/ 198
Chapter 68: PHANTOM read
Introduction
In database systems, isolation determines how transaction integrity is visible to other users and
systems, so it defines how/when the changes made by one operation become visible to other. The
phantom read may occurs when you getting data not yet commited to database.
Remarks
You can read the various ISOLATION LEVEL on MSDN
Examples
Isolation level READ UNCOMMITTED
Now open a First query editor (on the database) insert the code below, and execute (do not
touch the --rollback) in this case you insert a row on DB but do not commit changes.
begin tran
--rollback
Now open a Second Query Editor (on the database), insert the code below and execute
begin tran
You may notice that on second editor you can see the newly created row (but not committed) from
https://riptutorial.com/ 199
www.dbooks.org
first transaction. On first editor execute the rollback (select the rollback word and execute).
Execute the query on second editor and you see that the record disappear (phantom read), this
occurs because you tell, to the 2nd transaction to get all rows, also the uncommitteds.
https://riptutorial.com/ 200
Chapter 69: PIVOT / UNPIVOT
Syntax
• SELECT <non-pivoted column>,
[first pivoted column] AS <column name>,
[second pivoted column] AS <column name>,
...
[last pivoted column] AS <column name>
FROM
(<SELECT query that produces the data>)
AS <alias for the source query>
PIVOT
(
<aggregation function>(<column being aggregated>)
FOR
[<column that contains the values that will become column headers>]
IN ( [first pivoted column], [second pivoted column],
... [last pivoted column])
) AS <alias for the pivot table> <optional ORDER BY clause>;
Remarks
Using PIVOT and UNPIVOT operators you transform a table by shifting the rows (column values)
of a table to columns and vise-versa. As part of this transformation aggregation functions can be
applied on the table values.
Examples
Simple Pivot - Static Columns
Using Item Sales Table from Example Database, let us calculate and show the total Quantity we
sold of each Product.
This can be easily done with a group by, but lets assume we to 'rotate' our result table in a way
that for each Product Id we have a column.
https://riptutorial.com/ 201
www.dbooks.org
Since our 'new' columns are numbers (in the source table), we need to square brackets []
100 145
45 18
Below is a simple example which shows average item's price of each item per weekday.
First, suppose we have a table which keeps daily records of all items' prices.
+========+=========+=======+
| item | weekday | price |
+========+=========+=======+
| Item1 | Mon | 110 |
+--------+---------+-------+
| Item2 | Mon | 230 |
+--------+---------+-------+
| Item3 | Mon | 150 |
+--------+---------+-------+
| Item1 | Tue | 115 |
+--------+---------+-------+
| Item2 | Tue | 231 |
+--------+---------+-------+
| Item3 | Tue | 162 |
+--------+---------+-------+
| . . . |
+--------+---------+-------+
| Item2 | Wed | 220 |
+--------+---------+-------+
| Item3 | Wed | 142 |
+--------+---------+-------+
In order to perform aggregation which is to find the average price per item for each week day, we
are going to use the relational operator PIVOT to rotate the column weekday of table-valued
expression into aggregated row values as below:
https://riptutorial.com/ 202
SELECT * FROM tbl_stock
PIVOT (
AVG(price) FOR weekday IN ([Mon], [Tue], [Wed], [Thu], [Fri])
) pvt;
Result:
+--------+------+------+------+------+------+
| item | Mon | Tue | Wed | Thu | Fri |
+--------+------+------+------+------+------+
| Item1 | 116 | 112 | 117 | 109 | 120 |
| Item2 | 227 | 233 | 230 | 228 | 210 |
| Item3 | 145 | 158 | 152 | 145 | 125 |
+--------+------+------+------+------+------+
Lastly, in order to perform the reverse operation of PIVOT, we can use the relational operator
UNPIVOT to rotate columns into rows as below:
Result:
+=======+========+=========+
| item | price | weekday |
+=======+========+=========+
| Item1 | 116 | Mon |
+-------+--------+---------+
| Item1 | 112 | Tue |
+-------+--------+---------+
| Item1 | 117 | Wed |
+-------+--------+---------+
| Item1 | 109 | Thu |
+-------+--------+---------+
| Item1 | 120 | Fri |
+-------+--------+---------+
| Item2 | 227 | Mon |
+-------+--------+---------+
| Item2 | 233 | Tue |
+-------+--------+---------+
| Item2 | 230 | Wed |
+-------+--------+---------+
| Item2 | 228 | Thu |
+-------+--------+---------+
| Item2 | 210 | Fri |
+-------+--------+---------+
| Item3 | 145 | Mon |
+-------+--------+---------+
| Item3 | 158 | Tue |
+-------+--------+---------+
| Item3 | 152 | Wed |
+-------+--------+---------+
https://riptutorial.com/ 203
www.dbooks.org
| Item3 | 145 | Thu |
+-------+--------+---------+
| Item3 | 125 | Fri |
+-------+--------+---------+
Dynamic PIVOT
One problem with the PIVOT query is that you have to specify all values inside the IN selection if
you want to see them as columns. A quick way to circumvent this problem is to create a dynamic
IN selection making your PIVOT dynamic.
For demonstration we will use a table Books in a Bookstore’s database. We assume that the table is
quite de-normalised and has following columns
Table: Books
-----------------------------
BookId (Primary Key Column)
Name
Language
NumberOfPages
EditionNumber
YearOfPrint
YearBoughtIntoStore
ISBN
AuthorName
Price
NumberOfUnitsSold
GO
Now if we need to query on the database and figure out number of books in English, Russian,
German, Hindi, Latin languages bought into the bookstore every year and present our output in a
small report format, we can use PIVOT query like this
https://riptutorial.com/ 204
SELECT * FROM
(
SELECT YearBoughtIntoStore AS [Year Bought],[Language], NumberOfBooks
FROM BookList
) sourceData
PIVOT
(
SUM(NumberOfBooks)
FOR [Language] IN (English, Russian, German, Hindi, Latin)
) pivotrReport
Special case is when we do not have a full list of the languages, so we'll use dynamic SQL like
below
https://riptutorial.com/ 205
www.dbooks.org
Chapter 70: Primary Keys
Remarks
Primary keys are used to uniquely identify a record in a table. A table may only have a single
primary key (though the primary key can consist of multiple columns), and a primary key is
required for certain types of replication.
Primary keys are often used as (but don't have to be) the clustered index on a table.
Examples
Create table w/ identity column as primary key
-- natural primary key - using an existing piece of data within the table that uniquely
identifies the record
create table person (
firstName varchar(100) not null,
lastName varchar(100) not null,
dob DateTime not null,
ssn varchar(9) primary key not null
)
-- composite key - using two or more existing columns within a table to create a primary key
https://riptutorial.com/ 206
create table person (
firstName varchar(100) not null,
lastName varchar(100) not null,
dob DateTime not null,
ssn varchar(9) not null,
primary key (firstName, lastName, dob)
)
Note, if the primary key column (in this case ssn) has more than one row with the same candidate
key, the above statement will fail, as primary key values must be unique.
https://riptutorial.com/ 207
www.dbooks.org
Chapter 71: Privileges or Permissions
Examples
Simple rules
USE AdventureWorks;
GRANT CREATE TABLE TO MelanieK;
GO
USE AdventureWorks2012;
GRANT SHOWPLAN TO AuditMonitor;
GO
USE AdventureWorks2012;
GRANT CREATE VIEW TO CarmineEs WITH GRANT OPTION;
GO
use YourDatabase
go
exec sp_addrolemember 'db_owner', 'UserName'
go
https://riptutorial.com/ 208
Chapter 72: Queries with JSON data
Examples
Using values from JSON in query
JSON_VALUE function enables you to take a data from JSON text on the path specified as the
second argument, and use this value in any part of the select query:
Once JSON values are extracted from JSON text, you can use them ina any part of the query. You
can create some kind of report on JSON data with grouping aggregations, etc:
If some JSON text might not be properly formatted, you can remove those entries from query
using ISJSON function.
JSON_MODIFY function can be used to update value on some path. You can use this function to
modify original value of JSON cell in UPDATE statement:
update Product
set Data = JSON_MODIFY(Data, '$.Price', 24.99)
where ProductID = 17;
JSON_MODIFY function will update or create Price key (if it does not exists). If new value is
NULL, the key will be removed. JSON_MODIFY function will treat new value as string (escape
special characters, wrap it with double quotes to create proper JSON string). If your new value is
JSON fragment, you should wrap it with JSON_QUERY function:
https://riptutorial.com/ 209
www.dbooks.org
update Product
set Data = JSON_MODIFY(Data, '$.tags', JSON_QUERY('["promo","new"]'))
where ProductID = 17;
JSON_QUERY function without second parameter behaves like a "cast to JSON". Since the result
of JSON_QUERY is valid JSON fragment (object or array), JSON_MODIFY will no escape this
value when modifies input JSON.
JSON_MODIFY function can be used to append new value to some array inside JSON:
update Product
set Data = JSON_MODIFY(Data, 'append $.tags', "sales")
where ProductID = 17;
New value will be appended at the end of the array, or a new array with value ["sales"] will be
created. JSON_MODIFY function will treat new value as string (escape special characters, wrap it
with double quotes to create proper JSON string). If your new value is JSON fragment, you should
wrap it with JSON_QUERY function:
update Product
set Data = JSON_MODIFY(Data, 'append $.tags', JSON_QUERY('{"type":"new"}'))
where ProductID = 17;
JSON_QUERY function without second parameter behaves like a "cast to JSON". Since the result
of JSON_QUERY is valid JSON fragment (object or array), JSON_MODIFY will no escape this
value when modifies input JSON.
If you have a "child table" formatted as JSON collection and stored in-row as JSON column, you
can unpack this collection, transform it to table and join it with parent row. Instead of the standard
JOIN operator, you should use CROSS APPLY. In this example, product parts are formatted as
collection of JSON objects in and stored in Data column:
Result of the query is equivalent to the join between Product and Part tables.
In this example, Tags array may contain various keywords like ["promo", "sales"], so we can open
this array and filter values:
https://riptutorial.com/ 210
CROSS APPLY OPENJSON(Data, '$.Tags')
where value = 'sales'
OPENJSON will open inner collection of tags and return it as table. Then we can filter results by
some value in the table.
https://riptutorial.com/ 211
www.dbooks.org
Chapter 73: Query Hints
Examples
JOIN Hints
When you join two tables, SQL Server query optimizer (QO) can choose different types of joins
that will be used in query:
• HASH join
• LOOP join
• MERGE join
QO will explore plans and choose the optimal operator for joining tables. However, if you are sure
that you know what would be the optimal join operator, you can specify what kind of JOIN should
be used. Inner LOOP join will force QO to choose Nested loop join while joining two tables:
GROUP BY Hints
When you use GROUP BY clause, SQL Server query optimizer (QO) can choose different types of
grouping operators:
You can explicitly require that QO picks one or another aggregate operator if you know what would
be the optimal. With OPTION (ORDER GROUP), QO will always choose Stream aggregate and
add Sort operator in front of Stream aggregate if input is not sorted:
https://riptutorial.com/ 212
select OrderID, AVG(Quantity)
from Sales.OrderLines
group by OrderID
OPTION (ORDER GROUP)
Specifies that the query is optimized for fast retrieval of the first number_rows. This is a
nonnegative integer. After the first number_rows are returned, the query continues execution and
produces its full result set.
UNION hints
When you use UNION operator on two query results, Query optimizer (QO) can use following
operators to create a union of two result sets:
• Merge (Union)
• Concat (Union)
• Hash Match (Union)
You can explicitly specify what operator should be used using OPTION() hint:
MAXDOP Option
Specifies the max degree of parallelism for the query specifying this option.
SELECT OrderID,
AVG(Quantity)
https://riptutorial.com/ 213
www.dbooks.org
FROM Sales.OrderLines
GROUP BY OrderID
OPTION (MAXDOP 2);
This option overrides the MAXDOP configuration option of sp_configure and Resource Governor.
If MAXDOP is set to zero then the server chooses the max degree of parallelism.
INDEX Hints
Index hints are used to force a query to use a specific index, instead of allowing SQL Server's
Query Optimizer to choose what it deems the best index. In some cases you may gain benefits by
specifying the index a query must use. Usually SQL Server's Query Optimizer chooses the best
index suited for the query, but due to missing/outdated statistics or specific needs you can force it.
SELECT *
FROM mytable WITH (INDEX (ix_date))
WHERE field1 > 0
AND CreationDate > '20170101'
https://riptutorial.com/ 214
Chapter 74: Query Store
Examples
Enable query store on database
SQL Server/Azure SQL Database will collect information about executed queries and provide
information in sys.query_store views:
• sys.query_store_query
• sys.query_store_query_text
• sys.query_store_plan
• sys.query_store_runtime_stats
• sys.query_store_runtime_stats_interval
• sys.database_query_store_options
• sys.query_context_settings
The following query will return informationa about qeries, their plans and average statistics
regarding their duration, CPU time, physical and logical io reads.
If you want to remove some query or query plan from query store, you can use the following
commands:
EXEC sp_query_store_remove_query 4;
EXEC sp_query_store_remove_plan 3;
Parameters for these stored procedures are query/plan id retrieved from system views.
https://riptutorial.com/ 215
www.dbooks.org
You can also just remove execution statistics for particular plan without removing the plan from the
store:
EXEC sp_query_store_reset_exec_stats 3;
SQL Query optimizer will choose the baes possible plan that he can find for some query. If you
can find some plan that works optimally for some query, you can force QO to always use that plan
using the following stored procedure:
From this point, QO will always use plan provided for the query.
If you want to remove this binding, you can use the following stored procedure:
From this point, QO will again try to find the best plan.
https://riptutorial.com/ 216
Chapter 75: Querying results by page
Examples
Row_Number()
From which it will yield a result set with a RowID field which you can use to page between.
SELECT *
FROM
( SELECT Row_Number() OVER(ORDER BY UserName) As RowID, UserFirstName, UserLastName
FROM Users
) As RowResults
WHERE RowID Between 5 AND 10
https://riptutorial.com/ 217
www.dbooks.org
Chapter 76: Ranking Functions
Syntax
• DENSE_RANK ( ) OVER ( [ <partition_by_clause> ] < order_by_clause > )
• RANK ( ) OVER ( [ partition_by_clause ] order_by_clause )
Parameters
Arguments Details
Divides the result set produced by the FROM clause into partitions
<partition_by_clause> to which the DENSE_RANK function is applied. For the PARTITION BY
syntax, see OVER Clause (Transact-SQL).
Remarks
If two or more rows tie for a rank in the same partition, each tied rows receives the same rank. For
example, if the two top salespeople have the same SalesYTD value, they are both ranked one.
The salesperson with the next highest SalesYTD is ranked number two. This is one more than the
number of distinct rows that come before this row. Therefore, the numbers returned by the
DENSE_RANK function do not have gaps and always have consecutive ranks.
The sort order used for the whole query determines the order in which the rows appear in a result.
This implies that a row ranked number one does not have to be the first row in the partition.
Examples
https://riptutorial.com/ 218
RANK()
A RANK() Returns the rank of each row in the result set of partitioned column.
Eg :
Select Studentid,Name,Subject,Marks,
RANK() over(partition by name order by Marks desc)Rank
From Exam
order by name,subject
DENSE_RANK ()
https://riptutorial.com/ 219
www.dbooks.org
Chapter 77: Resource Governor
Remarks
Resource Governor in SQL Server is a feature that allows you to manage resource usage by
different applications and users. It kicks in realtime by setting CPU and memory limits. It will help
preventing that one heavy process will eat up all system resources while for example smaller tasks
are awaiting them.
Examples
Reading the Statistics
select *
from sys.dm_resource_governor_workload_groups
select *
from sys.dm_resource_governor_resource_pools
Create the function that contains the logic for the resource governor and attach it
https://riptutorial.com/ 220
END
end
GO
GO
GO
https://riptutorial.com/ 221
www.dbooks.org
Chapter 78: Retrieve information about the
database
Remarks
As with other relational database systems, SQL Server exposes metadata about your databases.
This is provided through the ISO Standard INFORMATION_SCHEMA schema, or the SQL Server-specific
sys catalog views.
Examples
Count the Number of Tables in a Database
This query will return the number of tables in the specified database.
USE YourDatabaseName
SELECT COUNT(*) from INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
Following is another way this can be done for all user tables with SQL Server 2008+. The
reference is here.
The following queries will return a list of all Stored Procedures in the database, with basic
information about each Stored Procedure:
SELECT *
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_TYPE = 'PROCEDURE'
The ROUTINE_NAME, ROUTINE_SCHEMA and ROUTINE_DEFINITION columns are generally the most useful.
SELECT *
FROM sys.objects
WHERE type = 'P'
https://riptutorial.com/ 222
SELECT *
FROM sys.procedures
Note that this version has an advantage over selecting from sys.objects since it includes the
additional columns is_auto_executed, is_execution_replicated, is_repl_serializable, and
skips_repl_constraints.
SELECT *
FROM sysobjects
WHERE type = 'P'
Note that the output contains many columns that will never relate to a stored procedure.
The next set of queries will return all Stored Procedures in the database that include the string
'SearchTerm':
SELECT o.name
FROM syscomments c
INNER JOIN sysobjects o
ON c.id=o.id
WHERE o.xtype = 'P'
AND c.TEXT LIKE '%SearchTerm%'
SELECT p.name
FROM sys.sql_modules AS m
INNER JOIN sys.procedures AS p
ON m.object_id = p.object_id
WHERE definition LIKE '%SearchTerm%'
Method 1: Below query will be applicable for SQL Server 2000+ version (Contains 12 columns)
Method 2: Below query extract information about databases with more informations (ex: State,
Isolation, recovery model etc.)
Note: This is a catalog view and will be available SQL SERVER 2005+ versions
Method 3: To see just database names you can use undocumented sp_MSForEachDB
https://riptutorial.com/ 223
www.dbooks.org
Method 4: Below SP will help you to provide database size along with databases name , owner,
status etc. on the server
EXEC sp_helpdb
Method 5 Similarly, below stored procedure will give database name, database size and Remarks
EXEC sp_databases
Database Files
Display all data files for all databases with size and growth info
FROM Master.SYS.SYSALTFILES SF
Join Master.SYS.Databases d on sf.fileid = d.database_id
Order by d.name
SELECT
s.name + '.' + t.NAME AS TableName,
SUM(a.used_pages)*8 AS 'TableSizeKB' --a page in SQL Server is 8kb
FROM sys.tables t
JOIN sys.schemas s on t.schema_id = s.schema_id
LEFT JOIN sys.indexes i ON t.OBJECT_ID = i.object_id
LEFT JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
LEFT JOIN sys.allocation_units a ON p.partition_id = a.container_id
GROUP BY
s.name, t.name
ORDER BY
--Either sort by name:
s.name + '.' + t.NAME
--Or sort largest to smallest:
https://riptutorial.com/ 224
--SUM(a.used_pages) desc
This will show the user type and permission path (which windows group the user is getting its
permissions from).
xp_logininfo 'DOMAIN\user'
This query will return all COLUMNS and their associated TABLES for a given column name. It is
designed to show you what tables (unknown) contain a specified column (known)
SELECT
c.name AS ColName,
t.name AS TableName
FROM
sys.columns c
JOIN sys.tables t ON c.object_id = t.object_id
WHERE
c.name LIKE '%MyName%'
It is sometimes useful to verify that your work on Developer edition hasn't introduced a
dependency on any features restricted to Enterprise edition.
You can do this using the sys.dm_db_persisted_sku_features system view, like so:
Search and Return All Tables and Columns Containing a Specified Column
Value
This script, from here and here, will return all Tables and Columns where a specified value exists.
This is powerful in finding out where a certain value is in a database. It can be taxing, so it is
suggested that it be executed in a backup / test enviroment first.
https://riptutorial.com/ 225
www.dbooks.org
-- Written by: Narayana Vyas Kondreddi
-- Site: http://vyaskn.tripod.com
-- Updated and tested by Tim Gaunt
-- http://www.thesitedoctor.co.uk
--
http://blogs.thesitedoctor.co.uk/tim/2010/02/19/Search+Every+Table+And+Field+In+A+SQL+Server+Database+U
-- Tested on: SQL Server 7.0, SQL Server 2000, SQL Server 2005 and SQL Server 2010
-- Date modified: 03rd March 2011 19:00 GMT
CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630))
SET NOCOUNT ON
BEGIN
SET @ColumnName = ''
SET @TableName =
(
SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
AND OBJECTPROPERTY(
OBJECT_ID(
QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
), 'IsMSShipped'
) = 0
)
BEGIN
SET @ColumnName =
(
SELECT MIN(QUOTENAME(COLUMN_NAME))
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = PARSENAME(@TableName, 2)
AND TABLE_NAME = PARSENAME(@TableName, 1)
AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar', 'int',
'decimal')
AND QUOTENAME(COLUMN_NAME) > @ColumnName
)
BEGIN
INSERT INTO #Results
EXEC
(
'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName +
', 3630) FROM ' + @TableName + ' (NOLOCK) ' +
' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
)
END
END
END
https://riptutorial.com/ 226
SELECT ColumnName, ColumnValue FROM #Results
SELECT
s.name AS [schema],
t.object_id AS [table_object_id],
t.name AS [table_name],
c.column_id,
c.name AS [column_name],
i.name AS [index_name],
i.type_desc AS [index_type]
FROM sys.schemas AS s
INNER JOIN sys.tables AS t
ON s.schema_id = t.schema_id
INNER JOIN sys.columns AS c
ON t.object_id = c.object_id
LEFT JOIN sys.index_columns AS ic
ON c.object_id = ic.object_id and c.column_id = ic.column_id
LEFT JOIN sys.indexes AS i
ON ic.object_id = i.object_id and ic.index_id = i.index_id
ORDER BY [schema], [table_name], c.column_id;
USE msdb
Go
https://riptutorial.com/ 227
www.dbooks.org
WHEN 3 THEN cast('00:0'
+ Left(right(active_start_time,3),1)
+':' + right(active_start_time,2) as char (8))
WHEN 4 THEN cast('00:'
+ Left(right(active_start_time,4),2)
+':' + right(active_start_time,2) as char (8))
WHEN 5 THEN cast('0'
+ Left(right(active_start_time,5),1)
+':' + Left(right(active_start_time,4),2)
+':' + right(active_start_time,2) as char (8))
WHEN 6 THEN cast(Left(right(active_start_time,6),2)
+':' + Left(right(active_start_time,4),2)
+':' + right(active_start_time,2) as char (8))
END,
CASE len(run_duration)
WHEN 1 THEN cast('00:00:0'
+ cast(run_duration as char) as char (8))
WHEN 2 THEN cast('00:00:'
+ cast(run_duration as char) as char (8))
WHEN 3 THEN cast('00:0'
+ Left(right(run_duration,3),1)
+':' + right(run_duration,2) as char (8))
WHEN 4 THEN cast('00:'
+ Left(right(run_duration,4),2)
+':' + right(run_duration,2) as char (8))
WHEN 5 THEN cast('0'
+ Left(right(run_duration,5),1)
+':' + Left(right(run_duration,4),2)
+':' + right(run_duration,2) as char (8))
WHEN 6 THEN cast(Left(right(run_duration,6),2)
+':' + Left(right(run_duration,4),2)
+':' + right(run_duration,2) as char (8))
END as 'Max Duration',
CASE(dbo.sysschedules.freq_subday_interval)
WHEN 0 THEN 'Once'
ELSE cast('Every '
+ right(dbo.sysschedules.freq_subday_interval,2)
+ ' '
+ CASE(dbo.sysschedules.freq_subday_type)
WHEN 1 THEN 'Once'
WHEN 4 THEN 'Minutes'
WHEN 8 THEN 'Hours'
END as char(16))
END as 'Subday Frequency'
FROM dbo.sysjobs
LEFT OUTER JOIN dbo.sysjobschedules
ON dbo.sysjobs.job_id = dbo.sysjobschedules.job_id
INNER JOIN dbo.sysschedules ON dbo.sysjobschedules.schedule_id = dbo.sysschedules.schedule_id
LEFT OUTER JOIN (SELECT job_id, max(run_duration) AS run_duration
FROM dbo.sysjobhistory
GROUP BY job_id) Q1
ON dbo.sysjobs.job_id = Q1.job_id
WHERE Next_run_time = 0
UNION
https://riptutorial.com/ 228
END,
'Frequency' = CASE dbo.sysschedules.freq_type
WHEN 1 THEN 'Once'
WHEN 4 THEN 'Daily'
WHEN 8 THEN 'Weekly'
WHEN 16 THEN 'Monthly'
WHEN 32 THEN 'Monthly relative'
WHEN 64 THEN 'When SQLServer Agent starts'
END,
'Start Date' = CASE next_run_date
WHEN 0 THEN null
ELSE
substring(convert(varchar(15),next_run_date),1,4) + '/' +
substring(convert(varchar(15),next_run_date),5,2) + '/' +
substring(convert(varchar(15),next_run_date),7,2)
END,
'Start Time' = CASE len(next_run_time)
WHEN 1 THEN cast('00:00:0' + right(next_run_time,2) as char(8))
WHEN 2 THEN cast('00:00:' + right(next_run_time,2) as char(8))
WHEN 3 THEN cast('00:0'
+ Left(right(next_run_time,3),1)
+':' + right(next_run_time,2) as char (8))
WHEN 4 THEN cast('00:'
+ Left(right(next_run_time,4),2)
+':' + right(next_run_time,2) as char (8))
WHEN 5 THEN cast('0' + Left(right(next_run_time,5),1)
+':' + Left(right(next_run_time,4),2)
+':' + right(next_run_time,2) as char (8))
WHEN 6 THEN cast(Left(right(next_run_time,6),2)
+':' + Left(right(next_run_time,4),2)
+':' + right(next_run_time,2) as char (8))
END,
CASE len(run_duration)
WHEN 1 THEN cast('00:00:0'
+ cast(run_duration as char) as char (8))
WHEN 2 THEN cast('00:00:'
+ cast(run_duration as char) as char (8))
WHEN 3 THEN cast('00:0'
+ Left(right(run_duration,3),1)
+':' + right(run_duration,2) as char (8))
WHEN 4 THEN cast('00:'
+ Left(right(run_duration,4),2)
+':' + right(run_duration,2) as char (8))
WHEN 5 THEN cast('0'
+ Left(right(run_duration,5),1)
+':' + Left(right(run_duration,4),2)
+':' + right(run_duration,2) as char (8))
WHEN 6 THEN cast(Left(right(run_duration,6),2)
+':' + Left(right(run_duration,4),2)
+':' + right(run_duration,2) as char (8))
END as 'Max Duration',
CASE(dbo.sysschedules.freq_subday_interval)
WHEN 0 THEN 'Once'
ELSE cast('Every '
+ right(dbo.sysschedules.freq_subday_interval,2)
+ ' '
+ CASE(dbo.sysschedules.freq_subday_type)
WHEN 1 THEN 'Once'
WHEN 4 THEN 'Minutes'
WHEN 8 THEN 'Hours'
https://riptutorial.com/ 229
www.dbooks.org
END as char(16))
END as 'Subday Frequency'
FROM dbo.sysjobs
LEFT OUTER JOIN dbo.sysjobschedules ON dbo.sysjobs.job_id = dbo.sysjobschedules.job_id
INNER JOIN dbo.sysschedules ON dbo.sysjobschedules.schedule_id = dbo.sysschedules.schedule_id
LEFT OUTER JOIN (SELECT job_id, max(run_duration) AS run_duration
FROM dbo.sysjobhistory
GROUP BY job_id) Q1
ON dbo.sysjobs.job_id = Q1.job_id
WHERE Next_run_time <> 0
To get the list of all backup operations performed on the current database instance:
To get the list of all restore operations performed on the current database instance:
SELECT
[d].[name] AS database_name,
[r].restore_date AS last_restore_date,
[r].[user_name],
[bs].[backup_finish_date] AS backup_creation_date,
[bmf].[physical_device_name] AS [backup_file_used_for_restore]
FROM master.sys.databases [d]
LEFT OUTER JOIN msdb.dbo.[restorehistory] r ON r.[destination_database_name] = d.Name
INNER JOIN msdb.dbo.backupset [bs] ON [r].[backup_set_id] = [bs].[backup_set_id]
INNER JOIN msdb.dbo.backupmediafamily bmf ON [bs].[media_set_id] = [bmf].[media_set_id]
ORDER BY [d].[name], [r].restore_date DESC
SELECT DISTINCT
o.name AS Object_Name,o.type_desc
FROM sys.sql_modules m
INNER JOIN sys.objects o ON m.object_id=o.object_id
WHERE m.definition Like '%myField%'
ORDER BY 2,1
https://riptutorial.com/ 230
Chapter 79: Retrieve Information about your
Instance
Examples
Retrieve Local and Remote Servers
EXEC sp_helpserver;
sp_who2
This procedure can be used to find information on current SQL server sessions. Since it is a
procedure, it's often helpful to store the results into a temporary table or table variable so one can
order, filter, and transform the results as needed.
-- Create a variable table to hold the results of sp_who2 for querying purposes
SELECT *
FROM @who2 w
WHERE 1=1
Examples:
https://riptutorial.com/ 231
www.dbooks.org
SELECT *
FROM @who2 w
WHERE 1=1
and login = 'userName'
To discover SQL Server's edition, product level and version number as well as the host machine
name and the server type:
https://riptutorial.com/ 232
SELECT o.type_desc AS ROUTINE_TYPE,o.[name] AS ROUTINE_NAME,
m.definition AS ROUTINE_DEFINITION
FROM sys.sql_modules AS m INNER JOIN sys.objects AS o
ON m.object_id = o.object_id WHERE m.definition LIKE '%Keyword%'
order by ROUTINE_NAME
WITH LastRestores AS
(
SELECT
DatabaseName = [d].[name] ,
[d].[create_date] ,
[d].[compatibility_level] ,
[d].[collation_name] ,
r.*,
RowNum = ROW_NUMBER() OVER (PARTITION BY d.Name ORDER BY r.[restore_date] DESC)
FROM master.sys.databases d
LEFT OUTER JOIN msdb.dbo.[restorehistory] r ON r.[destination_database_name] = d.Name
)
SELECT *
FROM [LastRestores]
WHERE [RowNum] = 1
https://riptutorial.com/ 233
www.dbooks.org
Chapter 80: Row-level security
Examples
RLS filter predicate
Sql Server 2016+ and Azure Sql database enables you to automatically filter rows that are
returned in select statement using some predicate. This feature is called Row-level security.
First, you need a table-valued function that contains some predicate that describes what it the
condition that will allow users to read data from some table:
dbo.pUserCanAccessCompany(@CompanyID int)
RETURNS TABLE
WITH SCHEMABINDING
AS RETURN (
SELECT 1 as canAccess WHERE
In this example, the predicate says that only users that have a value in SESSION_CONTEXT that
is matching input argument can access the company. You can put any other condition e.g. that
checks database role or database_id of the current user, etc.
Most of the code above is a template that you will copy-paste. The only thing that will
change here is the name and arguments of predicate and condition in WHERE clause.
Now you create security policy that will apply this predicate on some table.
Now you can create security policy that will apply predicate on some table:
This security policy assigns predicate to company table. Whenever someone tries to read data
from Company table , security policy will apply predicate on each row, pass CompanyID column
as a parameter of the predicate, and predicate will evaluate should this row be returned in the
result of SELECT query.
Security policy is a group of predicates associated to tables that can be managed together. You
https://riptutorial.com/ 234
can add, or remove predicates or turn on/off entire policy.
You can add more predicates on tables in the existing security policy.
Row-level security enables you to define some predicates that will control who could update rows
in the table. First you need to define some table-value function that represents predicate that wll
control access policy.
CREATE FUNCTION
dbo.pUserCanAccessProduct(@CompanyID int)
RETURNS TABLE
WITH SCHEMABINDING
) In this example, the predicate says that only users that have a value in SESSION_CONTEXT
that is matching input argument can access the company. You can put any other condition e.g.
that checks database role or database_id of the current user, etc.
Most of the code above is a template that you will copy-paste. The only thing that will
change here is the name and arguments of predicate and condition in WHERE clause.
Now you create security policy that will apply this predicate on some table.
Now we can create security policy with the predicate that will block updates on product table if
CompanyID column in table do not satisfies predicate.
https://riptutorial.com/ 235
www.dbooks.org
dbo.pUserCanAccessProduct(CompanyID) ON dbo.Product
This predicate will be applied on all operations. If you want to apply predicate on some operation
you can write something like:
Possible options that you can add after block predicate definition are:
https://riptutorial.com/ 236
Chapter 81: Scheduled Task or Job
Introduction
SQL Server Agent uses SQL Server to store job information. Jobs contain one or more job steps.
Each step contains its own task,i.e: backing up a database. SQL Server Agent can run a job on a
schedule, in response to a specific event, or on demand.
Examples
Create a scheduled Job
Create a Job
USE msdb ;
GO
EXEC dbo.sp_add_job
@job_name = N'Weekly Job' ; -- the job name
• Then we have to add a job step using a stored procedure named sp_add_jobStep
EXEC sp_add_jobstep
@job_name = N'Weekly Job', -- Job name to add a step
@step_name = N'Set database to read only', -- step name
@subsystem = N'TSQL', -- Step type
@command = N'ALTER DATABASE SALES SET READ_ONLY', -- Command
@retry_attempts = 5, --Number of attempts
@retry_interval = 5 ; -- in minutes
EXEC dbo.sp_add_jobserver
@job_name = N'Weekly Sales Data Backup',
@server_name = 'MyPC\data; -- Default is LOCAL
GO
USE msdb
GO
EXEC sp_add_schedule
@schedule_name = N'NightlyJobs' , -- specify the schedule name
@freq_type = 4, -- A value indicating when a job is to be executed (4) means Daily
@freq_interval = 1, -- The days that a job is executed and depends on the value of
https://riptutorial.com/ 237
www.dbooks.org
`freq_type`.
@active_start_time = 010000 ; -- The time on which execution of a job can begin
GO
There are more parameters that can be used with sp_add_schedule you can read more about in the
the link provided above.
To attach a schedule to an SQL agent job you have to use a stored procedure called
sp_attach_schedule
https://riptutorial.com/ 238
Chapter 82: Schemas
Examples
Creating a Schema
Alter Schema
This would transfer the tbl_Staging table from the dbo schema to the dvr schema
Dropping Schemas
Purpose
Schema refers to a specific database tables and how they are related to each other. It provides an
organisational blueprint of how the database is constructed. Additional benefits of implementing
database schemas is that schemas can be used as a method restricting / granting access to
specific tables within a database.
https://riptutorial.com/ 239
www.dbooks.org
Chapter 83: SCOPE_IDENTITY()
Syntax
• SELECT SCOPE_IDENTITY();
• SELECT SCOPE_IDENTITY() AS [SCOPE_IDENTITY];
• SCOPE_IDENTITY()
Examples
Introduction with Simple Example
SCOPE_IDENTITY() returns the last identity value inserted into an identity column in the same
scope. A scope is a module: a stored procedure, trigger, function, or batch. Therefore, two
statements are in the same scope if they are in the same stored procedure, function, or batch.
https://riptutorial.com/ 240
Chapter 84: SELECT statement
Introduction
In SQL, SELECT statements return sets of results from data collections like tables or views. SELECT
statements can be used with various other clauses like WHERE, GROUP BY, or ORDER BY to further refine
the desired results.
Examples
Basic SELECT from table
Select all columns from some table (system table in this case):
SELECT *
FROM sys.objects
WHERE clause filters only those rows that satisfy some condition:
SELECT *
FROM sys.objects
WHERE type = 'IT'
ORDER BY clause sorts rows in the returned result set by some column or expression:
SELECT *
FROM sys.objects
ORDER BY create_date
https://riptutorial.com/ 241
www.dbooks.org
You can apply some function on each group (aggregate function) to calculate sum or count of the
records in the group.
type c
SQ 3
S 72
IT 16
PK 1
U 5
type c
SQ 3
PK 1
U 5
SELECT TOP 10 *
FROM sys.objects
OFFSET FETCH clause is more advanced version of TOP. It enables you to skip N1 rows and
take next N2 rows:
SELECT *
FROM sys.objects
ORDER BY object_id
OFFSET 50 ROWS FETCH NEXT 10 ROWS ONLY
https://riptutorial.com/ 242
You can use OFFSET without fetch to just skip first 50 rows:
SELECT *
FROM sys.objects
ORDER BY object_id
OFFSET 50 ROWS
https://riptutorial.com/ 243
www.dbooks.org
Chapter 85: Sequences
Examples
Create Sequence
Results
CustomerID CustomerName
10001 Jerry
10002 Gorge
https://riptutorial.com/ 244
Results
CustomerID CustomerName
10001 Jerry
10003 George
https://riptutorial.com/ 245
www.dbooks.org
Chapter 86: Service broker
Examples
1. Basics
More: https://msdn.microsoft.com/en-us/library/bb522893.aspx
USE [MyDatabase]
https://riptutorial.com/ 246
GRANT SEND ON SERVICE::[TargetService] TO PUBLIC
GO
For this demonstration we will use service broker construction created in another part of this
documentation. Mentioned part is named 3. Create basic service broker construction on
database (single database communication).
USE [MyDatabase]
SET @msg = (
SELECT 'HelloThere' "elementNum1"
FOR XML PATH(''), ROOT('ExampleRoot'), ELEMENTS XSINIL, TYPE
);
For this demonstration we will use service broker construction created in another part of this
documentation. Mentioned part is called 3. Create basic service broker construction on
database (single database communication).
First we need to create a procedure that is able to read and process data from the Queue
USE [MyDatabase]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
AS
BEGIN
https://riptutorial.com/ 247
www.dbooks.org
declare
@message_body xml,
@message_type_name nvarchar(256),
@conversation_handle uniqueidentifier,
@messagetypename nvarchar(256);
WHILE 1=1
BEGIN
BEGIN TRANSACTION
WAITFOR(
RECEIVE TOP(1)
@message_body = CAST(message_body as xml),
@message_type_name = message_type_name,
@conversation_handle = conversation_handle,
@messagetypename = message_type_name
FROM DwhInsertSmsQueue
), TIMEOUT 1000;
IF (@@ROWCOUNT = 0)
BEGIN
ROLLBACK TRANSACTION
BREAK
END
IF (@messagetypename = '//initiator')
BEGIN
END
IF (@messagetypename = 'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog')
BEGIN
END CONVERSATION @conversation_handle;
END
COMMIT TRANSACTION
END
END
USE [MyDatabase]
https://riptutorial.com/ 248
MAX_QUEUE_READERS = 1 , --number of readers
EXECUTE AS SELF )
https://riptutorial.com/ 249
www.dbooks.org
Chapter 87: Sorting/ordering rows
Examples
Basics
Remember that when retrieving data, if you don't specify a row ordering clause (ORDER BY) SQL
server does not guarantee the sorting (order of the columns) at any time. Really, at any time. And
there's no point arguing about that, it has been shown literaly thousands of times and all over the
internet.
-- Ascending - upwards
SELECT * FROM SortOrder ORDER BY ID ASC
GO
-- Ascending is default
SELECT * FROM SortOrder ORDER BY ID
https://riptutorial.com/ 250
GO
-- Descending - downwards
SELECT * FROM SortOrder ORDER BY ID DESC
GO
When ordering by the textual column ((n)char or (n)varchar), pay attention that the order respects
the collation. For more information on collation look up for the topic.
Ordering and sorting of data can consume resources. This is where properly created indexes
come handy. For more information on indexes look up for the topic.
There is a possibility to pseudo-randomize the order of rows in your resultset. Just force the
ordering to appear nondeterministic.
Ordering can be remembered in a stored procedure, and that's the way you should do it if it is the
last step of manipulating the rowset before showing it to the end user.
EXEC GetSortOrder
GO
There is a limited (and hacky) support for ordering in the SQL Server views as well, but be
encouraged NOT to use it.
-- This will work, but hey... should you really use it?
CREATE VIEW VwSortOrder2
AS
SELECT TOP 99999999 *
FROM SortOrder
ORDER BY ID DESC
GO
https://riptutorial.com/ 251
www.dbooks.org
GO
For ordering you can either use column names, aliases or column numbers in your ORDER BY.
SELECT *
FROM SortOrder
ORDER BY [Text]
-- New resultset column aliased as 'Msg', feel free to use it for ordering
SELECT ID, [Text] + ' (' + CAST(ID AS nvarchar(10)) + ')' AS Msg
FROM SortOrder
ORDER BY Msg
-- Can be handy if you know your tables, but really NOT GOOD for production
SELECT *
FROM SortOrder
ORDER BY 2
I advise against using the numbers in your code, except if you want to forget about it the moment
after you execute it.
Order by Case
If you want to sort your data numerically or alphabetically, you can simply use order by [column]. If
you want to sort using a custom hierarchy, use a case statement.
Group
-----
Total
Young
MiddleAge
Old
Male
Female
Group
-----
Female
Male
MiddleAge
Old
Total
Young
Adding a 'case' statement, assigning ascending numerical values in the order you want your data
sorted:
https://riptutorial.com/ 252
Select * from MyTable
Order by case Group
when 'Total' then 10
when 'Male' then 20
when 'Female' then 30
when 'Young' then 40
when 'MiddleAge' then 50
when 'Old' then 60
end
Group
-----
Total
Male
Female
Young
MiddleAge
Old
https://riptutorial.com/ 253
www.dbooks.org
Chapter 88: Spatial Data
Introduction
There are 2 spatial data types
Geography Latitude/Longitude coordinate system for a curved surface (the earth). There are
multiple projections of curved surfaces so each geography spatial must let SQL Server know
which projection to use. The usual Spatial Reference ID (SRID) is 4326, which is measuring
distances in Kilometers. This is the default SRID used in most web maps
Examples
POINT
Creates a single Point. This will be a geometry or geography point depending on the class used.
Parameter Detail
Lat or X Is a float expression representing the x-coordinate of the Point being generated
Long or Y Is a float expression representing the y-coordinate of the Point being generated
--Explicit constructor
DECLARE @gm1 GEOMETRY = GEOMETRY::Point(10,5,0)
https://riptutorial.com/ 254
Read Spatial Data online: https://riptutorial.com/sql-server/topic/6816/spatial-data
https://riptutorial.com/ 255
www.dbooks.org
Chapter 89: Split String function in Sql Server
Examples
Split a String in Sql Server 2016
In SQL Server 2016 finally they have introduced Split string function : STRING_SPLIT
String:
separator :
Example:
Select Value
From STRING_SPLIT('a|b|c','|')
In above example
String : 'a|b|c'
separator : '|'
Result :
+-----+
|Value|
+-----+
|a |
+-----+
|b |
+-----+
|c |
+-----+
SELECT value
FROM STRING_SPLIT('',',')
Result :
https://riptutorial.com/ 256
+-----+
|Value|
+-----+
1 | |
+-----+
SELECT value
FROM STRING_SPLIT('',',')
WHERE LTRIM(RTRIM(value))<>''
Since there is no STRING_SPLIT function we need to use XML hack to split the string into rows:
Example:
Result:
+-----+
|Value|
+-----+
|A |
+-----+
|B |
+-----+
|C |
+-----+
Select @text
https://riptutorial.com/ 257
www.dbooks.org
string-function-in-sql-server
https://riptutorial.com/ 258
Chapter 90: SQL Server Evolution through
different versions (2000 - 2016)
Introduction
I am using SQL Server since 2004. I started with 2000 and now I am going to use SQL Server
2016. I created tables, views, functions, triggers, stored procedures and wrote many SQL queries
but I did not use many new features from subsequent versions. I googled it but unfortunately, I did
not find all the features in one place. So I gathered and validated these information from different
sources and put here. I am just adding the high level information for all the versions starting from
2000 to 20
Examples
SQL Server Version 2000 - 2016
The following features added in SQL Server 2000 from its previous version:
The following features added in version 2005 from its previous version:
https://riptutorial.com/ 259
www.dbooks.org
single client to have more than one active request per connection.
13. SQL Server Integration Services (Will be used as a primary ETL (Extraction, Transformation
and Loading) Tool
14. Enhancements in Analysis Services and Reporting Services.
15. Table and index partitioning. Allows partitioning of tables and indexes based on partition
boundaries as specified by a PARTITION FUNCTION with individual partitions mapped to
file groups via a PARTITION SCHEME.
The following features added in version 2008 from its previous version:
The following features added in version 2008 R2 from its previous version:
The following features added in version 2012 from its previous version:
1. Column store indexes - reduces I/O and memory utilization on large queries.
2. Pagination - pagination can be done by using “OFFSET” and “FETCH’ commands.
3. Contained database – Great feature for periodic data migrations.
4. AlwaysOn Availability Groups
5. Windows Server Core Support
6. User-Defined Server Roles
7. Big Data Support
8. PowerView
9. SQL Azure Enhancements
10. Tabular Model (SSAS)
11. DQS Data quality services
12. File Table - an enhancement to the FILESTREAM feature which was introduced in 2008.
13. Enhancement in Error Handling including THROW statement
https://riptutorial.com/ 260
14. Improvement to SQL Server Management Studio Debugging a. SQL Server 2012 introduces
more options to control breakpoints. b. Improvements to debug-mode windows
c. Enhancement in IntelliSense - like Inserting Code Snippets.
The following features added in version 2014 from its previous version:
The following features added in version 2016 from its previous version:
2. DROP IF EXISTS
4. ALTER TABLE can now alter many columns while the table remains online, using WITH
(ONLINE = ON | OFF).
9. FORMATMESSAGE Statement
https://riptutorial.com/ 261
www.dbooks.org
10. 2016 introduces 8 more properties with SERVERPROPERTY
a. InstanceDefaultDataPath
b. InstanceDefaultLogPath
c. ProductBuild
d. ProductBuildType
e. ProductMajorVersion
f. ProductMinorVersion
g. ProductUpdateLevel
h. ProductUpdateReference
Read SQL Server Evolution through different versions (2000 - 2016) online:
https://riptutorial.com/sql-server/topic/10129/sql-server-evolution-through-different-versions--2000-
--2016-
https://riptutorial.com/ 262
Chapter 91: SQL Server Management Studio
(SSMS)
Introduction
SQL Server Management Studio (SSMS) is a tool to manage and administer SQL Server and SQL
Database.
Examples
Refreshing the IntelliSense cache
When objects are created or modified they are not automatically available for IntelliSense. To
make them available to IntelliSense the local cache has to be refreshed.
Within an query editor window either press Ctrl + Shift + R or select Edit | IntelliSense |
Refresh Local Cache from the menu.
After this all changes since the last refresh will be available to IntelliSense.
https://riptutorial.com/ 263
www.dbooks.org
Chapter 92: SQLCMD
Remarks
You either need to be in the path where SQLCMD.exe exists or add it to your PATH environment
variable.
Examples
SQLCMD.exe called from a batch file or command line
echo off
cls
sqlcmd.exe -S "your server name" -U "sql user name" -P "sql password" -d "name of databse" -Q
"here you may write your query/stored procedure"
Batch files like these can be used to automate tasks, for example to make backups of databases
at a specified time (can be scheduled with Task Scheduler) for a SQL Server Express version
where Agent Jobs can't be used.
https://riptutorial.com/ 264
Chapter 93: Stored Procedures
Introduction
In SQL Server, a procedure is a stored program that you can pass parameters into. It does not
return a value like a function does. However, it can return a success/failure status to the procedure
that called it.
Syntax
• CREATE { PROCEDURE | PROC } [schema_name.]procedure_name
• [ @parameter [type_schema_name.] datatype
• [ VARYING ] [ = default ] [ OUT | OUTPUT | READONLY ]
• , @parameter [type_schema_name.] datatype
• [ VARYING ] [ = default ] [ OUT | OUTPUT | READONLY ] ]
• [ WITH { ENCRYPTION | RECOMPILE | EXECUTE AS Clause } ]
• [ FOR REPLICATION ]
• AS
• BEGIN
• [declaration_section]
• executable_section
• END;
Examples
Creating and executing a basic stored procedure
You can execute a procedure with a few different syntaxes. First, you can use EXECUTE or EXEC
https://riptutorial.com/ 265
www.dbooks.org
Additionally, you can omit the EXEC command. Also, you don't have to specify what parameter
you are passing in, as you pass in all parameters.
When you want to specify the input parameters in a different order than how they are declared in
the procedure you can specify the parameter name and assign values. For example
SELECT
Param1 = @Param1,
Param2 = @Param2
END
the normal order to execute this procedure is to specify the value for @Param1 first and then
@Param2 second. So it will look something like this
But it's also possible that you can use the following
in this, you are specifying the value for @param2 first and @Param1 second. Which means you
do not have to keep the same order as it is declared in the procedure but you can have any order
as you wish. but you will need to specify to which parameter you are setting the value
And also you can create a procedure with a prefix sp_ these procuedres, like all system stored
procedures, can be executed without specifying the database because of the default behavior of
SQL Server. When you execute a stored procedure that starts with "sp_", SQL Server looks for the
procedure in the master database first. If the procedure is not found in master, it looks in the active
database. If you have a stored procedure that you want to access from all your databases, create
it in master and use a name that includes the "sp_" prefix.
Use Master
https://riptutorial.com/ 266
AS
BEGIN
SELECT Name + ' is from ' + Country
FROM Authors
WHERE Id = @input_id OR Name = @name
END
GO
Stored procedures can return values using the OUTPUT keyword in its parameter list.
https://riptutorial.com/ 267
www.dbooks.org
RETURN
END
GO
Creates stored procedure that checks whether the values passed in stored procedure are not null
or non empty and perform insert operation in Employee table.
https://riptutorial.com/ 268
@Gender,
@DeptId
)
END
ELSE
PRINT 'Incorrect Parameters'
END
GO
EXECUTE spSetEmployeeDetails
@ID = 1,
@Name = 'Subin Nepal',
@Gender = 'Male',
@DeptId = 182666
Dynamic SQL enables us to generate and run SQL statements at run time. Dynamic SQL is
needed when our SQL statements contains identifier that may change at different compile times.
In the above sql query, we can see that we can use above query by defining values in @table_name,
@col_name, and @col_value at run time. The query is generated at runtime and executed. This is
technique in which we can create whole scripts as string in a variable and execute it. We can
create more complex queries using dynamic SQL and concatenation concept. This concept is very
powerful when you want to create a script that can be used under several conditions.
https://riptutorial.com/ 269
www.dbooks.org
@col_name,
@col_value
Output
Simple Looping
First lets get some data into a temp table named #systables and ad a incrementing row number so
we can query one record at a time
select
o.name,
row_number() over (order by o.name) as rn
into
#systables
from
sys.objects as o
where
o.type = 'S'
Next we declare some variables to control the looping and store the table name in this example
declare
@rn int = 1,
@maxRn int = (
select
max(rn)
from
#systables as s
)
declare @tablename sys name
Now we can loop using a simple while. We increment @rn in the select statement but this could
https://riptutorial.com/ 270
also have been a separate statement for ex set @rn = @rn + 1 it will depend on your requirements.
We also use the value of @rn before it's incremented to select a single record from #systables.
Lastly we print the table name.
select
@tablename = name,
@rn = @rn + 1
from
#systables as s
where
s.rn = @rn
print @tablename
end
Simple Looping
RETURN;
END
GO
https://riptutorial.com/ 271
www.dbooks.org
Chapter 94: Storing JSON in SQL tables
Examples
JSON stored as text column
Use nvarchar(max) as you are not sure what would be the size of your JSON documents.
nvarchar(4000) and varchar(8000) have better performance but with size limit to 8KB.
Since JSON is stored textual column, you might want to ensure that it is properly formatted. You
can add CHECK constraint on JSON column that checks is text properly formatted JSON:
If you already have a table, you can add check constraint using the ALTER TABLE statement:
If you add PERSISTED computed column, value from JSON text will be materialized in this
column. This way your queries can faster read value from JSON text because no parsing is
https://riptutorial.com/ 272
needed. Each time JSON in this row changes, value will be re-calculated.
Queries that filter or sort data by some value in JSON column usually use full table scan.
To optimize these kind of queries, you can add non-persisted computed column that exposes
JSON expression used in filter or sort (in this example JSON_VALUE(Data, '$.Color')), and create
index on this column:
If you can use memory-optimized tables, you can store JSON as text:
https://riptutorial.com/ 273
www.dbooks.org
Chapter 95: String Aggregate functions in
SQL Server
Examples
Using STUFF for string aggregation
We have a Student table with SubjectId. Here the requirement is to concatenate based on
subjectId.
select subjectid, stuff(( select concat( ',', studentname) from #yourstudent y where
y.subjectid = u.subjectid for xml path('')),1,1, '')
from #yourstudent u
group by subjectid
In case of SQL Server 2017 or vnext we can use in-built STRING_AGG for this aggregation. For
same student table,
https://riptutorial.com/ 274
Chapter 96: String Functions
Remarks
List of string functions (Alphabetically sorted):
• Ascii
• Char
• Charindex
• Concat
• Difference
• Format
• Left
• Len
• Lower
• Ltrim
• Nchar
• Patindex
• Quotename
• Replace
• Replicate
• Reverse
• Right
• Rtrim
• Soundex
• Space
• Str
• String_escape
https://riptutorial.com/ 275
www.dbooks.org
• String_split
• Stuff
• Substring
• Unicode
• Upper
Examples
Left
Returns a sub string starting with the left most char of a string and up to the maximum length
specified.
Parameters:
1. character expression. The character expression can be of any data type that can be implicitly
converted to varchar or nvarchar, except for text or ntext
2. max length. An integer number between 0 and bigint max value
(9,223,372,036,854,775,807).
If the max length parameter is negative, an error will be raised.
If the max length is more then the number of characters in the string, the entier string is returned.
Right
Returns a sub string that is the right most part of the string, with the specified max length.
Parameters:
1. character expression. The character expression can be of any data type that can be implicitly
converted to varchar or nvarchar, except for text or ntext
2. max length. An integer number between 0 and bigint max value
(9,223,372,036,854,775,807). If the max length parameter is negative, an error will be
raised.
If the max length is more then the number of characters in the string, the entier string is returned.
https://riptutorial.com/ 276
Substring
Returns a substring that starts with the char that's in the specified start index and the specified
max length.
Parameters:
1. Character expression. The character expression can be of any data type that can be
implicitly converted to varchar or nvarchar, except for text or ntext.
2. Start index. A number (int or bigint) that specifies the start index of the requested substring.
(Note: strings in sql server are base 1 index, meaning that the first character of the string is
index 1). This number can be less then 1. In this case, If the sum of start index and max
length is greater then 0, the return string would be a string starting from the first char of the
character expression and with the length of (start index + max length - 1). If it's less then 0,
an empty string would be returned.
3. Max length. An integer number between 0 and bigint max value
(9,223,372,036,854,775,807). If the max length parameter is negative, an error will be
raised.
If the max length + start index is more then the number of characters in the string, the entier string
is returned.
If the start index is bigger then the number of characters in the string, an empty string is returned.
ASCII
Returns an int value representing the ASCII code of the leftmost character of a string.
If the string is Unicode and the leftmost character is not ASCII but representable in the current
collation, a value greater than 127 can be returned:
If the string is Unicode and the leftmost character cannot be represented in the current collation,
the int value of 63 is returned: (which represents question mark in ASCII):
https://riptutorial.com/ 277
www.dbooks.org
SELECT ASCII(N' ') -- returns 63
SELECT ASCII(nchar(2039)) -- returns 63
CharIndex
Returns the start index of a the first occurrence of string expression inside another string
expression.
Parameters list:
If the string to search is varchar(max), nvarchar(max) or varbinary(max), the CHARINDEX function will
return a bigint value. Otherwise, it will return an int.
Char
This can be used to introduce new line/line feed CHAR(10), carriage returns CHAR(13), etc. See
AsciiTable.com for reference.
If the argument value is not between 0 and 255, the CHAR function returns NULL.
The return data type of the CHAR function is char(1)
Len
If the length including trailing spaces is desired there are several techniques to achieve this,
although each has its drawbacks. One technique is to append a single character to the string, and
then use the LEN minus one:
https://riptutorial.com/ 278
DECLARE @str varchar(100) = 'My string '
SELECT LEN(@str + 'x') - 1 -- returns 12
The drawback to this is if the type of the string variable or column is of the maximum length, the
append of the extra character is discarded, and the resulting length will still not count trailing
spaces. To address that, the following modified version solves the problem, and gives the correct
results in all cases at the expense of a small amount of additional execution time, and because of
this (correct results, including with surrogate pairs, and reasonable execution speed) appears to
be the best technique to use:
It's important to note though that DATALENGTH returns the length in bytes of the string in memory.
This will be different for varchar vs. nvarchar.
You can adjust for this by dividing the datalength of the string by the datalength of a single
character (which must be of the same type). The example below does this, and also handles the
case where the target string happens to be empty, thus avoiding a divide by zero.
Even this, though, has a problem in SQL Server 2012 and above. It will produce incorrect results
when the string contains surrogate pairs (some characters can occupy more bytes than other
characters in the same string).
Another technique is to use REPLACE to convert spaces to a non-space character, and take the LEN
of the result. This gives correct results in all cases, but has very poor execution speed with long
strings.
Concat
Returns a string that is the result of two or more strings joined together. CONCAT accepts two or
more arguments.
SELECT CONCAT('This', ' is', ' my', ' string') -- returns 'This is my string'
Note: Unlike concatenating strings using the string concatenation operator (+), when passing a null
https://riptutorial.com/ 279
www.dbooks.org
value to the concat function it will implicitly convert it to an empty string:
SELECT CONCAT('This', NULL, ' is', ' my', ' string'), -- returns 'This is my string'
'This' + NULL + ' is' + ' my' + ' string' -- returns NULL.
SELECT CONCAT('This', ' is my ', 3, 'rd string') -- returns 'This is my 3rd string'
Non-string type variables will also be converted to string format, no need to manually covert or
cast it to string:
Older versions do not support CONCAT function and must use the string concatenation operator (+)
instead. Non-string types must be cast or converted to string types in order to concatenate them
this way.
SELECT 'This is the number ' + CAST(42 AS VARCHAR(5)) --returns 'This is the number 42'
Lower
Returns a character expression (varchar or nvarchar) after converting all uppercase characters to
lowercase.
Parameters:
1. Character expression. Any expression of character or binary data that can be implicitly
converted to varchar.
Upper
Returns a character expression (varchar or nvarchar) after converting all lowercase characters to
uppercase.
Parameters:
1. Character expression. Any expression of character or binary data that can be implicitly
converted to varchar.
https://riptutorial.com/ 280
DECLARE @String nchar(17) = N'This IS my STRING';
SELECT UPPER(@String) -- Returns 'THIS IS MY STRING'
LTrim
Returns a character expression (varchar or nvarchar) after removing all leading white spaces, i.e.,
white spaces from the left through to the first non-white space character.
Parameters:
1. character expression. Any expression of character or binary data that can be implicitly
converted to varcher, except text, ntext and image.
RTrim
Returns a character expression (varchar or nvarchar) after removing all trailing white spaces, i.e.,
spaces from the right end of the string up until the first non-white space character to the left.
Parameters:
1. character expression. Any expression of character or binary data that can be implicitly
converted to varcher, except text, ntext and image.
Unicode
Returns the integer value representing the Unicode value of the first character of the input
expression.
Parameters:
NChar
Returns the Unicode character(s) (nchar(1) or nvarchar(2)) corresponding to the integer argument
it receives, as defined by the Unicode standard.
Parameters:
https://riptutorial.com/ 281
www.dbooks.org
1. integer expression. Any integer expression that is a positive number between 0 and 65535,
or if the collation of the database supports supplementary character (CS) flag, the supported
range is between 0 to 1114111. If the integer expression does not fall inside this range, null
is returned.
Reverse
Parameters:
1. string expression. Any string or binary data that can be implicitly converted to varchar.
PatIndex
Returns the starting position of the first occurrence of a the specified pattern in the specified
expression.
Parameters:
Space
Parameters:
https://riptutorial.com/ 282
empty string is returned. (To return a string longer then 8000 spaces, use Replicate.
Replicate
Parameters:
Note: If string expression is not of type varchar(max) or nvarchar(max), the return value will not
exceed 8000 chars. Replicate will stop before adding the string that will cause the return value to
exceed that limit:
Replace
Returns a string (varchar or nvarchar) where all occurrences of a specified sub string is replaced
with another sub string.
Parameters:
1. string expression. This is the string that would be searched. It can be a character or binary
data type.
2. pattern. This is the sub string that would be replaced. It can be a character or binary data
type. The pattern argument cannot be an empty string.
3. replacement. This is the sub string that would replace the pattern sub string. It can be a
character or binary data.
Notes:
https://riptutorial.com/ 283
www.dbooks.org
• If string expression is not of type varchar(max) or nvarchar(max), the replace function truncates
the return value at 8,000 chars.
• Return data type depends on input data types - returns nvarchar if one of the input values is
nvarchar, or varchar otherwise.
• Return NULL if any of the input parameters is NULL
String_Split
Splits a string expression using a character separator. Note that STRING_SPLIT() is a table-valued
function and therefore must be used within FROM clause.
Parameters:
Returns a single column table where each row contains a fragment of the string. The name of the
columns is value, and the datatype is nvarchar if any of the parameters is either nchar or nvarchar,
otherwise varchar.
SELECT value FROM STRING_SPLIT('Lorem ipsum dolor sit amet.', ' ');
Result:
value
-----
Lorem
ipsum
dolor
sit
amet.
Remarks:
The STRING_SPLIT function is available only under compatibility level 130. If your
database compatibility level is lower than 130, SQL Server will not be able to find and
execute STRING_SPLIT function. You can change the compatibility level of a database
using the following command:
Older versions of sql server does not have a built in split string function. There are many user
defined functions that handles the problem of splitting a string. You can read Aaron Bertrand's
https://riptutorial.com/ 284
article Split strings the right way – or the next best way for a comprehensive comparison of some
of them.
Str
Parameters:
Quotename
Returns a Unicode string surrounded by delimiters to make it a valid SQL Server delimited
identifier.
Parameters:
1. character string. A string of Unicode data, up to 128 characters (sysname). If an input string is
longer than 128 characters function returns null.
2. quote character. Optional. A single character to use as a delimiter. Can be a single
quotation mark (' or ``), a left or right bracket ({,[,(,< or >,),],}) or a double quotation mark ("
). Any other value will return null. Default value is square brackets.
https://riptutorial.com/ 285
www.dbooks.org
SELECT QUOTENAME('what''s my name?', '<') -- Returns <what's my name?>
SELECT QUOTENAME('what''s my name?', '>') -- Returns <what's my name?>
Soundex
Returns a four-character code (varchar) to evaluate the phonetic similarity of two strings.
Parameters:
The soundex function creates a four-character code that is based on how the character expression
would sound when spoken. the first char is the the upper case version of the first character of the
parameter, the rest 3 characters are numbers representing the letters in the expression (except a,
e, i, o, u, h, w and y that are ignored).
Difference
Returns an integer (int) value that indicates the difference between the soundex values of two
character expressions.
Parameters:
1. character expression 1.
2. character expression 2.
The integer returned is the number of chars in the soundex values of the parameters that are the
same, so 4 means that the expressions are very similar and 0 means that they are very different.
Format
https://riptutorial.com/ 286
Returns a NVARCHAR value formatted with the specified format and culture (if specified). This is
primarily used for converting date-time types to strings.
Parameters:
1. value. An expression of a supported data type to format. valid types are listed below.
2. format. An NVARCHAR format pattern. See Microsoft official documentation for standard and
custom format strings.
3. culture. Optional. nvarchar argument specifying a culture. The default value is the culture of
the current session.
DATE
SELECT
FORMAT ( @d, 'd', 'en-US' ) AS 'US English Result' -- Returns '7/31/2016'
,FORMAT ( @d, 'd', 'en-gb' ) AS 'Great Britain English Result' -- Returns '31/07/2016'
,FORMAT ( @d, 'd', 'de-de' ) AS 'German Result' -- Returns '31.07.2016'
,FORMAT ( @d, 'd', 'zh-cn' ) AS 'Simplified Chinese (PRC) Result' -- Returns '2016/7/31'
,FORMAT ( @d, 'D', 'en-US' ) AS 'US English Result' -- Returns 'Sunday, July 31, 2016'
,FORMAT ( @d, 'D', 'en-gb' ) AS 'Great Britain English Result' -- Returns '31 July 2016'
,FORMAT ( @d, 'D', 'de-de' ) AS 'German Result' -- Returns 'Sonntag, 31. Juli 2016'
CURRENCY
https://riptutorial.com/ 287
www.dbooks.org
PERCENTAGE
NUMBER
Important Notes:
• FORMATreturns NULL for errors other than a culture that is not valid. For example, NULL is
returned if the value specified in format is not valid.
• FORMAT relies on the presence of the .NET Framework Common Language Runtime (CLR).
• FORMAT relies upon CLR formatting rules which dictate that colons and periods must be
escaped. Therefore, when the format string (second parameter) contains a colon or period,
the colon or period must be escaped with backslash when an input value (first parameter) is
of the time data type.
See also Date & Time Formatting using FORMAT documentation example.
String_escape
https://riptutorial.com/ 288
Escapes special characters in texts and returns text (nvarchar(max)) with escaped characters.
Parameters:
2. type. Escaping rules that will be applied. Currently the only supported value is 'json'.
SELECT STRING_ESCAPE('\ /
\\ " ', 'json') -- returns '\\\t\/\n\\\\\t\"\t'
https://riptutorial.com/ 289
www.dbooks.org
Chapter 97: Subqueries
Examples
Subqueries
A subquery is a query within another SQL query. A subquery is also called inner query or inner
select and the statement containing a subquery is called an outer query or outer select.
Note
Subqueries can be used with select, insert, update and delete statement within where, from, select
clause along with IN, comparison operators, etc.
We have a table named ITCompanyInNepal on which we will perform queries to show subqueries
examples:
SELECT *
FROM ITCompanyInNepal
WHERE Headquarter IN (SELECT Headquarter
FROM ITCompanyInNepal
WHERE Headquarter = 'USA');
SELECT *
FROM ITCompanyInNepal
WHERE NumberOfEmployee < (SELECT AVG(NumberOfEmployee)
FROM ITCompanyInNepal
https://riptutorial.com/ 290
)
SELECT CompanyName,
CompanyAddress,
Headquarter,
(Select SUM(NumberOfEmployee)
FROM ITCompanyInNepal
Where Headquarter = 'USA') AS TotalEmployeeHiredByUSAInKathmandu
FROM ITCompanyInNepal
WHERE CompanyAddress = 'Kathmandu' AND Headquarter = 'USA'
We have to insert data from IndianCompany table to ITCompanyInNepal. The table for
IndianCompany is shown below:
Suppose all the companies whose headquarter is USA decided to fire 50 employees from all US
based companies of Nepal due to some change in policy of USA companies.
UPDATE ITCompanyInNepal
SET NumberOfEmployee = NumberOfEmployee - 50
WHERE Headquarter IN (SELECT Headquarter
FROM ITCompanyInNepal
WHERE Headquarter = 'USA')
Suppose all the companies whose headquarter is Denmark decided to shutdown their companies
from Nepal.
https://riptutorial.com/ 291
www.dbooks.org
Chapter 98: System database - TempDb
Examples
Identify TempDb usage
Following query will provide information about TempDb usage. Analyzing the counts you can
identify which thing is impacting TempDb
SELECT
SUM (user_object_reserved_page_count)*8 as usr_obj_kb,
SUM (internal_object_reserved_page_count)*8 as internal_obj_kb,
SUM (version_store_reserved_page_count)*8 as version_store_kb,
SUM (unallocated_extent_page_count)*8 as freespace_kb,
SUM (mixed_extent_page_count)*8 as mixedextent_kb
FROM sys.dm_db_file_space_usage
USE [MASTER]
SELECT * FROM sys.databases WHERE database_id = 2
OR
USE [MASTER]
SELECT * FROM sys.master_files WHERE database_id = 2
With the help of below DMV, you can check how much TempDb space does your session is using.
This query is quite helpful while debugging TempDb issues
https://riptutorial.com/ 292
Chapter 99: Table Valued Parameters
Remarks
Table valued parameters (TVP for short) are parameters passed to a stored procedure or function
that contains data that is table structured. Using table valued parameters requires creating a user
defined table type for the parameter being used.
Examples
Using a table valued parameter to insert multiple rows to a table
https://riptutorial.com/ 293
www.dbooks.org
Chapter 100: Temporal Tables
Remarks
SQL Server 2016 introduces support for system-versioned temporal tables as a database feature
that brings built-in support for providing information about data stored in the table at any point in
time rather than only the data that is correct at the current moment in time.
A system-versioned temporal table is a new type of user table in SQL Server 2016, designed to
keep a full history of data changes and allow easy point in time analysis. This type of temporal
table is referred to as a system-versioned temporal table because the period of validity for each
row is managed by the system (i.e. database engine). Every temporal table has two explicitly
defined columns, each with a datetime2 data type. These columns are referred to as period
columns. These period columns are used exclusively by the system to record period of validity for
each row whenever a row is modified.
Examples
CREATE Temporal Tables
INSERTS: On an INSERT, the system sets the value for the ValidFrom column to the begin time
of the current transaction (in the UTC time zone) based on the system clock and assigns the value
for the ValidTo column to the maximum value of 9999-12-31. This marks the row as open.
UPDATES: On an UPDATE, the system stores the previous value of the row in the history table
and sets the value for the ValidTo column to the begin time of the current transaction (in the UTC
time zone) based on the system clock. This marks the row as closed, with a period recorded for
which the row was valid. In the current table, the row is updated with its new value and the system
sets the value for the ValidFrom column to the begin time for the transaction (in the UTC time
zone) based on the system clock. The value for the updated row in the current table for the
ValidTo column remains the maximum value of 9999-12-31.
DELETES: On a DELETE, the system stores the previous value of the row in the history table and
sets the value for the ValidTo column to the begin time of the current transaction (in the UTC time
https://riptutorial.com/ 294
zone) based on the system clock. This marks the row as closed, with a period recorded for which
the previous row was valid. In the current table, the row is removed. Queries of the current table
will not return this row. Only queries that deal with history data return data for which a row is
closed.
MERGE: On a MERGE, the operation behaves exactly as if up to three statements (an INSERT,
an UPDATE, and/or a DELETE) executed, depending on what is specified as actions in the
MERGE statement.
Tip : The times recorded in the system datetime2 columns are based on the begin time of the
transaction itself. For example, all rows inserted within a single transaction will have the same
UTC time recorded in the column corresponding to the start of the SYSTEM_TIME period.
Returns a table with a rows containing the values that were actual (current) at the specified point
in time in the past.
Returns a table with the values for all row versions that were active within the specified time range,
regardless of whether they started being active before the <start_date_time> parameter value for
the FROM argument or ceased being active after the <end_date_time> parameter value for the
TO argument. Internally, a union is performed between the temporal table and its history table and
the results are filtered to return the values for all row versions that were active at any time during
the time range specified. Rows that became active exactly on the lower boundary defined by the
FROM endpoint are included and records that became active exactly on the upper boundary
defined by the TO endpoint are not included.
https://riptutorial.com/ 295
www.dbooks.org
SELECT * FROM Employee
FOR SYSTEM_TIME FROM '2015-01-01' TO '2015-12-31'
Returns a table with the values for all row versions that were opened and closed within the
specified time range defined by the two datetime values for the CONTAINED IN argument. Rows
that became active exactly on the lower boundary or ceased being active exactly on the upper
boundary are included.
Returns the union of rows that belong to the current and the history table.
Creating a temporal table with a default history table is a convenient option when you want to
control naming and still rely on system to create history table with default configuration. In the
example below, a new system-versioned memory-optimized temporal table linked to a new disk-
based history table.
Cleaning up the SQL Server history table Over time the history table can grow significantly.
Since inserting, updating or deleting data from the history table are not allowed, the only way to
clean up the history table is first to disable system versioning:
https://riptutorial.com/ 296
ALTER TABLE dbo.Employee
Cleaning the history table in Azure SQL Databases is a little different, since Azure SQL databases
have built-in support for cleaning of the history table. First, temporal history retention cleanup need
to be enable on a database level:
SET TEMPORAL_HISTORY_RETENTION ON GO
This will delete all data in the history table older than 90 days. SQL Server 2016 on-premise
databases do not support TEMPORAL_HISTORY_RETENTION and
HISTORY_RETENTION_PERIOD and either of the above two queries are executed on the SQL
Server 2016 on-premise databases the following errors will occur.
https://riptutorial.com/ 297
www.dbooks.org
Read Temporal Tables online: https://riptutorial.com/sql-server/topic/5296/temporal-tables
https://riptutorial.com/ 298
Chapter 101: The STUFF Function
Parameters
Parameter Details
Examples
Basic Character Replacement with STUFF()
The STUFF() function inserts a string into another string by first deleting a specified number of
characters. The following example, deletes "Svr" and replaces it with "Server". This happens by
specifying the start_position and length of the replacement.
Executing this example will result in returning SQL Server Documentation instead of SQL Svr
Documentation.
One common use for the FOR XML function is to concatenate the values of multiple rows.
SELECT
STUFF( (SELECT ';' + Email
FROM Customers
where (Email is not null and Email <> '')
ORDER BY Email ASC
FOR XML PATH('')),
1, 1, '')
In the example above, FOR XML PATH('')) is being used to concatenate email addresses, using ; as
the delimiter character. Also, the purpose of STUFF is to remove the leading ; from the
concatenated string. STUFF is also implicitly casting the concatenated string from XML to varchar.
https://riptutorial.com/ 299
www.dbooks.org
Note: the result from the above example will be XML-encoded, meaning it will replace < characters
with < etc. If you don't want this, change FOR XML PATH('')) to FOR XML PATH,
TYPE).value('.[1]','varchar(MAX)'), e.g.:
SELECT
STUFF( (SELECT ';' + Email
FROM Customers
where (Email is not null and Email <> '')
ORDER BY Email ASC
FOR XML PATH, TYPE).value('.[1]','varchar(900)'),
1, 1, '')
This can be used to achieve a result similar to GROUP_CONCAT in MySQL or string_agg in PostgreSQL
9.0+, although we use subqueries instead of GROUP BY aggregates. (As an alternative, you can
install a user-defined aggregate such as this one if you're looking for functionality closer to that of
GROUP_CONCAT).
/*
The result can be use for fast way to use columns on Insertion/Updates.
Works with tables and views.
FOR XML PATH and STUFF to concatenate the multiple rows into a single row:
https://riptutorial.com/ 300
, 1, 1, '') AS date
from yourtable t1;
STUFF() function inserts Replacement_expression, at the start position specified, along with
removing the characters specified using Length parameter.
https://riptutorial.com/ 301
www.dbooks.org
Chapter 102: Transaction handling
Parameters
Parameter Details
for naming your transaction - useful with the parameter [with mark]
transaction_name
which will allow a meaningfull logging -- case-sensitive (!)
with mark
can be added to [transaction_name] and will store a mark in the log
['description']
Examples
basic transaction skeleton with error handling
https://riptutorial.com/ 302
Chapter 103: Transaction isolation levels
Syntax
• SET TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED | READ COMMITTED |
REPEATABLE READ | SNAPSHOT | SERIALIZABLE } [ ; ]
Remarks
MSDN Reference: SET TRANSACTION ISOLATION LEVEL
Examples
Read Uncommitted
This is the most permissive isolation level, in that it does not cause any locks at all. It specifies that
statements can read all rows, including rows that have been written in transactions but not yet
committed (i.e., they are still in transaction). This isolation level can be subject to "dirty reads".
Read Committed
This isolation level is the 2nd most permissive. It prevents dirty reads. The behavior of READ
COMMITTED depends on the setting of the READ_COMMITTED_SNAPSHOT:
• If set to OFF (the default setting) the transaction uses shared locks to prevent other
transactions from modifying rows used by the current transaction, as well as block the
current transaction from reading rows modified by other transactions.
• If set to ON, the READCOMMITTEDLOCK table hint can be used to request shared locking instead of
row versioning for transactions running in READ COMMITTED mode.
Dirty reads (or uncommitted reads) are reads of rows which are being modified by an open
transaction.
https://riptutorial.com/ 303
www.dbooks.org
This behavior can be replicated by using 2 separate queries: one to open a transaction and write
some data to a table without committing, the other to select the data to be written (but not yet
committed) with this isolation level.
Returns:
col1 col2
----------- ---------------------------------------
99 Normal transaction
42 Dirty read
COMMIT TRANSACTION;
DROP TABLE dbo.demo;
GO
Repeatable Read
This transaction isolation level is slightly less permissive than READ COMMITTED, in that shared locks
are placed on all data read by each statement in the transaction and are held until the
transaction completes, as opposed to being released after each statement.
Note: Use this option only when necessary, as it is more likely to cause database performance
degradation as well as deadlocks than READ COMMITTED.
https://riptutorial.com/ 304
Snapshot
Specifies that data read by any statement in a transaction will be the transactionally consistent
version of the data that existed at the start of the transaction, i.e., it will only read data that has
been committed prior to the transaction starting.
SNAPSHOT transactions do not request or cause any locks on the data that is being read, as it is only
reading the version (or snapshot) of the data that existed at the time the transaction began.
A transaction running in SNAPSHOT isolation level read only its own data changes while it is running.
For example, a transaction could update some rows and then read the updated rows, but that
change will only be visible to the current transaction until it is committed.
Note: The ALLOW_SNAPSHOT_ISOLATION database option must be set to ON before the SNAPSHOT
isolation level can be used.
Serializable
This isolation level is the most restrictive. It requests range locks the range of key values that are
read by each statement in the transaction. This also means that INSERT statements from other
transactions will be blocked if the rows to be inserted are in the range locked by the current
transaction.
This option has the same effect as setting HOLDLOCK on all tables in all SELECT statements in a
transaction.
Note: This transaction isolation has the lowest concurrency and should only be used when
necessary.
https://riptutorial.com/ 305
www.dbooks.org
Chapter 104: Trigger
Introduction
A trigger is a special type of stored procedure, which is executed automatically after an event
occurs. There are two types of triggers: Data Definition Language Triggers and Data Manipulation
Language Triggers.
It is usually bound to a table and fires automatically. You cannot explicitly call any trigger.
Examples
Types and classifications of Trigger
In SQL Server, there are two categories of triggers: DDL Triggers and DML Triggers.
DDL Triggers are fired in response to Data Definition Language (DDL) events. These events
primarily correspond to Transact-SQL statements that start with the keywords CREATE, ALTER and
DROP.
DML Triggers are fired in response to Data Manipulation Language (DML) events. These events
corresponds to Transact-SQL statements that start with the keywords INSERT, UPDATE and DELETE.
2. Instead of triggers
DML Triggers
DML Triggers are fired as a response to dml statements (insert, update or delete).
A dml trigger can be created to address one or more dml events for a single table or view. This
means that a single dml trigger can handle inserting, updating and deleting records from a specific
table or view, but in can only handle data being changed on that single table or view.
DML Triggers provides access to inserted and deleted tables that holds information about the data
that was / will be affected by the insert, update or delete statement that fired the trigger.
https://riptutorial.com/ 306
Note that DML triggers are statement based, not row based. This means that if the statement
effected more then one row, the inserted or deleted tables will contain more then one row.
Examples:
GO
GO
GO
All the examples above will add records to tblAudit whenever a record is added, deleted or
updated in tblSomething.
https://riptutorial.com/ 307
www.dbooks.org
Chapter 105: TRY/CATCH
Remarks
TRY/CATCH is a language construct specific to MS SQL Server's T-SQL.
It allows error handling within T-SQL, similar to that seen in .NET code.
Examples
Transaction in a TRY/CATCH
BEGIN TRANSACTION
BEGIN TRY
INSERT INTO dbo.Sale(Price, SaleDate, Quantity)
VALUES (5.2, GETDATE(), 1)
INSERT INTO dbo.Sale(Price, SaleDate, Quantity)
VALUES (5.2, 'not a date', 1)
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION -- First Rollback and then throw.
THROW
END CATCH
BEGIN TRANSACTION
BEGIN TRY
INSERT INTO dbo.Sale(Price, SaleDate, Quantity)
VALUES (5.2, GETDATE(), 1)
INSERT INTO dbo.Sale(Price, SaleDate, Quantity)
VALUES (5.2, GETDATE(), 1)
COMMIT TRANSACTION
END TRY
BEGIN CATCH
THROW
ROLLBACK TRANSACTION
END CATCH
https://riptutorial.com/ 308
END TRY
BEGIN CATCH
print 'Error: ' + ERROR_MESSAGE();
END CATCH
RAISERROR with second parameter greater than 10 (11 in this example) will stop execution in
TRY BLOCK and raise an error that will be handled in CATCH block. You can access error
message using ERROR_MESSAGE() function. Output of this sample is:
First statement
Error: Here is a problem!
RAISERROR with severity (second parameter) less or equal to 10 will not throw exception.
BEGIN TRY
print 'First statement';
RAISERROR( 'Here is a problem!', 10, 15);
print 'Second statement';
END TRY
BEGIN CATCH
print 'Error: ' + ERROR_MESSAGE();
END CATCH
After RAISERROR statement, third statement will be executed and CATCH block will not be
invoked. Result of execution is:
First statement
Here is a problem!
Second statement
You can re-throw error that you catch in CATCH block using TRHOW statement:
Note that in this case we are raising error with formatted arguments (fourth and fifth parameter).
This might be useful if you want to add more info in message. Result of execution is:
First statement
https://riptutorial.com/ 309
www.dbooks.org
Error: Here is a problem! Area: 'TRY BLOCK' Line:'2'
Msg 50000, Level 11, State 1, Line 26
Here is a problem! Area: 'TRY BLOCK' Line:'2'
Exception with be handled in CATCH block and then re-thrown using THROW without parameters.
First statement
Error: Here is a problem!
Msg 51000, Level 16, State 15, Line 39
Here is a problem!
https://riptutorial.com/ 310
Chapter 106: UNION
Examples
Union and union all
Union operation combines the results of two or more queries into a single result set that includes
all the rows that belong to all queries in the union and will ignore any duplicates that exist. Union
all also does the same thing but include even the duplicate values. The concept of union operation
will be clear from the example below. Few things to consider while using union are:
1.The number and the order of the columns must be the same in all queries.
Example:
We have three tables : Marksheet1, Marksheet2 and Marksheet3. Marksheet3 is the duplicate
table of Marksheet2 which contains same values as that of Marksheet2.
Table1: Marksheet1
Table2: Marksheet2
Table3: Marksheet3
https://riptutorial.com/ 311
www.dbooks.org
Union on tables Marksheet1 and Marksheet2
Note: The output for union of the three tables will also be same as union on Marksheet1 and
Marksheet2 because union operation does not take duplicate values.
OUTPUT
Union All
OUTPUT
https://riptutorial.com/ 312
You will notice here that the duplicate values from Marksheet3 are also displayed using union all.
https://riptutorial.com/ 313
www.dbooks.org
Chapter 107: Use of TEMP Table
Remarks
Temporary Tables are really very helpful.
The table can be created at runtime and can do all operations which are done in a normal table.
Used when ?
Examples
Local Temp Table
• Will be available till the current connection persists for the user.
After executing all these statements if we close the query window and open it again and try
inserting and select it will show an error message
https://riptutorial.com/ 314
Will be deleted only if user disconnects all connections.
Note: These are viewable by all users of the database, irrespective of permissions level.
Temp tables must have unique IDs (within the session, for local temp tables, or within the server,
for global temp tables). Trying to create a table using a name that already exists will return the
following error:
If your query produces temp tables, and you want to run it more than once, you will need to drop
the tables before trying to generate them again. The basic syntax for this is:
Trying to execute this syntax before the table exists (e.g. on the first run of your syntax) will cause
another error:
Cannot drop the table '#tempTable', because it does not exist or you do not have permission.
To avoid this, you can check to see if the table already exists before dropping it, like so:
https://riptutorial.com/ 315
www.dbooks.org
Chapter 108: User Defined Table Types
Introduction
User defined table types (UDT for short) are data types that allows the user to define a table
structure. User defined table types supports primary keys, unique constraints and default values.
Remarks
UDTs have following restrictions -
Examples
creating a UDT with a single int column that is also a primary key
Creating a UDT with a primary key and a column with a default value:
https://riptutorial.com/ 316
CREATE TYPE MyUniqueNamesType as TABLE
(
FirstName varchar(10),
LastName varchar(10),
CreateDate datetime default GETDATE()
PRIMARY KEY (FirstName,LastName)
)
https://riptutorial.com/ 317
www.dbooks.org
Chapter 109: Variables
Syntax
• DECLARE @VariableName DataType [ = Value ] ;
• SET @VariableName = Value ;
Examples
Declare a Table Variable
When you create a normal table, you use CREATE TABLE Name (Columns) syntax. When creating a
table variable, you use DECLARE @Name TABLE (Columns) syntax.
To reference the table variable inside a SELECT statement, SQL Server requires that you give the
table variable an alias, otherwise you'll get an error:
i.e.
/*
-- the following two commented out statements would generate an error:
SELECT *
FROM @Table1
INNER JOIN @Table2 ON @Table1.Example = @Table2.Example
SELECT *
FROM @Table1
WHERE @Table1.Example = 1
*/
SELECT *
FROM @Table1 Table1
WHERE Table1.Example = 1
https://riptutorial.com/ 318
Updating a variable using SET
Hello
When using SELECT to update a variable from a table column, if there are multiple values, it will use
the last value. (Normal order rules apply - if no sort is given, the order is not guaranteed.)
PRINT @Variable
PRINT @Variable
If there are no rows returned by the query, the variable's value won't change:
https://riptutorial.com/ 319
www.dbooks.org
PRINT @Variable
DECLARE
@Var1 INT = 5,
@Var2 NVARCHAR(50) = N'Hello World',
@Var3 DATETIME = GETDATE()
Example usage:
Depending on the structure of your data, you can create variables that update dynamically.
https://riptutorial.com/ 320
DECLARE @CurrentID int = (SELECT TOP 1 ID FROM Table ORDER BY CreateDate desc)
In most cases, you will want to ensure that your query returns only one value when using this
method.
https://riptutorial.com/ 321
www.dbooks.org
Chapter 110: Views
Remarks
Views are stored queries that can be queried like regular tables. Views are not part of the physical
model of the database. Any changes that are applied to the data source of a view, such as a table,
will be reflected in the view as well.
Examples
Create a view
This query will drop the view - if it already exists - and create a new one.
If a view is created WITH SCHEMABINDING, the underlying table(s) can't be dropped or modified
in such a way that they would break the view. For example, a table column referenced in a view
can't be removed.
https://riptutorial.com/ 322
Views without schema binding can break if their underlying table(s) change or get dropped.
Querying a broken view results in an error message. sp_refreshview can be used to ensure
existing views without schema binding aren't broken.
https://riptutorial.com/ 323
www.dbooks.org
Chapter 111: WHILE loop
Remarks
Using a WHILE loop or other iterative process is not normally the most efficient way to process data
in SQL Server.
You should prefer to use a set-based query on the data to achieve the same results, where
possible
Examples
Using While loop
The WHILE loop can be used as an alternative to CURSORS. The following example will print numbers
from 0 to 99.
DECLARE @i int = 0;
WHILE(@i < 100)
BEGIN
PRINT @i;
SET @i = @i+1
END
https://riptutorial.com/ 324
Chapter 112: Window functions
Examples
Centered Moving Average
SELECT TradeDate, AVG(Px) OVER (ORDER BY TradeDate ROWS BETWEEN 63 PRECEDING AND 63 FOLLOWING)
AS PxMovingAverage
FROM HistoricalPrices
Note that, because it will take up to 63 rows before and after each returned row, at the beginning
and end of the TradeDate range it will not be centered: When it reaches the largest TradeDate it
will only be able to find 63 preceding values to include in the average.
In tables recording events there is often a datetime field recording the time an event happened.
Finding the single most recent event can be difficult because it's always possible that two events
were recorded with exactly identical timestamps. You can use row_number() over (order by ...) to
make sure all records are uniquely ranked, and select the top one (where my_ranking=1)
select *
from (
select
*,
row_number() over (order by crdate desc) as my_ranking
from sys.sysobjects
) g
where my_ranking=1
This same technique can be used to return a single row from any dataset with potentially duplicate
values.
SELECT
value_column1,
( SELECT
AVG(value_column1) AS moving_average
FROM Table1 T2
WHERE ( SELECT
COUNT(*)
FROM Table1 T3
WHERE date_column1 BETWEEN T2.date_column1 AND T1.date_column1
) BETWEEN 1 AND 30
https://riptutorial.com/ 325
www.dbooks.org
) as MovingAvg
FROM Table1 T1
https://riptutorial.com/ 326
Chapter 113: With Ties Option
Examples
Test Data
Below is the output of above table,As you can see Id Column is repeated three times..
Id Name
1 A
1 B
1 C
2 D
Id Name
1 B
Output :
Id Name
https://riptutorial.com/ 327
www.dbooks.org
1 A
1 B
1 C
As you can see SQL Server outputs all the Rows which are tied with Order by Column. Lets see
one more Example to understand this better..
Output:
Id Name
1 A
In Summary ,when we use with Ties Option,SQL Server Outputs all the Tied rows irrespective of
limit we impose
https://riptutorial.com/ 328
Credits
S.
Chapters Contributors
No
Basic DDL
7 Operations in MS Matt
SQL Server
CLUSTERED
11 Jovan MSFT
COLUMNSTORE
https://riptutorial.com/ 329
www.dbooks.org
Common Language
13 Jovan MSFT
Runtime Integration
Common Table Arif, bbrown, cteski, DForck42, Jeffrey Van Laethem, Jovan
14
Expressions MSFT, kafka, Keith Hall, Monty Wild, SQLMason
Converting data
16 Ben O, Edathadan Chief aka Arun
types
Database
21 Ben Thul
permissions
Database
22 Akash, Daryl, Jovan MSFT, Wolfgang
Snapshots
25 DBMAIL Phrancis
Delimiting special
26 characters and bassrek
reserved words
Dynamic data
28 Jovan MSFT
masking
31 Encryption Rubenisme
https://riptutorial.com/ 330
by using SQLCMD
Generating a range
39 James, Siyual
of dates
In-Memory OLTP
43 Akshay Anand, Behzad, Brandon, Jovan MSFT, Martijn Pieters
(Hekaton)
44 Insert Randall
Installing SQL
46 Luis Bosquez
Server on Windows
Last Inserted
50 Jeffrey Van Laethem, sqluser, Tot Zam
Identity
https://riptutorial.com/ 331
www.dbooks.org
51 Limit Result Set alalp, chrisb, cteski, ErikE
Managing Azure
53 Jovan MSFT
SQL Database
Microsoft SQL
Server Management
55 Bino Mathew Varghese, cteski, Sibeesh Venu
Studio Shortcut
Keys
Natively compiled
59 bakedpatato, Jovan MSFT
modules (Hekaton)
65 Parsename Mani
Permissions and
67 5arx
Security
71 Privileges or Oluwafemi
https://riptutorial.com/ 332
Permissions
Querying results by
75 Pat
page
Scheduled Task or
81 Edathadan Chief aka Arun, Hadi
Job
82 Schemas Merenix
Sorting/ordering
87 APH, OzrenTkalcecKrznaric
rows
SQL Server
90 Evolution through Dan Guzman, M.Ali
different versions
https://riptutorial.com/ 333
www.dbooks.org
(2000 - 2016)
SQL Server
91 Management Studio dd4711
(SSMS)
Storing JSON in
94 Ed Harper, Jovan MSFT, RamenChef
SQL tables
String Aggregate
95 functions in SQL Kannan Kandasamy
Server
97 Subqueries cnayak
System database -
98 Anuj Tripathi, RamenChef
TempDb
Table Valued
99 Zohar Peled
Parameters
Transaction
102 Metanormal
handling
Transaction isolation
103 Phrancis
levels
https://riptutorial.com/ 334
Types
https://riptutorial.com/ 335
www.dbooks.org