select loginid from humanresources.employee; … ·  · 2011-10-06 ... • union or union all...

28
http://www.mssqltips.com/sql_server_developer_tips.asp http://www.mssqltips.com/sqlservertutorial/10/select-command-for-sql-server/ SELECT command for SQL Server Overview If you are starting to learn the T-SQL language then starting with the SELECT statement makes a great deal of sense. The SELECT statement is the core command to access data in SQL Server. The main components of a SELECT statement are: Column listing - either specific columns or * (SELECT list) o When * is specified, then all columns from the tables included in the FROM clause are included Table listing (FROM clause) Filter logic (WHERE clause) Summarize values (GROUP BY) Filters the GROUP BY values (HAVING) Sorting logic (ORDER BY) SELECT can be combine with other statements to do the following: JOINing data from multiple tables to build a single result set INSERT with a SELECT statement to add records into an existing table SELECT...INTO statement to create a new table based on the column list specification and enter records into the new table UNION or UNION ALL command to have multiple set of logic returned in a single result set Include an index hint to force a particular lock level or index usage for the query You can either use the outline on the left or click on the arrows to the right or below to scroll through each of these topics. SELECT basics Overview At the most basic level, a single column can be accessed from a SELECT statement. In this circumstance all of the values from the column will be returned from the table. Let's take a look at an example. Explanation In the example below we are selecting the LoginID column from the HumanResources.Employee table without any other logic to restrict the result set. USE AdventureWorks; GO SELECT LoginID FROM HumanResources.Employee; GO Below is the sample result set: Multiple column SELECT example Overview To expand on the previous tutorial, multiple columns can be accessed from a single SELECT statement. In this circumstance we will select a few different columns from a table and all of the associated rows will be returned. Let's take a look at a simple example. Explanation In the example below we are selecting the EmployeeID, LoginID and HireDatecolumn columns from the HumanResources.Employee table. Here is the sample code: USE AdventureWorks; GO SELECT EmployeeID, LoginID,

Upload: phunganh

Post on 28-May-2018

213 views

Category:

Documents


0 download

TRANSCRIPT

http://www.mssqltips.com/sql_server_developer_tips.asp

http://www.mssqltips.com/sqlservertutorial/10/select-command-for-sql-server/

SELECT command for SQL Server

Overview If you are starting to learn the T-SQL language then starting with the SELECT statement makes

a great deal of sense. The SELECT statement is the core command to access data in SQL

Server. The main components of a SELECT statement are:

• Column listing - either specific columns or * (SELECT list)

o When * is specified, then all columns from the tables included in the FROM

clause are included

• Table listing (FROM clause)

• Filter logic (WHERE clause)

• Summarize values (GROUP BY)

• Filters the GROUP BY values (HAVING)

• Sorting logic (ORDER BY)

SELECT can be combine with other statements to do the following:

• JOINing data from multiple tables to build a single result set

• INSERT with a SELECT statement to add records into an existing table

• SELECT...INTO statement to create a new table based on the column list specification

and enter records into the new table

• UNION or UNION ALL command to have multiple set of logic returned in a single

result set

• Include an index hint to force a particular lock level or index usage for the query

You can either use the outline on the left or click on the arrows to the right or below to scroll

through each of these topics.

SELECT basics

Overview At the most basic level, a single column can be accessed from a SELECT statement. In this

circumstance all of the values from the column will be returned from the table. Let's take a look

at an example.

Explanation

In the example below we are selecting the LoginID column from the

HumanResources.Employee table without any other logic to restrict the result set.

USE AdventureWorks;

GO

SELECT LoginID

FROM HumanResources.Employee;

GO

Below is the sample result set:

Multiple column SELECT example

Overview To expand on the previous tutorial, multiple columns can be accessed from a single SELECT

statement. In this circumstance we will select a few different columns from a table and all of the

associated rows will be returned. Let's take a look at a simple example.

Explanation In the example below we are selecting the EmployeeID, LoginID and HireDatecolumn columns

from the HumanResources.Employee table. Here is the sample code:

USE AdventureWorks;

GO

SELECT EmployeeID,

LoginID,

HireDate

FROM HumanResources.Employee;

GO

Below is the sample result set:

SELECT with WHERE

Overview In this example we will return a single column in our SELECT statement and add a WHERE

clause to limit the records being returned. In this circumstance all of the values from the column

will be returned from the table only when the WHERE criteria is met. Let's take a look at an

example.

Explanation In the example below we are selecting the LoginID column from the

HumanResources.Employee table where the VacationHours column equals 8.

USE AdventureWorks;

GO

SELECT LoginID

FROM HumanResources.Employee

WHERE VacationHours = 8;

GO

Below is the sample result set:

SELECT with ORDER BY

Overview In this tutorial we will issue a variety of SELECT statements with ORDER BY clauses to show

how data can be sorted in both ascending and descending. We are going to offer examples with

character, numeric and date based columns. We will also provide some examples on

combinations of these columns and ORDER BY logic. Let's take a look at an example.

Explanation In the examples below we are selecting a variety of columns from the

HumanResources.Employee table and ordering the data in a variety of ways to show the various

options available in SQL Server. In the first example, we are ordering the data by the HireDate

column in ascending order. In the second example, we are ordering the data by the LoginID

column in descending order. In the third example, we are first ordering the data by the LoginID

column in ascending order and then by the HireDate column in descending order.

Data in ascending order

USE AdventureWorks;

GO

SELECT LoginID, EmployeeID, HireDate

FROM HumanResources.Employee

ORDER BY HireDate ASC;

GO

Data in descending order

USE AdventureWorks;

GO

SELECT LoginID, EmployeeID, HireDate

FROM HumanResources.Employee

ORDER BY LoginID DESC;

GO

A column in ascending order and a separate column in descending order

USE AdventureWorks;

GO

SELECT LoginID, EmployeeID, HireDate

FROM HumanResources.Employee

ORDER BY LoginID ASC, HireDate DESC;

GO

SELECT with WHERE and ORDER BY

Overview Let's bring the WHERE and ORDER BY concepts together in this tutorial.

Explanation

In the example below we are selecting the LoginID column from the

HumanResources.Employee table where the VacationHours column equals 8 and we are

ordering the data by the HireDate in ascending order which is implied.

USE AdventureWorks;

GO

SELECT LoginID

FROM HumanResources.Employee

WHERE VacationHours = 8

ORDER BY HireDate;

GO

Below is the sample result set:

Aliasing columns in a SELECT statement example

Overview The purpose for aliasing a column is to have a friendly name for the column. This name might

differ from the physical design to business terms or remove issues such as spacing in the column

name. Let's take a look at an example.

Explanation Let's use the same query from an earlier tutorial with one minor modification for the column

alias. In the example below, we are selecting the LoginID column from the

HumanResources.Employee table where the VacationHours column equals 8 and we are

ordering the data by the HireDate in ascending order which is implied. What is different is that

we are aliasing the LoginID column as 'Domain\LoginName' to be a little bit more specific.

USE AdventureWorks;

GO

SELECT LoginID AS 'Domain\LoginName'

FROM HumanResources.Employee

WHERE VacationHours = 8

ORDER BY HireDate;

GO

Below is the sample result set, which shows the column name returned as 'Domain\LoginName'

(alias) rather than LoginID (physical design):

Aliasing tables in a SELECT statement example

Overview The purpose for aliasing a table is to have a short abbreviation for the table. Typically a long

table name can easily be aliased with one to three characters. By doing so the code is typically

much shorter and easier to read when troubleshooting. Taking this small step will hopefully lead

to a simpler next step with JOINs where table aliasing is key. Let's take a look at an example.

Explanation Let's use the same query from an earlier tutorial with a few minor modifications for table

aliasing. In the example below, we are selecting the LoginID column aliased as

'Domain\LoginName' from the HumanResources.Employee table where the VacationHours

column equals 8 and we are ordering the data by the HireDate in ascending order which is

implied. What is different is that we are aliasing the HumanResources.Employee table as 'E' to

simplify the code in preparation for the JOIN examples.

USE AdventureWorks;

GO

SELECT E.LoginID AS 'Domain\LoginName'

FROM HumanResources.Employee E

WHERE E.VacationHours = 8

ORDER BY E.HireDate;

GO

Below is the sample result set:

Join tables in a SELECT statement example

Overview The JOIN syntax in SQL Server is used to build a single result set from more than 1 table. At the

most basic level, two tables are joined based on a common set of columns between the tables.

Joins can be coded in a few different manners, but in this example we will use INNER JOIN

logic to return matching rows from both tables. The tables included in the JOIN logic are

specified in the FROM clause. An ON statement is used to indicate the matching columns. Let's

dig in.

Explanation Let's use the same query from an earlier tutorial with a few different modifications to the FROM

clause. In the example below, we are selecting the columns from five different tables to show

that data is returned from each table in the JOIN logic. In the example below we are joining

between these tables:

• HumanResources.Employee

• HumanResources.EmployeeAddress

• Person.Address

• Person.StateProvince

In each of these circumstances the unique identifiers between the tables are used in the ON

clause to join between the tables to return matching rows.

As you can see in the example below, aliasing is valuable because it makes the code compact and

saves on a great deal of typing for each column specified in the SELECT, FROM, JOIN,

WHERE and ORDER BY logic.

USE AdventureWorks;

GO

SELECT E.EmployeeID,

E.LoginID AS 'Domain\LoginName',

E.HireDate,

EA.AddressID,

A.AddressID,

A.AddressLine1,

A.AddressLine2,

A.City,

S.[Name] AS 'State',

A.PostalCode

FROM HumanResources.Employee E

INNER JOIN HumanResources.EmployeeAddress EA

ON E.EmployeeID = EA.EmployeeID

INNER JOIN Person.Address A

ON EA.AddressID = A.AddressID

INNER JOIN Person.StateProvince S

ON A.StateProvinceID = S.StateProvinceID

WHERE E.VacationHours = 8

ORDER BY E.HireDate;

GO

Below is the sample result set:

Additional Information :

SQL Server Join Examples

By: Jeremy Kadlec http://www.mssqltips.com/sqlservertip/1667/sql server join examples/

Problem I am new to SQL Server and want to learn about the JOIN options. What are all of the JOIN

options in SQL Server? What is the significance of each of the options? I am a little confused

on the differences and syntax, can you provide some examples and explanations? Are JOINs

only for SELECT statements?

Solution Joining tables to obtain the needed data for a query, script or stored stored procedure is a key

concept as you learn about SQL Server development. In a nutshell, joins are typically performed

in the FROM clause of a table or view for the SELECT, INSERT...SELECT, SELECT...INTO,

UPDATE and DELETE statements. In previous versions of SQL Server, join logic could also

have been included in the WHERE clause with = (INNER JOIN), *= (LEFT OUTER JOIN), =*

(RIGHT OUTER JOIN), etc. syntax, but the support has been reduced and the best practice in

SQL Server is to use the syntax outlined in the examples below.

Before we jump into code, let's provide some baseline information on the joins options in SQL

Server:

• INNER JOIN - Match rows between the two tables specified in the INNER JOIN statement based

on one or more columns having matching data. Preferably the join is based on referential

integrity enforcing the relationship between the tables to ensure data integrity.

o Just to add a little commentary to the basic definitions above, in general the INNER JOIN

option is considered to be the most common join needed in applications and/or

queries. Although that is the case in some environments, it is really dependent on the

database design, referential integrity and data needed for the application. As such,

please take the time to understand the data being requested then select the proper join

option.

o Although most join logic is based on matching values between the two columns

specified, it is possible to also include logic using greater than, less than, not equals, etc.

• LEFT OUTER JOIN - Based on the two tables specified in the join clause, all data is returned from

the left table. On the right table, the matching data is returned in addition to NULL values

where a record exists in the left table, but not in the right table.

o Another item to keep in mind is that the LEFT and RIGHT OUTER JOIN logic is opposite of

one another. So you can change either the order of the tables in the specific join

statement or change the JOIN from left to right or vice versa and get the same results.

• RIGHT OUTER JOIN - Based on the two tables specified in the join clause, all data is returned

from the right table. On the left table, the matching data is returned in addition to NULL values

where a record exists in the right table but not in the left table.

• Self -Join - In this circumstance, the same table is specified twice with two different aliases in

order to match the data within the same table.

• CROSS JOIN - Based on the two tables specified in the join clause, a Cartesian product is created

if a WHERE clause does filter the rows. The size of the Cartesian product is based on multiplying

the number of rows from the left table by the number of rows in the right table. Please heed

caution when using a CROSS JOIN.

• FULL JOIN - Based on the two tables specified in the join clause, all data is returned from both

tables regardless of matching data.

Let's walk through examples from the AdventureWorks sample database that is available for

SQL Server to provide examples of each type of join then provide some insight into the usage

and sample result sets.

INNER JOIN Example

In this example we are joining between the Sales.SalesOrderDetail and Production.Product

tables. The tables are aliased with the following: SOD for Sales.SalesOrderDetail and P for

Production.Product. The JOIN logic is based on matching records in the SOD.ProductID and

P.ProductID columns. The records are filtered by only returning records with the SOD.UnitPrice

greater than 1000. Finally, the result set is returned in order with the most expensive first based

on the ORDER BY clause and only the highest 100 products based on the TOP clause.

USE AdventureWorks;

GO

SELECT TOP 100 P.ProductID,

P.Name,

P.ListPrice,

P.Size,

P.ModifiedDate,

SOD.UnitPrice,

SOD.UnitPriceDiscount,

SOD.OrderQty,

SOD.LineTotal

FROM Sales.SalesOrderDetail SOD

INNER JOIN Production.Product P

ON SOD.ProductID = P.ProductID

WHERE SOD.UnitPrice > 1000

ORDER BY SOD.UnitPrice DESC

GO

LEFT OUTER JOIN Example

In this example we are combining two concepts to show that more than two tables can be

JOINed in one SELECT statement and more than one JOIN type can be used in a single

SELECT statement. In the sample code below, we are retrieving the matching data between the

Person.Contact and Sales.SalesPerson tables in conjunction with all of the data from the

Sales.SalesPerson table and matching data in the Sales.SalesTerritory table. For records that

exist Sales.SalesPerson table and not in the Sales.SalesTerritory table, NULL values are returned

for the columns in the Sales.SalesTerritory. In addition, this code uses two columns to order the

data i.e. ST.TerritoryID and C.LastName.

USE AdventureWorks;

GO

SELECT C.ContactID,

C.FirstName,

C.LastName,

SP.SalesPersonID,

SP.CommissionPct,

SP.SalesYTD,

SP.SalesLastYear,

SP.Bonus,

ST.TerritoryID,

ST.Name,

ST.[Group],

ST.SalesYTD

FROM Person.Contact C

INNER JOIN Sales.SalesPerson SP

ON C.ContactID = SP.SalesPersonID

LEFT OUTER JOIN Sales.SalesTerritory ST

ON ST.TerritoryID = SP.TerritoryID

ORDER BY ST.TerritoryID, C.LastName

GO

RIGHT OUTER JOIN Example

In an effort to explain how the RIGHT OUTER JOIN and LEFT OUTER JOIN is logically a

reciprocal on one another, the code below is re-written version of the LEFT OUTER JOIN

above. As you can see the JOIN order and tables are different, but the final result set matches

the LEFT OUTER JOIN logic. In the sample code below, we are retrieving the matching data

between the Person.Contact and Sales.SalesPerson tables in conjunction with all of the data from

the Sales.SalesPerson table and matching data in the Sales.SalesTerritory table. For records that

exist Sales.SalesPerson table and not in the Sales.SalesTerritory table, NULL values are returned

for the columns in the Sales.SalesTerritory.

USE AdventureWorks;

GO

SELECT C.ContactID,

C.FirstName,

C.LastName,

SP.SalesPersonID,

SP.CommissionPct,

SP.SalesYTD,

SP.SalesLastYear,

SP.Bonus,

ST.TerritoryID,

ST.Name, ST.[Group],

ST.SalesYTD

FROM Sales.SalesTerritory ST

RIGHT OUTER JOIN Sales.SalesPerson SP

ON ST.TerritoryID = SP.TerritoryID

INNER JOIN Person.Contact C

ON C.ContactID = SP.SalesPersonID

ORDER BY ST.TerritoryID, C.LastName

GO

Self Join Example

In this example, we are actually self joining to the HumanResources.Employee table. We are

doing this to obtain the information about the Employee and Manager relationship in the

HumanResources.Employee table. In conjunction with that JOIN logic we are also joining to the

Person.Contact twice in order to capture the name and title data based on the original Employee

and Manager relationships. In addition, another new concept introduced in this query is aliasing

each of the columns. Although we could have done so in the previous examples, we made point

of doing so in this query to differentiate between the Employee and Manager related data.

USE AdventureWorks;

GO

SELECT M.ManagerID AS 'ManagerID',

M1.ContactID AS 'ManagerContactID',

M1.FirstName AS 'ManagerFirstName',

M1.LastName AS 'ManagerLastName',

M.Title AS 'ManagerTitle',

E.EmployeeID AS 'EmployeeID',

E1.ContactID AS 'EmployeeContactID',

E1.FirstName AS 'EmployeeFirstName',

E1.LastName AS 'EmployeeLastName',

E.Title AS 'EmployeeTitle'

FROM HumanResources.Employee E

INNER JOIN HumanResources.Employee M

ON E.ManagerID = M.ManagerID

INNER JOIN Person.Contact E1

ON E1.ContactID = E.ContactID

INNER JOIN Person.Contact M1

ON M1.ContactID = M.ContactID

ORDER BY M1.LastName

GO

CROSS JOIN Example

As indicated above, please heed caution when running or modifying this query in any SQL

Server database environment. The result set is intentionally limited by the TOP 100 clause and

the WHERE clause to prevent a Cartesian product, which is the result of each of the rows from

the left table multiplied by the number of rows in the right table.

USE AdventureWorks;

GO

SELECT TOP 100 P.ProductID,

P.Name,

P.ListPrice,

P.Size,

P.ModifiedDate,

SOD.UnitPrice,

SOD.UnitPriceDiscount,

SOD.OrderQty,

SOD.LineTotal

FROM Sales.SalesOrderDetail SOD

CROSS JOIN Production.Product P

WHERE SOD.UnitPrice > 3500

ORDER BY SOD.UnitPrice DESC

GO

FULL OUTER JOIN Example

In our last example, we have modified the logic from the LEFT OUTER JOIN example above

and converted the LEFT OUTER JOIN syntax to a FULL OUTER JOIN. In this circumstance,

the result set is the same as the LEFT OUTER JOIN where we are returning all of the data

between both tables and data not available in the Sales.SalesTerritory is returned as NULL.

USE AdventureWorks;

GO

SELECT C.ContactID,

C.FirstName,

C.LastName,

SP.SalesPersonID,

SP.CommissionPct,

SP.SalesYTD,

SP.SalesLastYear,

SP.Bonus,

ST.TerritoryID,

ST.Name,

ST.[Group],

ST.SalesYTD

FROM Person.Contact C

INNER JOIN Sales.SalesPerson SP

ON C.ContactID = SP.SalesPersonID

FULL OUTER JOIN Sales.SalesTerritory ST

ON ST.TerritoryID = SP.TerritoryID

ORDER BY ST.TerritoryID, C.LastName

GO

Next Steps

• As you begin to start coding in SQL Server be sure to have a firm understanding of the JOIN

options available as well as the associated data that is retrieved. Be sure to select the correct

JOIN logic based on the data that needs to be retrieved.

• Once you have a firm grasp of the JOIN logic with SELECT statements, progress to using the logic

with INSERT...SELECT, SELECT...INTO, UPDATE and DELETE statements

• In your learning process progresses, be sure to check out some of the alternatives to JOINs such

as:

o Joining data and differences of using UNION and UNION ALL in SQL Server

o Comparing Multiple SQL Server Datasets with the INTERSECT and EXCEPT operators

• Special thanks to Dave of the MSSQLTips community for suggesting this tip. If you have a SQL

Server problem you would like answered, please email [email protected] to see if we can

provide the solution to you.

• Check out the related MSSQLTips:

o SQL Server Cursor Examples

o SQL Server T-SQL Aggregate Functions

o Getting started with SQL Server stored procedures

o SQL Server 2000 Text Data Manipulation

o Date/Time Conversions Using SQL Server

Join SQL Server tables where columns

include NULL values

By: Greg Robidoux http://www.mssqltips.com/sqlservertip/1447/join-sql-server-tables-where-columns-

include-null-values/

Problem

When building database tables you are faced with the decision of whether to allow NULL values

or to not allow NULL values in your columns. By default SQL Server sets the column value to

allow NULL values when creating new tables, unless other options are set. This is not

necessarily a bad thing, but dealing with NULL values especially when joining tables can

become a challenge. Let's take a look at this issue and how this can be resolved.

Solution In most cases your columns in your tables probably allow NULL values unless you consciously

changed them when you created a table or changed the default setting for your database by using

the SET ANSI_NULL_DEFAULT OFF and SET ANSI_NULL_DFLT_ON OFF option. These

settings change the behavior of how a table is created if you do not specify NULL or NOT

NULL when creating a table.

The following examples show you how a table would get created differently with each of these

options, but by default SQL Server sets columns to allow nulls.

Example 1: When these two options are OFF the default nullable value is set to no, meaning no

null values are acceptable.

ALTER DATABASE AdventureWorks SET ANSI_NULL_DEFAULT OFF;

GO

SET ANSI_NULL_DFLT_ON OFF;

GO

CREATE TABLE Table1 (a TINYINT);

GO

sp_help Table1

GO

The screen shot below shows that the column does not allow NULLs.

Example 2: When these two options are ON the default nullable value is set to yes, meaning null

values are acceptable.

ALTER DATABASE AdventureWorks SET ANSI_NULL_DEFAULT ON;

GO

SET ANSI_NULL_DFLT_ON ON;

GO

CREATE TABLE Table2 (a TINYINT);

GO

sp_help Table2

GO

The screen shot below shows that the this column does allow NULLs.

So now that we have that covered let's get down to the issue at hand. So based on how tables

and columns are setup and how data is stored you may run into an issue where you have data

stored in tables that have NULL values and you need to join on these values. Sounds pretty easy,

but let's see what happens when this occurs.

Setup Test

First let's create two tables and load some sample data. (This is not a very practical example, but

it does help illustrate the issue.)

CREATE TABLE [dbo].[CarModels](

[Make] [varchar](50) NULL,

[Model] [varchar](50) NULL,

[Trim] [varchar](50) NULL

) ON [PRIMARY]

GO

CREATE TABLE [dbo].[Orders](

[Make] [varchar](50) NULL,

[Model] [varchar](50) NULL,

[Trim] [varchar](50) NULL

) ON [PRIMARY]

GO

INSERT INTO dbo.Orders VALUES ('Nissan','Altima','2-door 2.5 S Coupe')

INSERT INTO dbo.Orders VALUES ('Nissan','Altima','4-door 3.5 SE Sedan')

INSERT INTO dbo.Orders VALUES ('Nissan','Altima','')

INSERT INTO dbo.Orders VALUES ('Nissan','Altima',NULL)

INSERT INTO dbo.CarModels VALUES ('Nissan','Altima','')

INSERT INTO dbo.CarModels VALUES ('Nissan','Altima','2-door 2.5 S Coupe')

INSERT INTO dbo.CarModels VALUES ('Nissan','Altima','2-door 3.5 SE Coupe')

INSERT INTO dbo.CarModels VALUES ('Nissan','Altima','4-door 2.5 S Sedan')

INSERT INTO dbo.CarModels VALUES ('Nissan','Altima','4-door 3.5 SE Sedan')

INSERT INTO dbo.CarModels VALUES ('Nissan','Altima','4-door 3.5 SL Sedan')

INSERT INTO dbo.CarModels VALUES ('Nissan','Altima','4-door HYBRID Sedan')

INSERT INTO dbo.CarModels VALUES ('Nissan','Altima',NULL)

Selecting data

The first thing we will do is show the data in these two tables. The idea here is that we want to

join the tables based on Make, Model and Trim. For most of the records there is some value, but

there are a few records where the Trim value is NULL.

SELECT *

FROM dbo.Orders a

SELECT *

FROM dbo.CarModels b

The first query does a straight join of these tables based on all three columns.

SELECT *

FROM dbo.Orders a

INNER JOIN dbo.CarModels b

ON a.Make = b.Make

AND a.Model = b.Model

AND a.Trim = b.Trim

The result of the above query matches only three of the four records from the Orders table. The

records that have a NULL value for Trim do not show up in the resultset.

This next example introduces the ISNULL function in the join clause. The ISNULL function

takes two parameters, the first is the value to interrogate to see if it is NULL and it if is NULL

the second parameter specifies what the value should be converted to. So in this example if any

value is NULL it will be converted to a space ''.

SELECT *

FROM dbo.Orders a

INNER JOIN dbo.CarModels b

ON a.Make = b.Make

AND a.Model = b.Model

AND isnull(a.Trim,'') = isnull(b.Trim,'')

In the results below we can see that we now have more rows, but one of the issues we are facing

is that there are also values of space in the table and therefore we are picking up additional joins

that we do not want. The rows that should not be included are highlighted below.

To take this a step further we are using the ISNULL function again, but this time we are

converting the NULL values to '999999'. This is a value that we know does not exist in our table

and therefore will not cause any unwanted joins.

SELECT *

FROM dbo.Orders a

INNER JOIN dbo.CarModels b

ON a.Make = b.Make

AND a.Model = b.Model

AND isnull(a.Trim,'999999') = isnull(b.Trim,'999999')

Here is our final result with the four rows we are expecting.

Summary

As we have seen from the above examples joining NULL values does not work. Even though

you have two NULL values SQL Server does not treat these as the same value. Internally a

value of NULL is an unknown value and therefore SQL Server does not equate an unknown

value being equal to another unknown value. Another design decision is to not allow NULL

values and therefore you will not run into these issues.

Next Steps

• When dealing with NULL values don't forget about the ISNULL function

• Be aware when creating tables whether you want to allow NULL values or not. By

allowing NULL values you introduce other issues that you may need to face at a later

time.

• Although the ISNULL function is handy, if you are doing large joins having this function

in the join clause will slow down the query. A lot of this will also depend on the indexes

you have setup and how the indexes are used for the join. In general it is not a good idea

to use functions in your joins or on the left side of your WHERE clause, because SQL

Server needs to interrogate each value and therefore may negate the use of the index.

Although in some cases there are no other options, so you need to do what you need to

do.

Joining data using UNION and UNION ALL

in SQL Server

By: Greg Robidoux http://www.mssqltips.com/sqlservertip/1387/joining-data-using-union-and-union-

all-in-sql-server/

Problem Sometimes there is a need to combine data from multiple tables or views into one comprehensive

dataset. This may be for like tables within the same database or maybe there is a need to combine

like data across databases or even across servers. I have read about the UNION and UNION

ALL commands, but how do these work and how do they differ?

Solution In SQL Server you have the ability to combine multiple datasets into one comprehensive dataset

by using the UNION or UNION ALL operators. There is a big difference in how these work as

well as the final result set that is returned, but basically these commands join multiple datasets

that have similar structures into one combined dataset.

Here is a brief description:

• UNION - this command will allow you to join multiple datasets into one dataset and will remove

any duplicates that exist. Basically it is performing a DISTINCT operation across all columns in

the result set.

• UNION ALL - this command again allows you to join multiple datasets into one dataset, but it

does not remove any duplicate rows. Because this does not remove duplicate rows this process

is faster, but if you don't want duplicate records you will need to use the UNION operator

instead.

Rules to union data:

• Each query must have the same number of columns

• Each column must have compatible data types

• Column names for the final result set are taken from the first query

• ORDER BY and COMPUTE clauses can only be issued for the overall result set and not within

each individual result set

• GROUP BY and HAVING clauses can only be issued for each individual result set and not for the

overall result set

Tip

If you don't have the exact same columns in all queries use a default value or a NULL value such as:

SELECT firstName, lastName, company FROM businessContacts

UNION ALL

SELECT firstName, lastName, NULL FROM nonBusinessContacts

or

SELECT firstName, lastName, createDate FROM businessContacts

UNION ALL

SELECT firstName, lastName, getdate() FROM

nonBusinessContacts

Examples:

Let's take a look at a few simple examples of how these commands work and how they differ.

As you will see the final resultsets will differ, but there is some interesting info on how SQL

Server actually completes the process.

In this first example we are using the UNION ALL operator against the Employee table from the

AdventureWorks database. This is probably not something you would do, but this helps

illustrate the differences of these two operators.

There are 290 rows in table dbo.Employee.

SELECT * FROM dbo.Employee

UNION ALL

SELECT * FROM dbo.Employee

UNION ALL

SELECT * FROM dbo.Employee

When this query is run the result set has 870 rows. This is the 290 rows returned 3 times. The

data is just put together one dataset on top of the other dataset.

Here is the execution plan for this query. We can see that the table was queried 3 times and SQL

Server did a Concatenation step to concatenate all of the data.

In this next example we are using the UNION operator against the Employee table again from

the AdventureWorks database.

SELECT * FROM dbo.Employee

UNION

SELECT * FROM dbo.Employee

UNION

SELECT * FROM dbo.Employee

When this query is run the result set has 290 rows. Even though we combined the data three

times the UNION operator removed the duplicate records and therefore returns just the 290

unique rows.

Here is the execution plan for this query. We can see that SQL Server first queried 2 of the

tables, then did a Merge Join operation to combine the first two tables and then it did another

Merge Join along with querying the third table in the query. So we can see there was much more

worked that had to be performed to get this result set compared to the UNION ALL.

If we take this a step further and do a SORT of the data using the Clustered Index column we get

these execution plans. From this we can see that the execution plan that SQL Server is using is

identical for each of these operations even though the final result sets will still contain 870 rows

for the UNION ALL and 290 rows for the UNION.

UNION ALL query

UNION query

Here is another example doing the same thing, but this time doing a SORT on a non indexed

column. As you can see the execution plans are again identical for these two queries, but this

time instead of using a MERGE JOIN, a CONCATENATION and SORT operations are used.

UNION ALL query

UNION query

Next Steps

• Take a look at these other tips that may be useful for using the union operators

o Comparing Multiple Datasets with the INTERSECT and EXCEPT operators

o SQL Server Four-part naming

Compare SQL Server Datasets with

INTERSECT and EXCEPT

By: Greg Robidoux http://www.mssqltips.com/sqlservertip/1327/compare-sql-server-datasets-

with-intersect-and-except/

Problem When joining multiple datasets you have always had the ability to use the UNION and UNION

ALL operator to allow you to pull a distinct result set (union) or a complete result set (union all).

These are very helpful commands when you need to pull data from different tables and show the

results as one unified distinct result set. On the opposite side of this it would be helpful to only

show a result set where both sets of data match or only where data exists in one of the tables and

not the other. This could be done with using different join types, but what other options does

SQL Server offer?

Solution

With SQL Server 2005, Microsoft introduced the INTERSECT and EXCEPT operators to

further extend what you could already do with the UNION and UNION ALL operators.

• INTERSECT - gives you the final result set where values in both of the tables match

• EXCEPT - gives you the final result set where data exists in the first dataset and not in

the second dataset

The advantage of these commands is that it allows you to get a distinct listing across all of the

columns such as the UNION and UNION ALL operators do without having to do a group by or

do a comparison of every single column.

Like the UNION and UNION ALL operators the table structures need to be consistent as well as

the columns need to have compatible data types.

Let's take for example we have two tables manager and customer. Both of these tables have

somewhat the same structure such as the following columns:

• FirstName

• LastName

• AddressLine1

• City

• StateProvinceCode

• PostalCode

Manager table sample data

Customer table sample data

We want to do two queries:

1. Find the occurrences where a manager is a customer (intersect)

2. Find the occurrences where the manager is not a customer (except)

INTERSECT

If we want to find out which people exist in both the customer table and the manager table and

get a distinct list back we can issue the following command:

SELECT FIRSTNAME,

LASTNAME,

ADDRESSLINE1,

CITY,

STATEPROVINCECODE,

POSTALCODE

FROM MANAGER

INTERSECT

SELECT FIRSTNAME,

LASTNAME,

ADDRESSLINE1,

CITY,

STATEPROVINCECODE,

POSTALCODE

FROM CUSTOMER

Here is the result set:

To do this same thing with a regular T-SQL command we would have to write the following:

SELECT M.FIRSTNAME,

M.LASTNAME,

M.ADDRESSLINE1,

M.CITY,

M.STATEPROVINCECODE,

M.POSTALCODE

FROM MANAGER M

INNER JOIN CUSTOMER C

ON M.FIRSTNAME = C.FIRSTNAME

AND M.LASTNAME = C.LASTNAME

AND M.ADDRESSLINE1 = C.ADDRESSLINE1

AND M.CITY = C.CITY

AND M.POSTALCODE = C.POSTALCODE

GROUP BY M.FIRSTNAME,M.LASTNAME,M.ADDRESSLINE1,M.CITY,

M.STATEPROVINCECODE,M.POSTALCODE

EXCEPT

If we want to find out which people exists in the manager table, but not in the customer table and

get a distinct list back we can issue the following command:

SELECT FIRSTNAME,

LASTNAME,

ADDRESSLINE1,

CITY,

STATEPROVINCECODE,

POSTALCODE

FROM MANAGER

EXCEPT

SELECT FIRSTNAME,

LASTNAME,

ADDRESSLINE1,

CITY,

STATEPROVINCECODE,

POSTALCODE

FROM CUSTOMER

Here is the result set:

To do this same thing with a regular T-SQL command we would have to write the following:

SELECT M.FIRSTNAME,

M.LASTNAME,

M.ADDRESSLINE1,

M.CITY,

M.STATEPROVINCECODE,

M.POSTALCODE

FROM MANAGER M

WHERE NOT EXISTS (SELECT *

FROM CUSTOMER C

WHERE M.FIRSTNAME = C.FIRSTNAME

AND M.LASTNAME = C.LASTNAME

AND M.ADDRESSLINE1 = C.ADDRESSLINE1

AND M.CITY = C.CITY

AND M.POSTALCODE = C.POSTALCODE)

GROUP BY M.FIRSTNAME,M.LASTNAME,M.ADDRESSLINE1,M.CITY,

M.STATEPROVINCECODE,M.POSTALCODE

From the two examples above we can see that using the EXCEPT and INTERSECT commands

are much simpler to write then having to write the join or exists statements.

To take this a step further if we had a third table (or forth...) that listed sales reps and we wanted

to find out which managers were customers, but not sales reps we could do the following.

SalesRep table sample data

SELECT FIRSTNAME,

LASTNAME,

ADDRESSLINE1,

CITY,

STATEPROVINCECODE,

POSTALCODE

FROM MANAGER

INTERSECT

SELECT FIRSTNAME,

LASTNAME,

ADDRESSLINE1,

CITY,

STATEPROVINCECODE,

POSTALCODE

FROM CUSTOMER

EXCEPT

SELECT FIRSTNAME,

LASTNAME,

ADDRESSLINE1,

CITY,

STATEPROVINCECODE,

POSTALCODE

FROM SALESREP

Here is the result set:

As you can see this is pretty simple to mix and match these statements. In addition, you could

also use the UNION and UNION ALL operators to further extend your final result sets.

Next Steps

• Take a look at your existing code to see how the INTERSECT and EXCEPT operators

could be used

• Keep these new operators in mind next time you need to compare different datasets with

like data

Automatically generate a SELECT statement in SQL Server Management Studio

for a table example

Overview From your previous examples, I want to find out how to get SQL Server Management Studio

(SSMS) to do the work for me. How can I have this tool generate a SELECT statement rather

than typing out each of the columns?

Explanation SQL Server Management Studio does have a simple means to automatically generate a SELECT

statement from a single table. Let's follow the steps below:

Once you are in SQL Server Management Studio, right click on the table you which you would like to have the SELECT statement generated for.

On the subsequent interface, select the 'Script Table as' option.

On the subsequent interface, select the 'SELECT To' option.

On the subsequent interface, select the 'New Query Editor Window' option.

Below is a sample image of the SELECT code generated for a table.

Getting started with SQL Server stored

procedures

By: Greg Robidoux http://www.mssqltips.com/sqlservertip/1495/getting-started-with-sql-

server-stored-procedures/

Problem I have been using SQL Server for some time, but all of the code that is issued against the

database is embedded in the application code. I know that you can create stored procedures, but

I am not exactly sure where to start or what I need to do to implement stored procedures.

Solution Stored procedures are nothing more that a batch of T-SQL statements that are stored in the

database. Instead of having to issues multiple statements from your application you can issue

one command to call the stored procedure to do a batch of work instead of just one statement. In

addition, since the code is stored in the database you can issue the same set of code over and over

again even from different applications or a query window. To get started the rest of this tip looks

at some sample stored procedures and how you can get started and build upon them.

The below examples show you how simple it is to create stored procedures. All of these

examples use the AdventureWorks database, but these should be pretty straightforward that you

can apply these concepts to your own databases and applications.

Example 1 - simple stored procedure

This first example creates a simple stored procedure that gets the TOP 1 record from the Person.Contact table.

CREATE PROCEDURE uspGetContact

AS

SELECT TOP 1 ContactID, FirstName, LastName

FROM Person.Contact

After the above has been created use the command below to execute this stored procedure.

EXEC uspGetContact

This is the results from this first query.

Example 2 - stored procedure with a parameter

This next example is a modification of the first example, but this time adding a parameter that is passed into the procedure to dynamically select the records. Instead of using CREATE PROCEDURE we are using ALTER PROCEDURE to modify the procedure that we created in Example 1 instead of dropping it first and then recreating it.

ALTER PROCEDURE uspGetContact @LastName NVARCHAR(50)

AS

SELECT TOP 1 ContactID, FirstName, LastName

FROM Person.Contact

WHERE LastName = @LastName

Below shows two different ways the stored procedure can be run. The first example just passes the parameter value we want to use and the second example also includes the parameter name along with the value. You can run the stored procedure with either one of these commands.

EXEC uspGetContact 'Alberts'

EXEC uspGetContact @LastName='Alberts'

This is the results from this first query.

Example 3 - stored procedure with a parameter and output parameter

In this example we have both an input parameter as well as an OUTPUT parameter. The output parameter will be used to pass back the ContactID that we are looking up in the stored procedure. This output parameter will then be used to select the persons ContactID, FirstName and LastName along with any address records for this person.

Again we are altering the stored procedure uspGetContact and then secondly we are running the next set of code that executes procedure uspGetContact and then based on the return value it gets it will also query for the persons name and address info.

ALTER PROCEDURE uspGetContact @LastName NVARCHAR(50), @ContactID INT output

AS

SELECT TOP 1 @ContactID = c.ContactID

FROM HumanResources.Employee a

INNER JOIN HumanResources.EmployeeAddress b ON a.EmployeeID = b.EmployeeID

INNER JOIN Person.Contact c ON a.ContactID = c.ContactID

INNER JOIN Person.Address d ON b.AddressID = d.AddressID

WHERE c.LastName = @LastName

After the stored procedure has been altered run the below block of code. This will execute the above stored procedure and if the ContactID has a value it will also return the person and address info.

DECLARE @ContactID INT

SET @ContactID = 0

EXEC uspGetContact @LastName='Smith', @ContactID=@ContactID OUTPUT

IF @ContactID <> 0

BEGIN

SELECT ContactID, FirstName, LastName

FROM Person.Contact

WHERE ContactID = @ContactID

SELECT d.AddressLine1, d.City, d.PostalCode

FROM HumanResources.Employee a

INNER JOIN HumanResources.EmployeeAddress b ON a.EmployeeID = b.EmployeeID

INNER JOIN Person.Contact c ON a.ContactID = c.ContactID

INNER JOIN Person.Address d ON b.AddressID = d.AddressID

WHERE c.ContactID = @ContactID

END

This is the results from this first query.

Example 4 - stored procedure using the RAISERROR statement

In this example we are combining the two steps in Example 3 into one stored procedure. The first step is to get the ContactID and then the second part of the procedure will lookup the persons name and address info. We also added in code to use the RAISERROR statement to return an error if no records are found.

This is then being run twice to show what it looks like when data is found and when no data is found. The RAISERROR statement can be used to control how your application handles no data or any other error that may occur.

ALTER PROCEDURE uspGetContact @LastName NVARCHAR(50)

AS

DECLARE @ContactID INT

SELECT TOP 1 @ContactID = c.ContactID

FROM HumanResources.Employee a

INNER JOIN HumanResources.EmployeeAddress b ON a.EmployeeID = b.EmployeeID

INNER JOIN Person.Contact c ON a.ContactID = c.ContactID

INNER JOIN Person.Address d ON b.AddressID = d.AddressID

WHERE c.LastName = @LastName

IF @@ROWCOUNT > 0

BEGIN

SELECT ContactID, FirstName, LastName

FROM Person.Contact

WHERE ContactID = @ContactID

SELECT d.AddressLine1, d.City, d.PostalCode

FROM HumanResources.Employee a

INNER JOIN HumanResources.EmployeeAddress b ON a.EmployeeID = b.EmployeeID

INNER JOIN Person.Contact c ON a.ContactID = c.ContactID

INNER JOIN Person.Address d ON b.AddressID = d.AddressID

WHERE c.ContactID = @ContactID

END

ELSE

BEGIN

RAISERROR ('No record found',10,1)

END

EXEC uspGetContact @LastName='Walters'

This is the results from this first query.

EXEC uspGetContact @LastName='Job'

This is the results from this first query when no data is found.

Example 5 - stored procedure with a separate calling stored procedure

Here is another example where we have two stored procedures. The first stored procedure uspFindContact lookups the first record that has an address record and then returns the ContactID to the calling stored procedure to again display the person and address info.

CREATE PROCEDURE uspFindContact @LastName NVARCHAR(50), @ContactID INT output

AS

SELECT TOP 1 @ContactID = c.ContactID

FROM HumanResources.Employee a

INNER JOIN HumanResources.EmployeeAddress b ON a.EmployeeID = b.EmployeeID

INNER JOIN Person.Contact c ON a.ContactID = c.ContactID

INNER JOIN Person.Address d ON b.AddressID = d.AddressID

WHERE c.LastName = @LastName

The code below does an alter of the uspGetContact stored procedure that calls uspFindContact and returns the recordsets.

ALTER PROCEDURE uspGetContact @LastName NVARCHAR(50)

AS

DECLARE @ContactID INT

SET @ContactID = 0

EXEC uspFindContact @LastName=@LastName, @ContactID=@ContactID OUTPUT

IF @ContactID <> 0

BEGIN

SELECT ContactID, FirstName, LastName

FROM Person.Contact

WHERE ContactID = @ContactID

SELECT d.AddressLine1, d.City, d.PostalCode

FROM HumanResources.Employee a

INNER JOIN HumanResources.EmployeeAddress b ON a.EmployeeID = b.EmployeeID

INNER JOIN Person.Contact c ON a.ContactID = c.ContactID

INNER JOIN Person.Address d ON b.AddressID = d.AddressID

WHERE c.ContactID = @ContactID

END

ELSE

BEGIN

RAISERROR ('No record found',10,1)

END

EXEC uspGetContact @LastName='Walters'

This is the results from this first query.

EXEC uspGetContact @LastName='Job'

This is the results from this first query.

Example 6 - stored procedure with comments

This last example takes the uspGetContact stored procedure and adds comments to the code so you can see how comments work within a stored procedure. You can see that there are two ways that comments can be made. 1) using -- and 2) using /* to begin the comment block and */ to end the comment block. Other than that nothing else has changed.

ALTER PROCEDURE uspGetContact @LastName NVARCHAR(50)

AS

/* This is a sample stored procedure to show

how comments work within a stored procedure */

-- declare variable

DECLARE @ContactID INT

-- set variable value

SET @ContactID = 0

-- execute stored proc and return ContactID value

EXEC uspFindContact @LastName=@LastName, @ContactID=@ContactID OUTPUT

-- if ContactID does not equal 0 then return data else return error

IF @ContactID <> 0

BEGIN

SELECT ContactID, FirstName, LastName

FROM Person.Contact

WHERE ContactID = @ContactID

SELECT d.AddressLine1, d.City, d.PostalCode

FROM HumanResources.Employee a

INNER JOIN HumanResources.EmployeeAddress b ON a.EmployeeID = b.EmployeeID

INNER JOIN Person.Contact c ON a.ContactID = c.ContactID

INNER JOIN Person.Address d ON b.AddressID = d.AddressID

WHERE c.ContactID = @ContactID

END

ELSE

BEGIN

RAISERROR ('No record found',10,1)

END

These are pretty simple examples, but hopefully this gives you an idea of how easy it is to create

stored procedures for SQL Server. If you can run a SELECT statement from either a query

window or from your application you can just as easily run a stored procedure as show above.

Next Steps

• If you are not already using stored procedures hopefully this gives you some insight as to

what you need to do to begin using them

• As mentioned these are pretty simple examples, but just about anything you can do with a

batch of statements can be combined into a stored procedure and then used over and over

again for your applications.

http://www.mssqltips.com/sqlservertutorial/160/sql-server-stored-procedure/

SQL Server Stored Procedure

(Introduction)

Overview A stored procedure is nothing more than prepared SQL code that you save so you can reuse the

code over and over again. So if you think about a query that you write over and over again,

instead of having to write that query each time you would save it as a stored procedure and then

just call the stored procedure to execute the SQL code that you saved as part of the stored

procedure.

In addition to running the same SQL code over and over again you also have the ability to pass

parameters to the stored procedure, so depending on what the need is the stored procedure can

act accordingly based on the parameter values that were passed.

Take a look through each of these topics to learn how to get started with stored procedure

development for SQL Server.

You can either use the outline on the left or click on the arrows to the right or below to scroll

through each of these topics.

(CREATE PROCEDURE)

Overview As mentioned in the tutorial overview a stored procedure is nothing more than stored SQL code

that you would like to use over and over again. In this example we will look at creating a simple

stored procedure.

Explanation Before you create a stored procedure you need to know what your end result is, whether you are

selecting data, inserting data, etc..

In this simple example we will just select all data from the Person.Address table that is stored in

the AdventureWorks database.

So the simple T-SQL code would be as follows which will return all rows from this table.

SELECT * FROM AdventureWorks.Person.Address

To create a stored procedure to do this the code would look like this:

CREATE PROCEDURE uspGetAddress

AS

SELECT * FROM AdventureWorks.Person.Address

GO

To call the procedure to return the contents from the table specified, the code would be:

EXEC uspGetAddress

--or just simply

uspGetAddress

When creating a stored procedure you can either use CREATE PROCEDURE or CREATE

PROC. After the stored procedure name you need to use the keyword "AS" and then the rest is

just the regular SQL code that you would normally execute.

On thing to note is that you cannot use the keyword "GO" in the stored procedure. Once the

SQL Server compiler sees "GO" it assumes it is the end of the batch.

Also, you can not change database context within the stored procedure such as using "USE

dbName" the reason for this is because this would be a separate batch and a stored procedure is a

collection of only one batch of statements.

How to create a SQL Server stored procedure with parameters

Overview The real power of stored procedures is the ability to pass parameters and have the stored

procedure handle the differing requests that are made. In this topic we will look at passing

parameter values to a stored procedure.

Explanation Just like you have the ability to use parameters with your SQL code you can also setup your

stored procedures to except one or more parameter values.

One Parameter

In this example we will query the Person.Address table from the AdventureWorks database, but

instead of getting back all records we will limit it to just a particular city. This example assumes

there will be an exact match on the City value that is passed.

CREATE PROCEDURE uspGetAddress @City nvarchar(30)

AS

SELECT *

FROM AdventureWorks.Person.Address

WHERE City = @City

GO

To call this stored procedure we would execute it as follows:

EXEC uspGetAddress @City = 'New York'

We can also do the same thing, but allow the users to give us a starting point to search the data.

Here we can change the "=" to a LIKE and use the "%" wildcard.

CREATE PROCEDURE uspGetAddress @City nvarchar(30)

AS

SELECT *

FROM AdventureWorks.Person.Address

WHERE City LIKE @City + '%'

GO

In both of the proceeding examples it assumes that a parameter value will always be

passed. If you try to execute the procedure without passing a parameter value you will get an

error message such as the following:

Msg 201, Level 16, State 4, Procedure uspGetAddress, Line 0

Procedure or function 'uspGetAddress' expects parameter '@City', which was

not supplied.

Default Parameter Values

In most cases it is always a good practice to pass in all parameter values, but sometimes it is not

possible. So in this example we use the NULL option to allow you to not pass in a parameter

value. If we create and run this stored procedure as is it will not return any data, because it is

looking for any City values that equal NULL.

CREATE PROCEDURE uspGetAddress @City nvarchar(30) = NULL

AS

SELECT *

FROM AdventureWorks.Person.Address

WHERE City = @City

GO

We could change this stored procedure and use the ISNULL function to get around this. So if a

value is passed it will use the value to narrow the result set and if a value is not passed it will

return all records.

CREATE PROCEDURE uspGetAddress @City nvarchar(30) = NULL

AS

SELECT *

FROM AdventureWorks.Person.Address

WHERE City = ISNULL(@City,City)

GO

Multiple Parameters

Setting up multiple parameters is very easy to do. You just need to list each parameter and the

data type separated by a comma as shown below.

CREATE PROCEDURE uspGetAddress @City nvarchar(30) = NULL, @AddressLine1

nvarchar(60) = NULL

AS

SELECT *

FROM AdventureWorks.Person.Address

WHERE City = ISNULL(@City,City)

AND AddressLine1 LIKE '%' + ISNULL(@AddressLine1 ,AddressLine1) + '%'

GO

To execute this you could do any of the following:

EXEC uspGetAddress @City = 'Calgary'

--or

EXEC uspGetAddress @City = 'Calgary', @AddressLine1 = 'A'

--or

EXEC uspGetAddress @AddressLine1 = 'Acardia'

-- etc...

Returning stored procedure parameter values to a calling stored procedure

(OUTPUT)

Overview In a previous topic we discussed how to pass parameters into a stored procedure, but another

option is to pass parameter values back out from a stored procedure. One option for this may be

that you call another stored procedure that does not return any data, but returns parameter values

to be used by the calling stored procedure.

Explanation Setting up output paramters for a stored procedure is basically the same as setting up input

parameters, the only difference is that you use the OUTPUT clause after the parameter name to

specify that it should return a value. The output clause can be specified by either using the

keyword "OUTPUT" or just "OUT".

Simple Output

CREATE PROCEDURE uspGetAddressCount @City nvarchar(30), @AddressCount int

OUTPUT

AS

SELECT @AddressCount = count(*)

FROM AdventureWorks.Person.Address

WHERE City = @City

Or it can be done this way:

CREATE PROCEDURE uspGetAddressCount @City nvarchar(30), @AddressCount int OUT

AS

SELECT @AddressCount = count(*)

FROM AdventureWorks.Person.Address

WHERE City = @City

To call this stored procedure we would execute it as follows. First we are going to declare a

variable, execute the stored procedure and then select the returned valued.

DECLARE @AddressCount int

EXEC uspGetAddressCount @City = 'Calgary', @AddressCount = @AddressCount

OUTPUT

SELECT @AddressCount

This can also be done as follows, where the stored procedure parameter names are not passed.

DECLARE @AddressCount int

EXEC uspGetAddressCount 'Calgary', @AddressCount OUTPUT

SELECT @AddressCount

Using try catch in SQL Server stored procedures

(TRY...CATCH)

Overview

A great new option that was added in SQL Server 2005 was the ability to use the Try..Catch

paradigm that exists in other development languages. Doing error handling in SQL Server has

not always been the easiest thing, so this option definitely makes it much easier to code for and

handle errors.

Explanation If you are not familiar with the Try...Catch paradigm it is basically two blocks of code with your

stored procedures that lets you execute some code, this is the Try section and if there are errors

they are handled in the Catch section.

Let's take a look at an example of how this can be done. As you can see we are using a basic

SELECT statement that is contained within the TRY section, but for some reason if this fails it

will run the code in the CATCH section and return the error information.

CREATE PROCEDURE uspTryCatchTest

AS

BEGIN TRY

SELECT 1/0

END TRY

BEGIN CATCH

SELECT ERROR_NUMBER() AS ErrorNumber

,ERROR_SEVERITY() AS ErrorSeverity

,ERROR_STATE() AS ErrorState

,ERROR_PROCEDURE() AS ErrorProcedure

,ERROR_LINE() AS ErrorLine

,ERROR_MESSAGE() AS ErrorMessage;

END CATCH

Using comments in a SQL Server stored procedure

Overview One very helpful thing to do with your stored procedures is to add comments to your code. This

helps you to know what was done and why for future reference, but also helps other DBAs or

developers that may need to make modifications to the code.

Explanation SQL Server offers two types of comments in a stored procedure; line comments and block

comments. The following examples show you how to add comments using both techniques.

Comments are displayed in green in a SQL Server query window.

Line Comments

To create line comments you just use two dashes "--" in front of the code you want to comment.

You can comment out one or multiple lines with this technique.

In this example the entire line is commented out.

-- this procedure gets a list of addresses based

-- on the city value that is passed

CREATE PROCEDURE uspGetAddress @City nvarchar(30)

AS

SELECT *

FROM AdventureWorks.Person.Address

WHERE City = @City

GO

This next example shows you how to put the comment on the same line.

-- this procedure gets a list of addresses based on the city value that is

passed

CREATE PROCEDURE uspGetAddress @City nvarchar(30)

AS

SELECT *

FROM AdventureWorks.Person.Address

WHERE City = @City -- the @City parameter value will narrow the search

criteria

GO

Block Comments

To create block comments the block is started with "/*" and ends with "*/". Anything within

that block will be a comment section.

/*

-this procedure gets a list of addresses based

on the city value that is passed

-this procedure is used by the HR system

*/

CREATE PROCEDURE uspGetAddress @City nvarchar(30)

AS

SELECT *

FROM AdventureWorks.Person.Address

WHERE City = @City

GO

Combining Line and Block Comments

You can also use both types of comments within a stored procedure.

/*

-this procedure gets a list of addresses based

on the city value that is passed

-this procedure is used by the HR system

*/

CREATE PROCEDURE uspGetAddress @City nvarchar(30)

AS

SELECT *

FROM AdventureWorks.Person.Address

WHERE City = @City -- the @City parameter value will narrow the search

criteria

GO

Naming conventions for SQL Server stored procedures

Overview One good thing to do for all of your SQL Server objects is to come up with a naming convention

to use. There are not any hard and fast rules, so this is really just a guideline on what should be

done.

Explanation SQL Server uses object names and schema names to find a particular object that it needs to work

with. This could be a table, stored procedure, function ,etc...

It is a good practice to come up with a standard naming convention for you objects including

stored procedures.

Do not use sp_ as a prefix

One of the things you do not want to use as a standard is "sp_". This is a standard naming

convention that is used in the master database. If you do not specify the database where the

object is, SQL Server will first search the master database to see if the object exists there and

then it will search the user database. So avoid using this as a naming convention.

Standardize on a Prefix

It is a good idea to come up with a standard prefix to use for your stored procedures. As

mentioned above do not use "sp_", so here are some other options.

• usp_

• sp

• usp

• etc...

To be honest it does not really matter what you use. SQL Server will figure out that it is a stored

procedure, but it is helpful to differentiate the objects, so it is easier to manage.

So a few examples could be:

• spInsertPerson

• uspInsertPerson

• usp_InsertPerson

• InsertPerson

Again this is totally up to you, but some standard is better than none.

Naming Stored Procedure Action

I liked to first give the action that the stored procedure takes and then give it a name representing

the object it will affect.

So based on the actions that you may take with a stored procedure, you may use:

• Insert

• Delete

• Update

• Select

• Get

• Validate

• etc...

So here are a few examples:

• uspInsertPerson

• uspGetPerson

• spValidatePerson

• SelectPerson

• etc...

Another option is to put the object name first and the action second, this way all of the stored

procedures for an object will be together.

• uspPersonInsert

• uspPersonDelete

• uspPersonGet

• etc...

Again, this does not really matter what action words that you use, but this will be helpful to

classify the behavior characteristics.

Naming Stored Procedure Object

The last part of this is the object that you are working with. Some of these may be real objects

like tables, but others may be business processes. Keep the names simple, but meaningful. As

your database grows and you add more and more objects you will be glad that you created some

standards.

So some of these may be:

• uspInsertPerson - insert a new person record

• uspGetAccountBalance - get the balance of an account

• uspGetOrderHistory - return list of orders

Schema Names

Another thing to consider is the schema that you will use when saving the objects. A schema is

the a collection of objects, so basically just a container. This is useful if you want to keep all

utility like objects together or have some objects that are HR related, etc...

This logical grouping will help you differentiate the objects further and allow you to focus on a

group of objects.

Here are some examples of using a schema:

• HR.uspGetPerson

• HR.uspInsertPerson

• UTIL.uspGet

• UTIL.uspGetLastBackupDate

• etc...

To create a new schema you use the CREATE SCHEMA command

Here is a simple example to create a new schema called "HR" and giving authorization to this

schema to "DBO".

CREATE SCHEMA [HumanResources] AUTHORIZATION [dbo]

Putting It All Together

So you basically have four parts that you should consider when you come up with a naming

convention:

• Schema

• Prefix

• Action

• Object

Take the time to think through what makes the most sense and try to stick to your conventions.

Reducing amount of network data for SQL Server stored procedures

(SET NOCOUNT ON)

Overview There are many tricks that can be used when you write T-SQL code. One of these is to reduce

the amount of network data for each statement that occurs within your stored procedures. Every

time a SQL statement is executed it returns the number of rows that were affected. By using

"SET NOCOUNT ON" within your stored procedure you can shut off these messages and reduce

some of the traffic.

Explanation As mentioned above there is not really any reason to return messages about what is occuring

within SQL Server when you run a stored procedure. If you are running things from a query

window, this may be useful, but most end users that run stored procedures through an application

would never see these messages.

You can still use @@ROWCOUNT to get the number of rows impacted by a SQL statement, so

turning SET NOCOUNT ON will not change that behavior.

Not using SET NOCOUNT ON

Here is an example without using SET NOCOUNT ON:

-- not using SET NOCOUNT ON

CREATE PROCEDURE uspGetAddress @City nvarchar(30)

AS

SELECT *

FROM AdventureWorks.Person.Address

WHERE City = @City

GO

The messages that are returned would be similar to this:

(23 row(s) affected)

Using SET NOCOUNT ON

This example uses the SET NOCOUNT ON as shown below. It is a good practice to put this at

the beginning of the stored procedure.

-- using SET NOCOUNT ON

CREATE PROCEDURE uspGetAddress @City nvarchar(30)

AS

SET NOCOUNT ON

SELECT *

FROM AdventureWorks.Person.Address

WHERE City = @City

GO

The messages that are returned would be similar to this:

Command(s) completed successfully.

Using SET NOCOUNT ON and @@ROWCOUNT

This example uses SET NOCOUNT ON, but will still return the number of rows impacted by the

previous statement. This just shows that this still works.

-- not using SET NOCOUNT ON

CREATE PROCEDURE uspGetAddress @City nvarchar(30)

AS

SET NOCOUNT ON

SELECT *

FROM AdventureWorks.Person.Address

WHERE City = @City

PRINT @@ROWCOUNT

GO

The messages that are returned would be similar to this:

23

SET NOCOUNT OFF

If you wanted to turn this behavior off, you would just use the command "SET NOCOUNT

OFF".

Deleting a SQL Server stored procedure

(DROP PROCEDURE)

Overview In addition to creating stored procedures there is also the need to delete stored procedures. This

topic shows you how you can delete stored procedures that are no longer needed.

Explanation The syntax is very straightforward to drop a stored procedure, here are some examples.

Dropping Single Stored Procedure

To drop a single stored procedure you use the DROP PROCEDURE or DROP PROC command

as follows.

DROP PROCEDURE uspGetAddress

GO

-- or

DROP PROC uspGetAddress

GO

-- or

DROP PROC dbo.uspGetAddress -- also specify the schema

Dropping Multiple Stored Procedures

To drop multiple stored procedures with one command you specify each procedure separated by

a comma as shown below.

DROP PROCEDURE uspGetAddress, uspInsertAddress, uspDeleteAddress

GO

-- or

DROP PROC uspGetAddress, uspInsertAddress, uspDeleteAddress

GO

Modifying an existing SQL Server stored procedure

(ALTER PROCEDURE)

Overview When you first create your stored procedures it may work as planned, but how to do you modify

an existing stored procedure. In this topic we look at the ALTER PROCEDURE command and

it is used.

Explanation Modifying or ALTERing a stored procedure is pretty simple. Once a stored procedure has been

created it is stored within one of the system tables in the database that is was created in. When

you modify a stored procedure the entry that was originally made in the system table is replaced

by this new code. Also, SQL Server will recompile the stored procedure the next time it is run,

so your users are using the new logic. The command to modify an existing stored procedure is

ALTER PROCEDURE or ALTER PROC.

Modifying an Existing Stored Procedure

Let's say we have the following existing stored procedure: This allows us to do an exact match

on the City.

CREATE PROCEDURE uspGetAddress @City nvarchar(30)

AS

SELECT *

FROM AdventureWorks.Person.Address

WHERE City = @City

GO

Let's say we want to change this to do a LIKE instead of an equals.

To change the stored procedure and save the updated code you would use the ALTER

PROCEDURE command as follows.

ALTER PROCEDURE uspGetAddress @City nvarchar(30)

AS

SELECT *

FROM AdventureWorks.Person.Address

WHERE City LIKE @City + '%'

GO

Now the next time that the stored procedure is called by an end user it will use this new logic.