Murachs SQL Server 2016 For Developers - Searchable PDF
Murachs SQL Server 2016 For Developers - Searchable PDF
ers
Bryan Syverson
Joel Murach
10 9 8 7 6 5 4 3 2 l
ISBN-13: 978-1-890774-96-7
Content
Introduction xv
Reference aids
Appendix A How to set up your computer for this book 649
Index 661
Expanded contents V
Expanded contents
Section 1 An introduction to SQL
Chapter 1 An introduction to relational databases and SQL
An introduction to client/server systems ......................................... 4
The hardware cornponents of a client/server systern ...................................................... 4
The software cornponents of a client/server systern ........................................................ 6
Other client/server systern architectures ......................................................................... 8
An introduction to the relational database model ......................... 10
How a database table is organized ................................................................................ 10
How the tables in a relational database are related ....................................................... 12
How the colurnns in a table are defined ........................................................................ 14
How relational databases corn pare to other data rnodels .............................................. 16
An introduction to SQL and SOL-based systems ......................... 18
A brief history of SQL .................................................................................................. 18
A cornparison of Oracle, DB2, MySQL, and SQL Server. ........................................... 20
The Transact-SOL statements ......................................................... 22
An introduction to the SQL staternents ......................................................................... 22
Typical staternents for working with database objects .................................................. 24
How to query a single table ........................................................................................... 26
How to join data frorn two or rnore tables .................................................................... 28
How to add, update, and delete data in a table .............................................................. 30
SQL coding guidelines .................................................................................................. 32
How to work with other database objects ...................................... 34
How to work with views ............................................................................................... 34
How to work with stored procedures, triggers, and user-defined functions .................. 36
How to use SQL from an application program .............................. 38
Corrunon data access rnodels ........................................................................................ 38
How to use ADO.NET frorn a .NET application .......................................................... 40
Visual Basic code that retrieves data frorn a SQL Server database ............................... 42
C# code that retrieves data frorn a SQL Server database .............................................. 44
• Like all our books, this one includes hundreds of examples that range from
the simple to the complex. That way, you can quickly get the idea of how a
feature works from the simple examples, but you '11 also see how the feature
is used in the real world from the complex examples.
• Like most of our books, this one has exercises at the end of each chapter
that give you hands-on experience by letting you practice what you've
learned. These exercises also encourage you to experiment and to apply
what you've learned in new ways.
• If you page through this book, you '11 see that all of the information is
presented in "paired pages," with the essential syntax, guidelines, and
examples on the right page and the perspective and extra explanation on
the left page. This helps you learn more with less reading, and it is the ideal
reference format when you need to refresh your memory about how to do
something.
Prerequisites
Although you will progress through this book more quickly if you have
some development experience, everything you need to know about databases
and SQL is presented in this book. As a result, you don't need to have any
programming background to use this book to learn SQL.
Introduction xvii
However, if you want to use C# or Visual Basic to work with a SQL Server
database as described in chapter 19, you need to have some experience using C#
or Visual Basic to write ADO.NET code. For example, this chapter assumes you
can understand the code that's presented in chapter 20 of Murach 's C# 2015 or
chapter 16 of Murach's Visual Basic 2012.
Joel Murach
Author
joel@murach.com
Section 1
An introduction to SQL
Before you begin to learn the fundamentals of programming in SQL, you
need to understand the concepts and terms related to SQL and relational
databases. That's what you'll learn in chapter 1. Then, in chapter 2, you'll
learn about some of the tools you can use to work with a SQL Server
database. That will prepare you for using the skills you'll learn in the rest
of this book.
1
An introduction
to relational databases
and SQL
Before you can use SQL to work with a SQL Server database, you need to
be familiar with the concepts and terms that apply to database systems. In
particular, you need to understand what a relational database is. That's what
you '11 learn in the first part of this chapter. Then, you '11 learn about some of the
basic SQL statements and features provided by SQL Server.
An introduction
to client/server systems
In case you aren't familiar with client/server systems, the first two topics that
follow introduce you to their essential hardware and software components. These
are the types of systems that you 're most likely to use SQL with. Then, the last
topic gives you an idea of how complex client/server systems can be.
Database Server
-Client
Network
-Client
- Client
SQL queries
-
-
Results
I
Server software
• To store and 1nanage the databases of the client/server syste1n, each server requires
a database management system (DBMS) like Microsoft SQL Server.
• The processing that's done by the DBMS is typically referred to as back-end
processing, and the database server is referred to as the back end.
Client software
• The application software does the work that the user wants to do. This type of
software can be purchased or developed.
• The data access A P/ (application programming interface) provides the interface
between the application pro grain and the DBMS. The newest Microsoft API is
ADO.NET, which can co1n1nunicate directly with SQL Server. Older APis required
a data access 1nodel, such as ADO or DAO, plus a driver, such as OLE DB or
ODBC.
• The processing that's done by the client software is typically referred to as
front-end processing, and the client is typically referred to as the front end.
User request
- SQL queries .
-
~
_____..
□
◄
◄ Results
-
Response
I I
Client Application Server Database Server
User interface Business components DBMS
Database
Client
---
I
Web Server
I
Database Server
Web browser Web applications DBMS
Web services Database
Description
• In addition to a database server and clients, a client/server syste1n can include
additional servers, such as application servers and web servers.
• Application servers are typically used to store business components that do part
of the processing of the application. In particular, these co1nponents are used to
process database requests fro1n the user interface running on the client.
• Web servers are typically used to store web applications and web services. Web
applications are applications that are designed to run on a web server. Web services
are like business co1nponents, except that, like web applications, they are designed
to run on a web server.
• In a web-based syste1n, a web browser running on a client sends a request to a web
server over the Internet. Then, the web server processes the request and passes any
requests for data on to the database server.
• More co1nplex syste1n architectures can include two or 1nore application servers,
web servers, and database servers.
An introduction
to the relational database model
In 1970, Dr. E. F. Codd developed a model for a new type of database called
a relational database. This type of database eliminated some of the problems
that were associated with standard files and other database designs. By using the
relational model, you can reduce data redundancy, which saves disk storage and
leads to efficient data retrieval. You can also view and manipulate data in a way
that is both intuitive and efficient. Today, relational databases are the de facto
standard for database applications.
< >
Concepts
• A relational database consists of tables . Tables consist of ro ws and columns, which
can also be referred to as records andfields.
• A table is typically 1nodeled after a real-world entity, such as an invoice or a
vendor.
• A colu1nn represents so1ne attribute of the entity, such as the a1nount of an invoice
or a vendor's address.
• A row contains a set of values for a single instance of the entity, such as one invoice
or one vendor.
• The intersection of a row and a colu1nn is soineti1nes called a cell. A cell stores a
single value.
• Most tables have a primary key that uniq uely identifies each row in the table. The
pri1nary key is usually a single colu1nn, but it can also consist of two or 1nore
colu1nns. If a pri1nary key uses two or 1nore colu1nns, it's called a composite
primary key.
• In addition to pri1nary keys, so1ne database 1nanage1nent syste1ns let you define one
or 1nore non-primary keys. In SQL Server, these keys are called unique keys. Like a
pri1nary key, a non-pri1nary key uniq uely identifies each row in the table.
• A table can also be defined with one or 1nore indexes. An index provides an
efficient way to access data fro1n a table based on the values in specific colu1nns.
An index is auto1natically created for a table's pri1nary and non-pri1nary keys.
The relationship between the Vendors and Invoices tables in the database
Primary key
115 116 State of California Employment Development D... PO Box 826276 Sacramento
116 117 Suburban Propane 2874 S O,eny Ave NULL Fresno
117 118 Unocal P.0 . Box 860070 NULL Pasadena
118 119 Yesmed. Inc PO Box 2061 NULL Fresno
119 120 Dataforms/West 1617 W. Shaw Avenue Suite F Fresno
120 121 Zylka Design 3467 W Shaw Ave t1103 NULL Fresno
~
121 122 United Parcel Seivice P.0 . Box 505820 NULL Reno
.. 123 Federal Express Corporation P.O. Box 1140 Dept A Memphis y
< > ,,
""'
< >
""'·"
Foreign key
Concepts
• The tables in a relational database are related to each other through their key
colu1nns. For exa1nple, the VendorlD colu1nn is used to relate the Vendors and
Invoices tables above. The VendorlD colu1nn in the Invoices table is called aforeign
key because it identifies a related row in the Vendors table. A table 1nay contain one
or 1nore foreign keys.
• When you define a foreign key for a table in SQL Server, you can't add rows to
the table with the foreign key unless there's a 1natching pri1nary key in the related
table.
• The relationships between the tables in a database correspond to the relationships
between the entities they represent. The 1nost co1n1non type of relationship is
a one-to-many relationship as illustrated by the Vendors and Invoices tables. A
table can also have a one-to-one relationship or a many-to-many relationship with
another table.
•
(Is Identity} Yes
rn:J lnvoiceDate (smalldatetime, not n
Identity Increment 1
I!] lnvoiceT otal (money, not null)
Identity Seed 1
l!I PaymentT otal (money, not null)
.,
Indexable Yes
l!I CreditTotal (money, not null)
'f TermslD (FK. int. not null)
[ii lnvoiceDueDate (smalldatetime. n
I!] PaymentDate (smalldatetime, nul .,
< >
Description
• The data type that's assigned to a colu1nn deter1nines the type and size of the
infor1nation that can be stored in the colu1nn.
• Each colu1nn definition also indicates whether or not it can contain null values. A
null value indicates that the value of the colu1nn is unknown.
• A colu1nn can also be defined with a default value. Then, that value is used if
another value isn 't provided when a row is added to the table.
• A colu1nn can also be defined as an identity column. An identity colu1nn is a nu1neric
colu1nn whose value is generated auto1natically when a row is added to the table.
Description
• To work with any of the data 1nodels other than the relational database 1nodel, yo u 1nust
know the physical structure of the data and the relationships between the files or tables.
• Because relationships are difficult to i1nple1nent in a conventional file syste1n, redundant
data is often stored in these types of files.
• The hierarchical database 1nodel provides only for one-to-1nany relationships, called
parent/child relationships.
• The network database 1nodel can acco1runodate any type of relationship.
• Conventional files, hierarchical databases, and network databases are all 1nore efficient
than relational databases because they require fewer syste1n resources. However, the
flexibility and ease of use of relational databases typically outweigh this inefficiency.
An introduction
to SQL and SQL-based systems
In the topics that follow, you'll learn how SQL and SQL-based database
management systems evolved. In addition, you'll learn how some of the most
popular SQL-based systems compare.
Description
• SQL-92 initially provided for three levels of compliance, or levels of conformance:
entry, inter1nediate, and full. A transitional level was later added between the entry
and inter1nediate levels because the j u1np between those levels was too great.
• SQL: 1999 includes a core specification that defines the essential ele1nents for co1npliance,
plus nine packages. Each package is designed to serve a specific 1narket niche.
• Altho ugh SQL is a standard language, each vendor has its own SQL dialect, or
variant, that 1nay include extensions to the standards. SQL Server's SQL dialect is
called Transact-SQL.
How knowing "standard SQL'' helps you
• The 1nost basic SQL state1nents are the sa1ne for all SQL dialects.
• Once yo u have learned one SQL dialect, yo u can easily learn other dialects.
How knowing "standard SQL'' does not help you
• Any non-trivial application will require 1nodification when 1noved fro1n one SQL
database to another.
Description
• Oracle is typically used for large, 1nission-critical syste1ns that run on one or 1nore
Unix servers.
• DB2 is typically used for large, 1nission-critical syste1ns that run on legacy IBM
1nainfra1ne syste1ns using the z/OS or OS/390 operating syste1n.
• MySQL is a popular open-source database that runs on all 1najor operating syste1ns
and is co1n1nonly used for web applications.
• SQL Server is typically used for s1nall- to 1nediu1n-sized syste1ns that run on one
or 1nore Windows servers. However, Microsoft plans to release a version of SQL
Server that runs on Lin ux in 2017.
Description
• The SQL state1nents can be divided into two categories: the data manipulation
language (DML) that lets you work with the data in the database and the data
definition language (DDL) that lets you work with the objects in the database.
• SQL progra1n1n ers typically work with the D ML state1nents, while database
administrators (DBAs) use the DDL state1nents.
Typical statements
for working with database objects
To give you an idea of how you use the DDL statements you saw in the
previous figure, figure 1-11 presents five examples. The first statement creates an
accounts payable database named AP. This is the database that's used in many of
the examples throughout this book.
The second statement creates the Invoices table you saw earlier in this
chapter. If you don't understand all of this code right now, don't worry. You'll
learn how to code statements like this later in this book. For now, just realize that
this statement defines each column in the table, including its data type, whether
or not it allows null values, and its default value if it has one. In addition, it
identifies identity columns, primary key columns, and foreign key columns.
The third statement in this figure changes the Invoices table by adding a
column to it. Like the statement that created the table, this statement specifies all
the attributes of the new column. Then, the fourth statement deletes the column
that was just added.
The last statement creates an index on the Invoices table. In this case, the
index is for the VendorID column, which is used frequently to access the table.
Notice the name that's given to this index. This follows the standard naming
conventions for indexes, which you'll learn about in chapter 11.
Chapter 1 An introduction to relational databases and SQL 25
Description
• The REFERENCES clause for a column indicates that the column contains a
foreign key, and it names the table and column that contains the primary key.
Because the Invoices table includes foreign keys to the Vendors and Terms tables,
these tables must be created before the Invoices table.
• Because default values are specified for the PaymentTotal and CreditTotal columns,
these values don't need to be specified when a row is added to the table.
• Because the PaymentDate column accepts nulls, a null value is assumed if a value
isn't specified for this column when a row is added to the table.
< > ~,
A SELECT statement that retrieves and sorts selected columns and rows
from the Invoices table
SELECT InvoiceNumber, InvoiceDate, InvoiceTotal,
PaymentTotal, CreditTotal,
InvoiceTotal - PaymentTotal - CreditTotal AS BalanceDue
FROM Invoices
WHERE InvoiceTotal - PaymentTotal - CreditTotal > 0
ORDER BY InvoiceDate;
Concepts
• You use the SELECT statement to retrieve selected columns and rows from a base
table. The result of a SELECT statement is a result table, or result set, like the one
shown above.
• A result set can include calculated values that are calculated from columns in the
table.
• The execution of a SELECT statement is commonly referred to as a query.
A SELECT statement that joins data from the Vendors and Invoices tables
SELECT VendorName, InvoiceNumber, InvoiceDate, InvoiceTotal
FROM vendors INNER JOIN Invoices
ON vendors.vendorID = Invoices.vendorID
WHERE InvoiceTotal >= 500
ORDER BY VendorName, InvoiceTotal DESC;
Concepts
• A join lets you combine data from two or more tables into a single result set.
• The most common type of join is an inner join. This type of join returns rows from
both tables only if their related columns match.
• An outer join returns rows from one table in the join even if the other table doesn't
contain a matching row.
A statement that deletes all paid invoices from the Invoices table
DELETE FROM Invoices
WHERE InvoiceTotal - PaymentTotal - CreditTotal = 0;
Concepts
• You use the INSERT statement to add rows to a table.
• You use the UPDATE statement to change the values in one or more rows of a table
based on the condition you specify.
• You use the DELETE statement to delete one or more rows from a table based on
the condition you specify.
• The execution of an INSERT, UPDATE, or DELETE statement is often referred to
as an action query.
Warning
• Until you read chapter 7 and understand the effect that these statements can have on
the database, do not execute the statements shown above.
Coding recommendations
• Start each new clause on a new line.
• Break long clauses into multiple lines and indent continued lines.
• Capitalize the first letter of each keyword and each word in column and table names.
• End each statement with a semicolon (;).
• Use comments only for portions of code that are difficult to understand.
Description
• Line breaks, white space, indentation, and capitalization have no effect on the
operation of a statement.
• Comments can be used to document what a statement does or what specific parts of
a statement do. They are not executed by the system.
Note
• Throughout this book, SQL keywords are capitalized so they're easier to identify.
However, it's not necessary or customary to capitalize SQL keywords in your own code.
How to work
with other database objects
In addition to the tables you've already learned about, relational databases
can contain other objects. In the two topics that follow, you '11 be introduced
to four of those objects: views, stored procedures, triggers, and user-defined
functions. Then, in section 4, you '11 learn more about how to code and use these
objects.
Description
• A view consists of a SELECT state1nent that's stored with the database. Because
views are stored as part of the database, they can be 1nanaged independently of the
applications that use the1n.
• A view behaves like a virtual table. Since you can code a view na1ne anywhere
you 'd code a table na1ne, a view is so1neti1nes called a viewed table.
• Views can be used to restrict the data that a user is allowed to access or to present
data in a for1n that's easy for the user to understand. In so1ne databases, users 1nay
be allowed to access data only through views.
The result set that's created when the stored procedure is executed
VendorName VendorState VendorPhone ,..
---·--·--·----·--·--·----·
Abbey Office Furnishings (559) 555-8300
1 ........................................................................................ CA
2 American Express CA (800) 555-3344
3 ASC Signs CA NULL
4 Aztek Label CA (714) 555-9000
5 Bertelsmann Industry Svcs. Inc CA (805) 555-0584
6 BFI Industries CA (559) 555-1551
7 Bill Jones CA NULL
8 Bill Marvin Electric Inc CA (559) 555-5106
Concepts
• A stored procedure is one or more SQL statements that have been compiled and
stored with the database. A stored procedure can be started by application code on
the client.
• Stored procedures can improve database performance because the SQL statements
in each procedure are only compiled and optimized the first time they're executed.
In contrast, SQL statements that are sent from a client to the server have to be
compiled and optimized every time they're executed.
• In addition to SELECT statements, a stored procedure can contain other SQL
statements such as INSERT, UPDATE, and DELETE. It can also contain
control-of-flow language, which lets you perform conditional processing within the
stored procedure.
• A trigger is a special type of procedure that's executed when rows are inserted,
updated, or deleted from a table or when the definition of a database is changed.
Triggers are typically used to check the validity of the data in a row that's being
updated or added to a table.
• A user-defined function (UDF) is a special type of procedure that can return a value
or a table.
Figure 1-17 How to use stored procedures, triggers, and user-defined functions
38 Section 1 An introduction to SQL
Description
• To work with the data in a SQL Server database, an application uses a data access
model. For an application written in a .NET language such as C# or Visual Basic
that 1nodel is typically ADO.NET. For an application written in Java, that 1nodel is
typically JDBC (Java Database Connectivity ).
• Each data access 1nodel defines a set of objects you can use to connect to and work
with a SQL Server database. For exa1nple, both of the 1nodels shown above include
a connection object that you can use to specify the infor1nation for connecting to a
database.
• So1ne of the data access 1nodels require additional software, called drivers, to
co1n1nunicate with SQL Server. For exa1nple, JDBC requires a Java driver.
• ADO.NET, a data access 1nodel developed by Microsoft, includes its own driver so
it can co1n1nunicate directly with SQL Server.
Data reader
Select command
Database server
Connection ◄
►
Insert, Delete, or
Update command
Description
• To work with the data in a SQL Server database fro1n a .NET application, you can
use ADO.NET objects like the ones shown above.
• A .NET data provider provides the classes that let you create the objects that you
use to retrieve data fro1n a database and to store data in a database.
• To retrieve data fro1n a database, you execute a command object that contains a
SELECT state1nent. Then, the co1n1nand object uses a connection object to connect
to the database and retrieve the data. You can then read the results one row at a ti1ne
using a data reader object.
• To insert, update, or delete data in a database, you execute a co1n1nand object that
contains an INSERT, UPDATE, or DELETE state1nent. Then, the co1n1nand object
uses a connection to connect to the database and update the data. You can then
check the value that's returned to deter1nine if the operation was successful.
• After data is retrieved fro1n a database or updated in a database, the connection is
closed and the resources used by the connection are released. This is referred to as
a disconnected data architecture.
Return vendor
E.n d Fun ct ion
Description
• To issue a SQL state1nent fro1n a Visual Basic progra1n, yo u can create ADO.NET
objects like the ones shown above.
• After yo u create the ADO.NET objects, yo u have to set the properties of those
objects that define how they work. For exa1nple, the ConnectionString property
of a connection object contains the infor1nation ADO.NET needs to connect to a
database.
Figure 1-20 Visual Basic code that retrieves data from a SOL Server database
44 Section 1 An introduction to SQL
return vendor;
}
Description
• To issue a SQL state1nent fro1n a C# application, yo u can use ADO.NET objects
like the ones shown above.
Perspective
To help you understand how SQL is used from an application program,
this chapter has introduced you to the hardware and software components
of a client/server system. It has also described how relational databases are
organized and how you use some of the basic SQL statements to work with
the data in a relational database. With that as background, you 're ready to start
using SQL Server. In the next chapter, then, you'll learn how to use some of the
tools provided by SQL Server.
Terms
client primary key
server composite primary key
database server non-primary key
network unique key
client/server system index
local area network (LAN) foreign key
enterprise system one-to-many relationship
wide area network (WAN) one-to-one relationship
network operating system many-to-many relationship
database management system data type
(DBMS) null value
back end default value
application software identity column
data access API (application hierarchical database
programming interface) parent/child relationship
front end network database
SQL (Structured Query Language) object database
SQL query relational database management
query results system (RDBMS)
application server Oracle
web server DB2 (Database 2)
business component ANSI (American National Standards
web application Institute)
web service levels of compliance
web browser levels of conformance
thin client core specification
relational database package
table SQL dialect
row extension
column SQL variant
record Transact-SQL
field open-source database
cell data manipulation language (DML)
Chapter 1 An introduction to relational databases and SQL 47
Description
• To work with a SQL Server database and the data it contains, yo u can use the SQL
Server 2016 tools described above.
• After yo u install SQL Server 2016, yo u can access the Manage1nent Studio and
the Configuration Manager fro1n the Start➔ All Pro grains ➔ Microsoft SQL Server
2016 progra1n group. To start one of these tools, j ust select it fro1n that progra1n
group.
~ SQL Server Configuration Manager (Local) Name State Start Mode Log On As Process ID
BSQL Server Services 'cSQL Server (SQLEXPRESS) Running Automatic NT Service\MSSQLSSQLEXPRESS 3068
·J.· SQl Server Network Configuration (32bit
~.ti.11'1. SQL F IIF"I D L
u -text , t er aemon aunc: ... Running Manual NT Service\ MSSQLFDLauncherSS ... 3800
> ~ SQL Native Client 11.0 Configuration (321 W
·1· - SQL S R • S ·
erver eportong eMces
(SQ Running
.. Automatic NT Service\ ReportServerSSQLEXP ... 3024
) SQL Server Network Configuration
ii.. SQL N · ci·
> .~ l l OC t·
at,ve ,ent . on 1gurat1on
· ~ SQL Server Agent (SQLEXPRESS)
.,,._
Stopped Other (Boot, Syste... NT AUTHORITY\NETWORKSERVI ... 0
· · ~.!I SQL Server Browser Stopped Other (Boot. Syste... NT AUTHORITY\LOCALSERVICE 0
Description
• After yo u install SQL Server Express, the database server will start auto1natically
each ti1ne yo u start yo ur PC by default.
• To display the Configuration Manager, select Start➔ All Apps ➔ Microsoft SQL
Server 2016 ➔ Configuration Tools ➔ SQL Server Configuration Manager.
• To start or stop a service, select the service in the right pane, and use the buttons in
the toolbar to start or stop the service.
• To change the start 1node for a service, right-click on the service in the right pane,
select the Properties co1n1nand to display the properties for the service, select the
Service tab, and select the start 1node yo u want fro1n the Start Mode co1nbo box.
• By default, re1note connections are disabled for SQL Server 2016. To enable the1n,
expand the SQL Server Network Configuration node and select the Protocols node
for the server. Then, right-click on the protocol yo u want to enable and select the
Enable co1n1nand.
An introduction
to the Management Studio
Once the SQL Server database engine is installed, configured, and running,
you can use the Management Studio to connect to an instance of the SQL Server
database engine. Then, you can use the Management Studio to work with the
SQL Server database engine as described throughout this chapter.
SQL Server
Server type: [ Database Engine V
RAY-PC\Ray
Password
Remember password
SQL Server
Server type: V
Server name:
Password :
0 Remember password
Description
• When you start the Manage1nent Studio, it displays a dialog box that allows you to
specify the infor1nation that's needed to connect to the appropriate database server.
• To connect to a database server, you use the Server Na1ne co1nbo box to enter or
select a path that specifies the database server. You begin by entering the na1ne of
the co1nputer, followed by a backslash, followed by the na1ne of the SQL Server
database server.
• To connect to the SQL Server Express database engine when it's running on
your PC, you can use the localhost keyword to specify your co1nputer as the host
1nachine, and you can use "SqlExpress" to specify SQL Server Express as the
database engine.
• If you select Windows authentication, SQL Server will use the login na1ne and
password that you use for your co1nputer to verify that you are authorized to
connect to the database server.
• If you select SQL Server authentication, you '11 need to enter an appropriate
login na1ne and password. This type of authentication is typically used only with
non-Windows clients.
Description
• The Manage1nent Studio is a graphical tool that yo u can use to work with the
objects in a SQL Server database.
• If the Object Explorer isn 't displayed, yo u can use the View 1nenu to display it. You
can close this window by clicking the Close b utton at the top of the window.
• To navigate thro ugh the database objects displayed in the Object Explorer, click on
the plus (+) and 1ninus (-) signs to the left of each node to expand or collapse the
node.
• To display a 1nenu of co1n1nands for working with an object, right-click on the
object.
• If yo u want to auto1natically hide the Object Explorer, yo u can click on the
AutoHide button at the top of the Object Explorer. Then, yo u can display the
window by pointing to the Object Explorer tab that's displayed along the left side
of the Manage1nent Studio window.
Databases to attach:
MDF File Location Database Name Attach As Owner
·-·-7 C:\Pfllljram Fles\Microsofl SQL Ser... C AP AP RAY-PC\Ray
< >
L ~d.. L Remove j
"AP" databasedelails: - - - - - - - - - - - - - - - -
Original Ale Name File Type Current Ale Path Message
Connection
~
AP.mcf
- -- ~ J Data C:\Pfllljram Fles\Microsofl SQL Server\... ...
>-----~
Server: AP_~g.ldf log C:\Program Fles\Microsoft SQL Server\... ...
~calho~\SQLEXPRESS
C01Y1ection:
RAY-PC\Ray
,ti View connection properties
< >
Progress Re
Ready
OK !I Cancel
Description
• To attach a database, right-click on the Databases folder and select the Attach
co1n1nand to display the Attach Databases dialog box shown above. Then, click
on the Add button and use the resulting dialog box to select the 1ndf file for the
database. This should add both the data file a nd the log file for the database to the
Database Details pane at the botto1n of the dialog box. Finally, click OK to attach
the database.
• If you want to attach a database that doesn ' t have a log file, or if you want to create
a new log file for a database, you can re1nove the log file for the database before
you click the OK button. To do that, select the log file in the Database Details pane
and click the Re1nove button.
• To detach a database, right-click on its icon and select the Tasks ➔ Detach co1n1nand
to display the Detach Database dialog box. Then, click on the OK button.
D Copy-only backup
Backup component :
@ Database
■
• es a-id •· egroups
Destination - - - - - - - - - - - - - - - - - - -
Backupto: Disk
C \P ram Fles\ M,crosoft SQL Server\MSSQL13 SQLEXPRESS\ MSSQL\ Backu \AP bak
[ Md ...
Connection [ iemove
Server:
localhost\SQLEXPRESS
'---------------------'~ rients
Comedion:
RAY-PC\Ray
~ View connection properties
Proi,ess
Ready
OK l[ Cancel I .:
Description
• To back up a database, right-click on the database and select the Tasks ➔ Back Up
co1n1nand to display the Back Up Database dialog box. For the purposes of this
book, the default settings are usually adequate for backing up the database. As a
result, you can usually click OK to back up the database.
• To restore a database, right-click on the database and select the
Tasks ➔ Restore ➔ Database co1n1nand to display the Restore Database dialog box.
Then, click OK to restore the database. This replaces the current database with the
1nost recent backup of the database.
The Database Properties dialog box with the compatibility level options
(i Database Properties - AP - □ X
~ lectapage
,ff- General
~ Sc'l)I T m Help
Ii
±]- Ales
±f' Alegroups Collation: SQL_Latin1_General_CP1_CI_AS V
I"·--
A Ut' I ~1111 I n , ..z. , ,a
Progress
Ready
7
I OK II Cancel
I_,
=
Description
• The SQL Server 2016 database engine is backwards co1npatible and can run older
versions of SQL Server databases just as if they were running under an older
version of the SQL Server database engine.
• To set the co1npatibility level for a database to SQL Server 2016, right-click the
database, select the Properties co1n1nand, click on the Options ite1n, and select SQL
Server 2016 fro1n the Co1npatibility Level drop-down list.
Terms
',/ TermslD lnvoicelineltems
TermsDescription ',/ lnvoicelD
TermsDueDays 1/ lnvoiceSequence
AccountNo
GLAc.c,ounts
lnvoicelineltemAmount
',/ AccountNo
lnvoicelineltemDescription
AccountDescription
Description
• Database diagrams can be used to illustrate the relationships between the tables in
a database.
• To view a database diagra1n, expand the Database Diagra1ns node for the database,
and do uble-click on the diagra1n you want to display. If you get a dialog box that
says that the database doesn 't have one or 1nore of the req uired support objects for
database diagra1runing, you can select Yes to create the support objects.
• The relationships between the tables in the diagra1n appear as links, where the
endpoints of the links indicate the type of relationship. A key indicates the "one"
side of a relationship, and the infinity sy1nbo 1 (oo) indicates the "1nany" side of a
relationship.
• The pri1nary key for a table appears as a key icon that's displayed to the left of the
colu1nn or colu1nns that define the pri1nary key.
• You can use standard Windows techniques to 1nove and size the tables in a database
diagra1n to 1nake the diagra1n easier to understand.
Description
• To view the colu1nns for a table, expand the Tables node, expand the node for
the table, and expand the Colu1nns node. This displays the colu1nns in the Object
Explorer.
• To 1nodify the colu1nns for a table, expand the Tables node, right-click on the
table, and select the Design co1n1nand to display the table in a Table Designer tab.
Then, you can click on the row selector to the left of the colu1nn na1ne to display
the properties for the colu1nn in the Colu1nn Properties tab at the botto1n of the
window. If necessary, you can use the Table Designer tab or the Colu1nn Properties
tab to 1nodify the properties for a colu1nn.
Description
• To view the data for a table, expand the Tables node, right-click on the table, and
select the Select Top 1000 Rows co1n1nand. This auto1natically generates and
executes a query that displays the top 1000 rows of the table.
• To 1nodify the data for a table, expand the Tables node, right-click on the table, and
select the Edit Top 200 Rows co1n1nand. This displays the top 200 rows of the table
in an editable grid. Then, you can use the grid to insert, update, or delete data fro1n
the table.
~ SQLQueryl.sql - I calhost\ SQLEXPRESS.AP (RAV-PC\Ray (54 - Microsoft SQL Server Management Studio □ X
File Edit View Q ery Project Debug Tools Win w Help
( ~ • _J w Q '1 .New Query t'J @; " ~ ~ ~ "') • J:11 • -_ ~ ►
..,
___, = .
• l'".811 :.:
Description
• To open a new Query Editor window, click on the New Query button in the toolbar.
To open a saved query in a Query Editor window, click on the Open button in the
toolbar as described in figure 2-13.
• To select the database that you want to work with, use the Available Databases
co1nbo box in the toolbar.
• To enter a SQL state1nent, type it into the Query Editor window.
• As you enter a SQL state1nent, the lntelliSense feature auto1natically displays
completion lists that help you co1nplete the state1nent. To select an ite1n fro1n a list,
use the Up or Down arrow key to select the ite1n and press the Tab key. To hide a
list, press the Esc key. To 1nanually display a list, press Alt+Right-arrow or Ctrl+J.
• To execute a SQL state1nent, press the F5 key or click the Execute button in the
toolbar. If the state1nent retrieves data, the data is displayed in the Results tab that's
displayed at the botto1n of the Query Editor. Otherwise, a 1nessage is displayed in
the Messages tab that's displayed at the botto1n of the Query Editor.
tab. If you execute an action query, the Messages tab is displayed instead of the
Results tab. This tab will contain an indication of the number of rows that were
affected by the query. The Messages tab is also used to provide error information,
as you'll see in figure 2-12.
Object Explorer T YX SQLQuery2.sql - lo ...P (RAY-PC\Ray (53)) SQLQuery1.sql - lo...P (RAY-PC\ Ray (54))• X
1 - SELECT InvoiceNu11, InvoiceDate , InvoiceTotal, PaymentTota l , Cred i t Tota l ,
2 InvoiceTotal - PaymentTot a l - Cr editTota l AS Ba l a nceDue
El U) localhost\ SQLEXPRESS (SQL Server 13.0.900 - 3 FROM Invoices "
8 L:J
1B
Databases
System Databases
4 1 l~HERE InvoiceTotal - PaymentTota l - Cr ed i tTota l > 0
5 ORDER BY Invoice Da t e ;
8 (j AP
B Database Diagrams
cg
dbo.DIAGRAM1
El Tables
1±1 L:J System Tables
Ill FileTables
Ill 1:1 dbo.ContactUpdates
1±1 1:1 dbo.GLAccounts
1±1 1:1 dbo.lnvoiceArchive "
1±1 1:1 dbo.lnvoicel ineltems 100 % • < >
Ill 1:1 dbo.lnvoices o) Messages
Ill 1:1 dbo.Terms Msg 207, Le ve l 16, State 1 , Line 1
It) 1:1 dbo.Vendors Inva l id column name · I nvoic eNum· .
1±1 D Views
1±1 L] Synonyms
Ill Programmability
Ill Service Broker
1±1 Storage
1±1 D Security
1±1 L:J Security
1±1 Server Objects
Ill Replication 100 % •
"
1±1 ~ Management
< > J._ Query completed with error~. localhost\SQLEXPRESS (13.0 ... RAY-PC\Ray (54) AP 00:00:00 0 rows
Description
• Befo re you execute a state1nent, IntelliSense 1nay display wavy red underlining
beneath the parts of a SQL state1nent that contain errors.
• If an error occurs during the execution of a SQL state1nent, the Manage1nent Studio
displays an error 1nessage in the Messages tab of the Query Editor.
• Most errors are caused by incorrect syntax and can be detected and corrected
without any additional assistance. If not, you can get 1nore infor1nation about an
error by looking it up in the docu1nentation fo r SQL Server.
Open !I
J.... Cancel I
Description
• To save a query, click the Save button in the toolbar or press Ctrl+S. Then, if necessary,
use the Save File As dialog box to specify a file na1ne for the query.
• To open a query, click the Open button in the toolbar or press Ctrl+O. Then, use the
Open File dialog box shown above to locate and open the query.
• To save all open queries, click the Save All button in the toolbar. Then, if necessary,
use the Save File As dialog box to specify a file na1ne for any queries that haven 't
already been na1ned.
• To switch between open queries, click on the tab for the query you want to display.
If you can 't see the tab, click on the drop-down arrow that's displayed to the right
of the Query Editor tabs, and select the query fro1n the list of active files.
• To cut, copy, and paste code fro1n one query to another, use the standard Windows
techniques.
I OK I Cancel
.,'
-""'
Description
• Yo u can use the Query Designer to build si1nple queries quickly and easily.
However, yo u 1nay not be able to create 1nore co1nplex queries this way.
• To display the Query Designer, right-click on a blank Query Editor window and
select the Design Query in Editor co1n1nand. Then, yo u can use the Query Designer
window to create the query. When yo u click the OK button, the query will be
inserted into the Query Editor where yo u can edit and run it just as yo u wo uld any
other query.
• To 1nodify a query with the Query Designer, select the query, right-click on the
selection, and select the Design Query in Editor co1n1nand.
f- ➔ 0 I8 ms<''l.microsoft.com ren·US/1ibrary/ms189499.aspx
=
■ Microsoft Sign In MSJN suoscriptior s Get tools
••• > Microsoft SQL Server Language Reference > Transact· SQL Reference (Data base Engine) > Data Manipulation Language (DML) Statements •.. •
Search Condition (Transact·SQL) THIS TOPIC APPLIES TO: 0 SQL Server [starting with 2008) 0 Azure SQL Database
0 Azure SQL Data Warehouse O Parallel Data Warehouse
• SELECT (Transact·SQL)
Retrieves rows from the database and enables the selection of o ne or many rows or columns IN THIS ARTICLE
SELECT Clause (Transact-SQL) from one or many tables in SQL Server. The full syntax of the SELECT statement is co mplex,
but the main clauses can be summarized as: I Syntax
SELECT Exa mples [Transact-SQL) Remarks
[ WITH { [ XMLNAMESPACES ,] [ <common_table_expression> J)]
Permissions
FOR Oause (Transact-SQL) SELECT select_list I INTO new_table J
Examples: Azure SQL
GROUP BY (Transact-SQL) [ FROM table_source J [ WHERE search_condition J Data Warehouse Public
Preview and Parallel
[ GROUP BY group_by_expression J Data w arehouse
HAVING (Transact-SOL)
[ HAVING seorch_condition J See Also
INTO Clause (Transact-SQL)
[ ORDER BY order_expression [ ASC ) DESC JJ
ORDER BY Clause (Transact-SQL)
The UNION. EXCEPT and INTERSECT operators can be used between queries to combine or
OVER Clause (Transact•SQL) compare their results into one result set.
Description
• To view the official docu1nentation for SQL Server 2016, you can start a web
browser and navigate to the Microsoft Developer Network (MSDN) website. You
can usually find that site by searching for "SQL Server docu1nentation".
• The left colu1nn of the website displays the table of contents.
• To use the table of contents, click on a topic to display it in the 1niddle pane.
• To use full-text search, click the search icon that looks like a 1nagnifying glass,
enter the text into the Search text box, and press the Enter key. Then, select the
topic that you want fro1n the resulting list of topics.
Perspective
In this chapter, you learned how to use the tools that you need to begin
learning about SQL. To begin, you learned how to start and stop the database
server. Then, you learned how to use the Management Studio to connect to
the database server, to attach a database, to view the definition of a database,
and to execute SQL statements against that database. Finally, you learned how
to view the official documentation for SQL Server. With that as background,
you 're ready to go on to the next chapter where you '11 start learning the details
of coding your own SQL statements.
Before you go on to the next chapter, though, I recommend that you install
SQL Server Express and the Management Studio on your system as described
in appendix A. In addition, I recommend that you download and install the
databases and sample code that come with this book as described in appendix
A. That way, you can begin experimenting with these tools. In particular, you
can enter and execute queries like the ones described in this chapter. Or, you
can open any of the queries shown in this chapter, view their code, and execute
them.
For now, though, focus on the mechanics of using the Management Studio
to enter and execute queries, and don't worry if you don't understand the
details of how the SQL statements are coded. You '11 learn the details for coding
SQL statements in the chapters that follow. In the next chapter, for example,
you 'II learn the details for coding a SELECT state1nent that retrieves data fro1n
a single table.
Terms
database server schema
client tools attach a database
database engine detach a database
SQL Server 2016 Express Edition restore a database
SQL Server Express database diagram
SQL Server Management Studio Query Editor
SQL Server Configuration Manager IntelliSense feature
SQL Server Surface Area completion list
Configuration Query Designer
Microsoft Developer Network
(MSDN)
Chapter 2 How to use the Management Studio 81
Exercises
1. Use the Management Studio to view all of the databases that are available
from the server. If the AP database isn't available, follow the procedure in
appendix A to create it. Then, view the tables that are available from the AP
database. Finally, view the columns that are available from the Invoices table.
Note the primary and foreign keys of this table and the definition for each
column.
2. Right-click on the Vendors table and select the Design command to display
the Vendors table in a Table Designer tab. Review the properties for each
column in this table. In particular, note that the VendorID column is defined as
an identity column.
3. Use the Management Studio to view the diagram for the AP database. Then,
organize the tables and connecting lines in the diagram so they are easy to read.
(Hint: You can use the Autosize Selected Tables button and the Arrange Tables
button in the toolbar to help you do this.) Finally, review the information that's
contained in each table, note the primary key of each table, and try to identify
the relationships between the tables.
4. Open a new Query Editor window and then enter this SELECT statement:
SELECT VendorName, VendorState
FROM Vendors
WHERE vendorState = 'CA'
Press F5 to execute the query and display the results. If an error is displayed,
correct the problem before you continue. (Hint: If you get an error message
that indicates that 'Vendors' isn't a valid object, the AP database isn't the
current database. To fix this error, select the AP database from the Available
Databases combo box.) Then, save the query with a name of VendorslnCA
and close it.
5. Open the query named VendorslnCA that you saved in exercise 4. Then, click
the Execute Query toolbar button to execute it. (Hint: You may need to select
the AP database from the Available Databases combo box.)
6. Look up information about the Query Editor on the MSDN website. The
easiest way to do this is to display the part of the MSDN website and use the
full-text search to look up "query editor". Continue experimenting with the
MSDN website until you feel comfortable with it.
Section 2
An introduction
to the SELECT statement
To help you learn to code SELECT statements, this chapter starts by
presenting its basic syntax. Next, it presents several examples that will give you
an idea of what you can do with this statement. Then, the rest of this chapter will
teach you the details of coding this statement.
Description
• Yo u use the basic SELECT state1nent shown above to retrieve the colu1nns
specified in the SELECT clause fro1n the base table specified in the FROM clause
and store the1n in a result set.
• The WHERE clause is used to filter the rows in the base table so that only those
rows that 1natch the search condition are included in the result set. If yo u 01nit the
WHERE clause, all of the rows in the base table are included.
• The search condition of a WHERE clause consists of one or 1nore Boolean
expressions, or predicates, that result in a value of True, False, or Unknown. If the
co1nbination of all the expressions is True, the row being tested is included in the
result set. Otherwise, it's not.
• If you include the ORDER BY clause, the rows in the result set are sorted in the
specified sequence. Otherwise, the rows are returned in the sa1ne order as they
appear in the base table. In 1nost cases, that 1neans that they're returned in pri1nary
key sequence.
Note
• The syntax shown above does not include all of the clauses of the SELECT
state1nent. Yo u'll learn abo ut the other clauses later in this book.
A SELECT statement that retrieves all the data from the Invoices table
SELECT*
FROM Invoices;
Invoice ID VendorlD Invoice Number InvoiceDate InvoiceTotal Payment Total Cred~Total I\
< >
( 114 rows )
( 114 rows )
ORDER BY InvoiceDate;
lnvoiceNumber lnvoiceDate InvoiceTotal
1 l
l._25022111 ............... 201&-01-01 00:00:00 6.oo
2 P02-&8D77S7 2016-01-03 00:00:00 &56.92
3 21-4748363 2016-01-03 00:00:00 9.95
4 4-321-2596 2016-01-05 00:00:00 10.00
(101 rows )
"
Description
• Use SELECT* only when yo u need to retrieve all of the colu1nns fro1n a table.
Otherwise, list the na1nes of the colu1nns yo u need.
• An expression is a co1nbination of colu1nn na1nes and operators that evaluate to a
single value. In the SELECT clause, yo u can code arith1netic expressions, string
expressions, and expressions that include one or 1nore functions.
• After each colu1nn specification, yo u can code an AS clause to specify the na1ne fo r
the colu1nn in the result set. See figure 3-4 fo r details.
Note
• The ALL and DISTINCT keywords and the TOP clause let yo u control the nu1nber
of rows that are returned by a query. See figures 3-8 and 3-9 fo r details.
Two SELECT statements that name the columns in the result set
A SELECT statement that uses the AS keyword (the preferred technique)
SELECT InvoiceNumber AS [Invoice Number], InvoiceDate AS Date,
InvoiceTotal AS Total
FROM Invoices;
A SELECT statement that uses the equal operator (an older technique)
SELECT [Invoice Number] = InvoiceNumber, Date= InvoiceDate,
Total= InvoiceTotal
FROM Invoices;
Description
• By default, a column in the result set is given the same name as the column in the
base table. If that's not what you want, you can specify a column alias or substitute
name for the column.
• One way to name a column is to use the AS phrase as shown in the first example
above. Although the AS keyword is optional, I recommend you code it for
readability.
• Another way to name a column is to code the name followed by an equal sign and
the column specification as shown in the second example above. This syntax is
unique to Transact-SQL.
• It's generally considered a good practice to specify an alias for a column that
contains a calculated value. If you don't, no name is assigned to it as shown in the
third example above.
• If an alias includes spaces or special characters, you must enclose it in double
quotes or brackets ([]). That's true of all names you use in Transact-SQL. SQL
Server also lets you enclose column aliases in single quotes for compatibility with
earlier releases.
Description
• A string expression can consist of one or 1nore character colu1nns, one or 1nore
literal values , or a co1nbination of character colu1nns and literal values.
• The colu1nns specified in a string expression 1nust contain string data (that 1neans
they're defined with the char or varchar data type).
• The literal values in a string expression also contain string data, so they can be
called string literals or string constants. To create a literal value, enclose one or
1nore characters within single quotation 1narks (').
• You can use the concatenation operator (+) to co1nbine colu1nns and literals in a
string expression.
• You can include a single quote within a literal value by coding two single quotation
1narks as shown in the third exa1nple above.
Description
• Unless parentheses are used, the operations in an expression take place fro1n left to
right in the order ofprecedence. For arith1netic expressions, 1nultiplication, division,
and 1nodulo operations are done first, followed by addition and subtraction.
• Whenever necessary, you can use parentheses to clarify or override the sequence of
operations. Then, the operations in the innerrnost sets of parentheses are done first,
followed by the operations in the next sets, and so on.
1
(No column name)
__ .......................................................................,
LInvoice:_#9&9319-457._dated_01/07/ 16for sJ,813.33_..)
2 Invoice: #263253241. dated 01 / 14/ 16 for S40.20
Description
• An expression can include any of the functions that are supported by SQL Server. A
function perfor1ns an operation and returns a value.
• A function consists of the function na1ne, followed by a set of parentheses that
contains any parameters, or arguments, required by the function. If a function
requires two or 1nore argu1nents, yo u separate the1n with co1n1nas.
• For 1nore infonnation on using functions, see chapter 9.
(122 rows)
( 53 rows)
Description
• The DISTINCT keyword prevents duplicate (identical) rows fro1n being included in
the result set. It also causes the result set to be sorted by its first colu1nn.
• The ALL keyword causes all rows 1natching the search condition to be included in
the result set, regardless of whether rows are duplicated. Since this is the default,
it's a co1n1non practice to 01nit the ALL keyword.
• To use the DISTINCT or ALL keyword, code it i1n1nediately after the SELECT
keyword as shown above.
Figure 3-8 How to use the DIST INCT keywo rd to eliminate duplicate rows
102 Section 2 The essential SQL skills
A SELECT statement with a TOP clause and the WITH TIES keyword
SELECT TOP 5 WITH TIES vendorID, InvoiceDate
FROM Invoices
ORDER BY InvoiceDate ASC;
Vendorl D Invoice Date
............................ ,
1 . ..................,......... 2015-12-08 00:00:00
....122
2 123 2015-12-10 00:00:00
3 123 2015-12-13 00:00:00 I
4 123 2015-12-16 00:00:00
5 123 2015-12-16 00:00:00
6 123 2015-12-16 00:00:00
Description
• You can use the TOP clause within a SELECT clause to li1nit the nu1nber of rows
included in the res ult set. When you use this clause, the first n rows that 1neet the
search condition are included, where n is an integer.
• If you include PERCENT, the first n percent of the selected rows are included in
the result set.
• If you include WITH TIES, additional rows will be included if their values 1natch,
or tie, the values of the last row.
• You should include an ORDER BY clause whenever you use the TOP keyword.
Otherwise, the rows in the result set will be in no particular sequence.
Figure 3-9 How to use the TOP clause to return a subset of selected rows
104 Section 2 The essential SQL skills
Description
• You can use a co1nparison operator to co1npare any two expressions that result in
like data types. Although unlike data types 1nay be converted to data types that can
be co1npared, the co1nparison 1nay produce unexpected results.
• If a co1nparison results in a True value, the row being tested is included in the result
set. If it's False or Unknown, the row isn 't included.
• To use a string literal or a date literal in a coinparison, enclose it in quotes. To use a
nu1neric literal, enter the nu1nber without quotes.
• Character co1nparisons perfor1ned on SQL Server databases are not case-sensitive.
So, for exa1nple, ' CA' and 'Ca ' are considered equivalent.
OR InvoiceTotal > 5 00
AND InvoiceTotal - PaymentTotal - CreditTotal > 0
Invoice Number Invoice Date Invoice Total Balance [l)ue
1 !t ......P02-&8DnS7 ! 2016-01-03 00:00:00
....,....,........,............,.....,...;
&56.92 0.00
2 21-474&363 2016-01-03 00:00:00 9.95 0.00
3 4-321 -2596 2016-01-05 00:00:00 10.00 0.00
4 963253242 2016-01-06 00:00:00 104.00 0.00
( 1 00 r ows )
( 11 r ows )
Description
• Yo u can use the AND and OR logical operators to create compound conditions that
consist of two or 1nore conditions. Yo u use the AND operator to specify that the
search 1nust satisfy both of the conditions, and yo u use the OR operator to specify
that the search 1nust satisfy at least one of the conditions.
• Yo u can use the NOT operator to negate a condition. Because this operator can
1nake the search condition difficult to read, yo u should rephrase the condition if
possible so it doesn 't use NOT.
• When SQL Server evaluates a co1npound condition, it evaluates the operators in this
sequence: ( 1) NOT, (2) AND, and (3) OR. Yo u can use parentheses to override this
order of precedence or to clarify the sequence in which the operations will be evaluated.
Figure 3- 11 How to use the AND, OR, and NOT logical operators
108 Section 2 The essential SQL skills
Description
• You can use the IN phrase to test whether an expression is equal to a value in a list
of expressions. Each of the expressions in the list must evaluate to the same type of
data as the test expression.
• The list of expressions can be coded in any order without affecting the order of the
rows in the result set.
• You can use the NOT operator to test for an expression that's not in the list of
expressions.
• You can also compare the test expression to the items in a list returned by a subquery
as illustrated by the third example above. You '11 learn more about coding subqueries
in chapter 6.
Description
• You can use the BETWEEN phrase to test whether an expression falls within a
range of values. The lower limit must be coded as the first expression, and the
upper limit must be coded as the second expression. Otherwise, the result set will
be empty.
• The two expressions used in the BETWEEN phrase for the range of values are
inclusive. That is, the result set will include values that are equal to the upper or
lower limit.
• You can use the NOT operator to test for an expression that's not within the given
range.
Wildcard symbols
Symbol Description
% Matches any string of zero or n1ore characters.
Matches any single character.
[ ] Matches a single character listed within the brackets.
[ - ] Matches a single character within the given range.
[ A ] Matches a single character not listed after the caret.
Description
• Yo u use the LIKE operator to retrieve rows that 1natch a string pattern, called
a mask. Within the 1nask, yo u can use special characters, called wildcards, that
deter1nine which values in the colu1nn satisfy the condition.
• Yo u can use the NOT keyword before the LIKE keyword. Then, only those rows
with values that don ' t 1natch the string pattern will be included in the result set.
• Most LIKE phrases will significantly degrade perfor1nance co1npared to other types
of searches, so use the1n only when necessary.
not available, or unknown. When you allow null values in one or more columns,
you need to know how to test for them in search conditions. To do that, you can
use the IS NULL clause as shown in figure 3-15.
This figure uses a table named NullSample to illustrate how to search for
null values. This table contains two columns. The first column, InvoiceID, is
an identity column. The second column, InvoiceTotal, contains the total for
the invoice, which can be a null value. As you can see in the first example, the
invoice with InvoiceID 3 contains a null value.
The second example in this figure shows what happens when you retrieve
all the invoices with invoice totals equal to zero. Notice that the row that has a
null invoice total isn't included in the result set. Likewise, it isn't included in the
result set that contains all the invoices with invoices totals that aren't equal to
zero, as illustrated by the third example. Instead, you have to use the IS NULL
clause to retrieve rows with null values, as shown in the fourth example.
You can also use the NOT operator with the IS NULL clause as illustrated
in the last example in this figure. When you use this operator, all of the rows that
don't contain null values are included in the query results.
Chapter 3 How to retrieve data from a single table 115
Description
• A null value represents a value that's unknown, unavailable, or not applicable. It
isn 't the sa1ne as a zero, a blank space (' '), or an e1npty string (").
• To test for a null value, you can use the IS NULL clause. You can also use the NOT
keyword with this clause to test for values that aren 't null.
• The definition of each colu1nn in a table indicates whether or not it can store null
values. Before you work with a table, you should identify those colu1nns that allow
null values so you can acco1n1nodate the1n in your queries.
Description
• The ORDER BY clause specifies how you want the rows in the result set sorted.
You can sort by one or 1nore colu1nns, and you can sort each colu1nn in either
ascending (ASC) or descending (DESC) sequence. ASC is the default.
• By default, in an ascending sort, nulls appear first in the sort sequence, followed
by special characters, then nu1nbers, then letters. Although you can change this
sequence, that's beyond the scope of this book.
• You can sort by any colu1nn in the base table regardless of whether it's included
in the SELECT clause. The exception is if the query includes the DISTINCT
keyword. Then, you can only sort by colu1nns included in the SELECT clause.
1 !:...................................................................................
Dristas Groom & McCormick 1 Fresno, CA 93720 :
Description
• The ORDER BY clause can include a colu1nn alias that's specified in the SELECT
clause.
• The ORDER BY clause can include any valid expression. The expression can refer
to any colu1nn in the base table, even if it isn't included in the result set.
• The ORDER BY clause can use nu1nbers to specify the colu1nns to use for sorting.
In that case, 1 represents the first colu1nn in the result set, 2 represents the second
colu1nn, and so on.
Description
• The OFFSET clause specifies the nu1n ber of rows that should be skipped before
rows are returned fro1n the result set.
• The FETCH clause specifies the nu1n ber of rows that should be retrieved after
skipping the specified nu1n ber of rows. If yo u 01nit the FETCH clause, all of the
rows to the end of the result set are retrieved.
• The nu1n ber of rows to be skipped and retrieved can be specified as an integer or an
expression that results in an integer that is greater than or equal to zero.
• The OFFSET and FETCH clauses are 1n ost useful when a client application needs
to retrieve one page of data at a ti1n e.
Perspective
The goal of this chapter has been to teach you the basic skills for coding
SELECT statements. You'll use these skills in almost every SELECT statement
you code. As you '11 see in the chapters that follow, however, there's a lot more
to coding SELECT statements than what's presented here. In the next three
chapters, then, you '11 learn additional skills for coding SELECT statements.
When you complete those chapters, you'll know everything you need to know
about retrieving data from a SQL Server database.
Terms
keyword order of precedence
filter function
Boolean expression parameter
predicate argument
expression date literal
column alias comparison operator
substitute name logical operator
string expression compound condition
concatenate subquery
concatenation operator string pattern
literal value mask
string literal wildcard
string constant Full-Text Search
arithmetic expression null value
arithmetic operator nested sort
Chapter 3 How to retrieve data from a single table 123
Exercises
1. Write a SELECT statement that returns three columns from the Vendors table:
VendorContactFName, VendorContactLName, and VendorName. Sort the
result set by last name, then by first name.
2. Write a SELECT statement that returns four columns from the Invoices table,
named Number, Total, Credits, and Balance:
Number Column alias for the lnvoiceNumber column
Total Column alias for the lnvoiceTotal column
Credits Sum of the PaymentTotal and CreditTotal columns
Balance lnvoiceTotal minus the sum of PaymentTotal and CreditTotal
Use the AS keyword to assign column aliases.
3. Write a SELECT statement that returns one column from the Vendors table
named Full Name. Create this column from the VendorContactFName and
VendorContactLName columns. Format it as follows: last name, comma, first
name (for example, "Doe, John"). Sort the result set by last name, then by first
name.
4. Write a SELECT statement that returns three columns:
lnvoiceTotal From the Invoices table
10% 10% of the value of lnvoiceTotal
Plus 10% The value of InvoiceTotal plus 10%
(For example, if lnvoiceTotal is 100.0000, 10% is 10.0000, and Plus 10% is
110.0000.) Only return those rows with a balance due greater than 1000. Sort
the result set by lnvoiceTotal, with the largest invoice first.
5. Modify the solution to exercise 2 to filter for invoices with an lnvoiceTotal
that's greater than or equal to $500 but less than or equal to $10,000.
6. Modify the solution to exercise 3 to filter for contacts whose last name begins
with the letter A, B, C, or E.
7. Write a SELECT statement that determines whether the PaymentDate column
of the Invoices table has any invalid values. To be valid, PaymentDate must be
a null value if there's a balance due and a non-null value if there's no balance
due. Code a compound condition in the WHERE clause that tests for these
conditions.
4
How to retrieve data
from two or more tables
In the last chapter, you learned how to create result sets that contain data from
a single table. Now, this chapter will show you how to create result sets that
contain data from two or more tables. To do that, you can use either a join or a
union.
( 114 r ows)
Description
• A join is used to co1nbine colu1nns fro1n two or 1nore tables into a result set based
on the join conditions you specify. For an inner join, only those rows that satisfy
the join condition are included in the result set.
• A join condition na1nes a colu1nn in each of the two tables involved in the join and
indicates how the two colu1nns should be cornpared. In 1nost cases, you use the
equal operator to retrieve rows with 1natching colu1nns. However, you can also use
any of the other co1nparison operators in a join condition.
• In 1nost cases, you '11 join two tables based on the relationship between the pri1nary
key in one table and a foreign key in the other table. However, you can also join
tables based on relationships not defined in the database. These are called ad hoc
relationships.
• If the two colu1nns in a join condition have the sa1ne na1ne, you have to qualify
the1n with the table na1ne so that SQL Server can distinguish between the1n. To
code a qualified column name, type the table na1ne, followed by a period, followed
by the colu1nn na1ne.
Notes
• The INNER keyword is optional and is seldo1n used.
• This syntax for coding an inner join can be referred to as the explicit syntax. It is
also called the SQL-92 syntax because it was introduced by the SQL-92 standards.
• You can also code an inner join using the implicit syntax. See figure 4-7 for 1nore
infor1natio n.
( 11 rows)
(6 rows)
Description
• Correlation names are te1nporary table na1nes assigned in the FROM clause. You
can use correlation na1nes when long table na1nes 1nake qualified colu1nn na1nes
long or confusing. A correlation na1ne can also be called a table alias.
• If you assign a correlation na1ne to a table, you 1n ust use that na1ne to refer to the
table within your query. You can 't use the original table na1ne.
• Although the AS keyword is optional, I reco1n1nend you use it because it 1nakes the
FROM clause easier to read.
• You can use a correlation na1ne for any table in a join without using correlation
na1nes for all of the other tables.
• Use correlation na1nes whenever they si1nplify or clarify the query. Avoid using
correlation na1nes when they 1nake a query 1nore confusing or difficult to read.
(37 rows)
Description
• A fully-qualified object name is 1nade up of fo ur parts : the server na1ne, the
database na1ne, the sche1na na1ne (typically dbo ), and the na1ne of the object
(typically a table). This syntax can be used when joining tables fro1n different
databases or databases on different servers.
• If the server or database na1ne is the sa1ne as the current server or database na1ne,
or if the sche1na na1ne is dbo or the na1ne of the user's default sche1na, yo u can
01nit that part of the na1ne to create a partially-qualified object name. If the 01nitted
na1ne falls between two other parts of the na1ne, code two periods to indicate that
the na1ne is 01nitted.
• Before yo u can specify a server na1ne, yo u 1nust add a linked server to the
current instance of the server. To do that, yo u can use the stored procedure na1ned
sp_addlinkedserver. Then, yo u can specify the na1ne of the linked server. To re1nove
a linked server, yo u can use the stored proced ure na1ned sp_dropserver.
To remove a linked server, you can use the stored procedure named
sp_dropserver. For more information about working with linked servers, look up
"Linked Servers (Database Engine)" in the documentation for SQL Server.
The same join with the second condition coded in a WHERE clause
SELECT InvoiceNumber, InvoiceDate,
InvoiceTotal, InvoiceLineitemAmount
FROM Invoices JOIN InvoiceLineitems AS Lineitems
ON Invoices.InvoiceID = Lineitems.InvoiceID
WHERE Invoices.InvoiceTotal > Lineitems.InvoiceLineitemAmount
ORDER BY InvoiceNumber;
Description
• A join condition can include two or 1nore conditions connected by AND or OR
operators.
• In 1nost cases, yo ur code will be easier to read if yo u code the join condition in the
ON expression and search conditions in the WHERE clause.
A self-join that returns vendors from cities in common with other vendors
SELECT DISTINCT Vendorsl.VendorName, Vendorsl.VendorCity,
Vendorsl.VendorState
FROM Vendors AS Vendorsl JOIN Vendors AS Vendors2
ON (Vendorsl.VendorCity = Vendors2.VendorCity ) AND
(Vendorsl.VendorState = Vendors2.VendorState ) AND
(Vendorsl.VendorID <> Vendors2.VendorID )
ORDER BY Vendorsl.VendorState, Vendorsl.VendorCity;
(84 rows)
Description
• A self-join is a join that joins a table with itself.
• When yo u code a self-join, yo u 1nust use correlation na1nes for the tables, and yo u
1nust qualify each colu1nn na1ne with the correlation na1ne.
• Self-joins freq uently include the DISTINCT keyword to eli1ninate duplicate rows.
( 11 row s )
( 11 row s )
2 Cardinal Business Media. Inc. 134116 2016-03-28 00:00:00 90.36 Direct Mail Advertising
3 Data Reproductions Corp 39104 2016-03-10 00:00:00 85.31 Book Printing Costs
4 Federal Express Corporation 263253270 2016-03-22 00:00:00 67.92 Freight
5 Federal Express Corporation 263253268 2016-03-21 00:00:00 59.97 Freight
6 Federal Express Corporation 963253264 2016-03-18 00:00:00 52.25 Freight
7 Federal Express Corporation 263253273 2016-03-22 00:00:00 30.75 Freight
=
( 11 rows )
Description
• You can think of a 1nulti-table join as a series of two-table joins proceeding fro1n
left to right. The first two tables are joined to produce an interim result set or
interim table. Then, the interi1n table is joined with the next table, and so on.
Figure 4-6 Inner joins that join more than two tables
138 Section 2 The essential SQL skills
2 Cardinal Business Media. Inc. 134116 2016-03-28 00:00:00 90.36 Direct Mail Advertising
3 Data Reproductions Corp 39104 2016-03-10 00:00:00 85.31 Book Printing Costs
4 Federal Express Corporation 263253270 2016-03-22 00:00:00 67.92 Freight -
5 Federal Express Corporation 263253268 2016-03-21 00:00:00 59.97 Freight
6 Federal Express Corporation 963253264 2016-03-18 00:00:00 52.25 Freight
7 Federal Express Corporation 263253273 2016-03-22 00:00:00 30.75 Freight
=
Description
• Instead of coding a join condition in the FROM clause, you can code it in the
WHERE clause along with any search conditions. Then, you si1nply list the tables
you want to join in the FROM clause separated by co1n1nas.
• This syntax for coding joins is referred to as the implicit syntax, or the theta syntax.
It was used prior to the SQL-92 standards, which introduced the explicit syntax.
• If you 01nit the join condition fro1n the WHERE clause, a cross join is perfor1ned.
You ' 11 leam about cross joins later in this chapter.
(202 rows)
Description
• An outer join retrieves all rows that satisfy the join condition, plus un1n atched rows
in one or both tables.
• In 1n ost cases, you use the equal operator to retrieve rows with 1n atching colu1n ns.
However, you can also use any of the other co1nparison operators.
• When a row with un1n atched colu1n ns is retrieved, any colu1n ns fro1n the other
table that are included in the result set are given null values.
Notes
• The OUTER keyword is optional and typically 01nitted.
• Prior to SQL Server 2005, you could also use the i1n plicit syntax to code left outer
and right outer joins. To do that, you listed the tables to be joined in the FROM
clause, and you used the *= (left) and =* (right) operators in the WHERE clause to
specify the join condition.
-
SELECT DeptName, Departments.DeptNo, DeptName DeptNo Last Name
........................................
LastName 1 [..Accounting........J 1 Hernandez
FROM Departments LEFT JOIN Employees 2 Payroll 2 Smith
ON Departments.DeptNo - 3 Payroll 2 Simonian
Employees.DeptNo; 4 Payroll 2 Aaronsen
5 Operations 3 NULL
6 Personnel 4 Jones
7 Personnel 4 O'Leary
8 Maintenance 5 Hardy
=
7 Maintenance 5 Hardy
8 Personnel 4 O'Leary
9 NULL 6 Locario
Description
• Fro1n these exa1nples, you can see that none of the e1nployees in the E1nployees
table work in the Operations depart1nent, and two of the e1nployees (Watson and
Locario) work in a depart1nent that doesn 't exist in the Depart1nents table.
A SELECT statement that joins the three tables using left outer joins
SELECT DeptName, LastName, ProjectNo
FROM Departments
LEFT JOIN Employees
ON Departments.DeptNo - Employees.DeptNo
LEFT JOIN Projects
ON Employees.EmployeeID = Projects.EmployeeID
ORDER BY DeptName, LastName, ProjectNo;
DeptName Last Name Project No
.••·····································
1 ! Accounting
........ ......... ........ ..........! Hernandez
;., ,., ,.;
P1011
2 Maintenance Hardy NULL
3 Operations NULL NULL
4 Payroll Aaronsen P101 2
5 Payroll Simonian P101 2
6 Payroll Smith P101 2
7 Personnel Jones NULL
8 Personnel O'Leary P1011
es
A SELECT statement that joins the three tables using full outer joins
SELECT DeptName, LastName, ProjectNo
FROM Departments
FULL JOIN Employees
ON Departments.DeptNo - Employees.DeptNo
FULL JOIN Projects
ON Employees.EmployeeID = Projects.EmployeeID
ORDER BY DeptName;
DeptName Last Name Project No
1 P1013
l._NULL··················__j Watson
2 NULL Locario P1013
3 NULL NULL P1014
4 Accounting Hernandez P1011
5 Maintenance Hardy NULL
6 Operations NULL NULL
7 Payroll Smith P101 2
8 Payroll Simonian P101 2
9 Payroll Aaronsen P101 2
10 Personnel Jones NULL
11 Personnel O'Leary P1011
""
9 9 Locario Paulo 6
Description
• You can co1nbine inner and outer joins within a single SELECT state1nent using
the explicit join syntax. You can 't co1nbine inner and outer joins using the i1nplicit
syntax.
Description
• A cross join joins each row fro1n the first table with each row fro1n the second
table. The result set returned by a cross join is known as a Cartesian product.
• To code a cross join using the explicit syntax, use the CROSS JOIN keywords in
the FROM clause.
• To code a cross join using the i1nplicit syntax, list the tables in the FROM clause
and 01nit the join condition fro1n the WHERE clause.
(72 rows)
Description
• A union co1nbines the result sets of two or 1nore SELECT state1nents into one
result set.
• Each result set 1n ust return the sa1ne nu1nber of colu1nns, and the corresponding
colu1nns in each result set 1n ust have co1npatible data types.
• By default, a union eli1ninates duplicate rows. If you want to include duplicate
rows, code the ALL keyword.
• The colu1nn na1nes in the final result set are taken fro1n the first SELECT clause.
Colu1nn aliases assigned by the other SELECT clauses have no effect on the final
result set.
• To sort the rows in the final result set, code an ORDER BY clause after the last
SELECT state1nent. This clause 1n ust refer to the colu1nn na1nes assigned in the
first SELECT clause.
A union that combines payment data from the same joined tables
SELECT InvoiceNumber, VendorName, 1 33% Payment' AS PaymentType,
InvoiceTotal AS Total, (InvoiceTotal * 0.333) AS Payment
FROM Invoices JOIN Vendors
ON Invoices.vendorID = vendors.vendorID
WHERE InvoiceTotal > 10000
UNION
SELECT InvoiceNumber, vendorName, '50% Payment' AS PaymentType,
InvoiceTotal AS Total, (InvoiceTotal * 0.5) AS Payment
FROM Invoices JOIN Vendors
ON Invoices.vendorID = vendors.vendorID
WHERE InvoiceTotal BETWEEN 500 AND 10000
UNION
SELECT InvoiceNumber, VendorName, 'Full amount' AS PaymentType,
InvoiceTotal AS Total, InvoiceTotal AS Payment
FROM Invoices JOIN Vendors
ON Invoices.vendorID = vendors.vendorID
WHERE InvoiceTotal < 500
ORDER BY PaymentType, VendorName, InvoiceNumber;
6 P-0608 Malloy Lithographing Inc 33% Payment ~51 .18 6843.5429400 .__
7 50:9786 Bertelsmann Industry S... 50"4 Payment 6940.25 34 70.1250000
8 587056 Cahners Publishing Co ... 50"4 Payment 2184.50 1092.2500000
9 367447 Computerworid 50"4 Payment 2433.00 1216.5000000
=
( 114 rows )
(23 rows)
(1 row)
Description
• The nu1nber of colu1nns 1nust be the sa1ne in both SELECT state1nents.
• The data types for each colu1nn 1nust be co1npatible.
• The colu1nn na1nes in the final result set are taken fro1n the first SELECT state1nent.
Figure 4-15 How to use the EXCEPT and INTERSECT ope rators
156 Section 2 The essential SQL skills
Perspective
In this chapter, you learned a variety of techniques for combining data from
two or more tables into a single result set. In particular, you learned how to use
the SQL-92 syntax for combining data using inner joins. Of all the techniques
presented in this chapter, this is the one you '11 use most often. So you '11 want to
be sure you understand it thoroughly before you go on.
Terms
JOln interim table
join condition implicit syntax
mner JOln theta syntax
ad hoc relationship outer join
qualified column name left outer join
explicit syntax right outer join
correlation name full outer join
table alias cross Join
fully-qualified object name Cartesian product
partially-qualified object name union
self-join set operator
interim result set
Exercises
Unless otherwise stated, use the explicit join syntax.
1. Write a SELECT statement that returns all columns from the Vendors table
inner-joined with the Invoices table.
2. Write a SELECT statement that returns four columns:
VendorName From the Vendors table
lnvoiceNumber From the Invoices table
lnvoiceDate From the Invoices table
Balance lnvoiceTotal minus the sum of
PaymentTotal and CreditTotal
The result set should have one row for each invoice with a non-zero balance.
Sort the result set by VendorName in ascending order.
3. Write a SELECT statement that returns three columns:
VendorName From the Vendors table
DefaultAccountNo From the Vendors table
AccountDescription From the GLAccounts table
The result set should have one row for each vendor, with the account number
and account description for that vendor's default account number. Sort the
result set by AccountDescription, then by VendorName.
Chapter 4 How to retrieve data from two or more tables 157
4. Generate the same result set described in exercise 2, but use the implicit join
syntax.
5. Write a SELECT statement that returns five columns from three tables, all
using column aliases:
Vendor VendorName column
Date lnvoiceDate column
Number lnvoiceNumber column
# lnvoiceSequence column
Lineltem lnvoiceLineltemAmount column
Assign the following correlation names to the tables:
v Vendors table
1 Invoices table
Ii lnvoiceLineltems table
Sort the final result set by Vendor, Date, Number, and #.
6. Write a SELECT statement that returns three columns:
VendorID From the Vendors table
VendorName From the Vendors table
Name A concatenation of VendorContactFName and
VendorContactLName, with a space in between
The result set should have one row for each vendor whose contact has the
same first name as another vendor 's contact. Sort the final result set by Name.
Hint: Use a self-join.
7. Write a SELECT statement that returns two columns from the GLAccounts
table: AccountNo and AccountDescription. The result set should have one row
for each account number that has never been used. Sort the final result set by
AccountNo.
Hint: Use an outer join to the lnvoiceLineltems table.
8. Use the UNION operator to generate a result set consisting of two columns
from the Vendors table: VendorName and VendorState. If the vendor is in
California, the VendorState value should be "CA"; otherwise, the VendorState
value should be "Outside CA." Sort the final result set by VendorName.
5
How to code
•
summary queries
In this chapter, you '11 learn how to code queries that summarize data. For
example, you can use summary queries to report sales totals by vendor or
state, or to get a count of the number of invoices that were processed each day
of the month. You '11 also learn how to use a special type of function called an
aggregate function. Aggregate functions allow you to easily do jobs like figure
averages or totals, or find the highest value for a given column. So you '11 use
them frequently in your summary queries.
A summary query that counts unpaid invoices and calculates the total due
SELECT COUNT ( * ) AS NumberOfinvoices,
SUM ( InvoiceTotal - PaymentTotal - CreditTotal ) AS TotalDue
FROM Invoices
WHERE InvoiceTotal - PaymentTotal - CreditTotal > 0 ;
l. .~--~·-························--·············..J 32020.42
Description
• Aggregate functions, also called column functions, perfor1n a calculation on the
values in a set of selected rows. Yo u specify the values to be used in the calculation
by coding an expression for the function 's argu1nent. In 1nany cases, the expression
is j ust the na1ne of a colu1nn.
• A SELECT state1nent that includes an aggregate function can be called a summary
query.
• The expression yo u specify for the AVG and SUM functions 1nust result in a
nu1neric value. The expression for the MIN, MAX, and COUNT functions can
result in a nu1neric, date, or string value.
• By default, all values are included in the calculation regardless of whether they're
duplicated. If yo u want to 01nit d uplicate values, code the DISTINCT keyword.
This keyword is typically used only with the COUNT function.
• All of the aggregate functions except for COUNT(*) ignore null values.
• Aggregate functions are often used with the GROUP BY clause of the SELECT
state1nent, which is used to gro up the rows in a result set. See fig ure 5-3 for 1nore
infor1natio n.
• If you code an aggregate function in the SELECT clause, that clause can 't include
non-aggregate colu1nns fro1n the base table unless the colu1nn is specified in a
GROUP BY clause or the OVER clause is included for each aggregate function.
See fig ure 5-10 for 1nore infor1nation on the OVER clause.
A summary query that uses the COUNT(*), AVG, and SUM functions
SELECT 'After 9 / 1 / 2 0 15' AS SelectionDate, COUNT ( * ) AS NumberOfinvoices,
AVG (InvoiceTotal ) AS AverageinvoiceAmount,
SUM (InvoiceTotal ) AS TotalinvoiceAmount
FROM Invoices
WHERE InvoiceDate > 1 2 015-0 9- 01 1 ;
Selection Date NumberOflnvoices Average InvoiceAmount Total lnvoiceAmount
1 After 91112015
It ......................... 1 114
,..........., .............=
1879.7413 214290.51
Notes
• If you want to count all of the selected rows, you ' 11 typically use the COUNT(*)
function as illustrated by the first two exa1nples above. An alternative is to code the
na1ne of any colu1nn in the base table that can 't contain null values, as illustrated by
the third exa1nple.
• If you want to count only the rows with uniq ue values in a specified colu1nn, you
can code the COUNT function with the DISTINCT keyword followed by the na1ne
of the colu1nn, as illustrated in the fo urth exa1nple.
Description
• The GROUP BY clause groups the rows of a result set based on one or 1nore
colu1nns or expressions. It 's typically used in SELECT state1nents that include
aggregate functions.
• If you include aggregate functions in the SELECT clause, the aggregate is calcu-
lated for each set of values that result fro1n the colu1nns na1ned in the GROUP BY
clause.
• If you include two or 1nore colu1nns or expressions in the GROUP BY clause, they
for1n a hierarchy where each colu1nn or expression is subordinate to the previous
one.
• When a SELECT state1nent includes a GROUP BY clause, the SELECT clause can
include aggregate functions, the colu1nns used for grouping, and expressions that
result in a constant value.
• A group-by list typically consists of the na1nes of one or 1nore colu1nns separated
by co1n1nas. However, it can contain any expression except for those that contain
aggregate functions.
• The HAYING clause specifies a search condition for a group or an aggregate. This
condition is applied after the rows that satisfy the search condition in the WHERE
clause are grouped.
(34 rows)
2 CA Fresno 19 1208.7457
3 CA Los Angeles 1 503.20
4 CA Oxnard 3 188.00
5 CA Pasadena 5 196.12
~
( 2 0 rows)
(12 rows)
Note
• You can use a join with a su1n1nary query to group and su1n1narize the data in two
or 1nore tables.
Figure 5-4 Queries that use the GROUP BY and HAVI NG clauses
168 Section 2 The essential SQL skills
( 19 rows)
Description
• When you include a WHERE clause in a SELECT state1nent that uses grouping
and aggregates, the search condition is applied before the rows are grouped and the
aggregates are calculated. That way, only the rows that satisfy the search condition
are grouped and su1n1narized.
• When you include a HAVING clause in a SELECT state1nent that uses grouping
and aggregates, the search condition is applied after the rows are grouped and the
aggregates are calculated. That way, only the groups that satisfy the search condi-
tion are included in the result set.
• A HAVING clause can only refer to a colu1nn included in the SELECT or GROUP
BY clause. A WHERE clause can refer to any colu1nn in the base tables.
• Aggregate functions can only be coded in the HAVING clause. A WHERE clause
can 't contain aggregate functions.
Figure 5-5 How the HAVI NG clause compares to the WHERE clause
170 Section 2 The essential SQL skills
GROUP BY InvoiceDate
HAVING COUNT ( * ) > 1
AND SUM ( InvoiceTotal ) > 1 00
ORDER BY InvoiceDate DESC;
Description
• You can use the AND and OR operators to code co1npound search conditions in a
HAVING clause just as you can in a WHERE clause.
• If a search condition includes an aggregate function, it 1nust be coded in the
HAVING clause. Otherwise, it can be coded in either the HAVING or the WHERE
clause.
• In 1nost cases, your code will be easier to read if you code all the search conditions
in the HAVING clause, but you can code non-aggregate search conditions in the
WHERE clause if you prefer.
Another way to code the GROUP BY clause (SQL Server 2008 or later)
GROUP BY ROLLUP (VendorID )
A summary query that includes a summary row for each grouping level
SELECT VendorState, VendorCity, COUNT ( * ) AS QtyVendors
FROM Vendors
WHERE VendorState IN ( 'IA', 'NJ' )
GROUP BY VendorState, VendorCity WITH ROLLUP
ORDER BY VendorState DESC, VendorCity DESC;
VendorState VendorOty QtyVendors
··········•········•···············
1 NJ Washington 1
.........,...................., ...
.....
2 NJ Fairfield 1
3 NJ East Brunswick 2
4 NJ NULl 4 - - - Sum1
m ary row for state 'NJ '
5 IA Washington 1
6 IA Fairfield 1
7 IA NULl 2 - - - Sum1m ary row for state 'IA'
8 NULL NULl 6 - - - Sum1m ary row for all rows
Another way to code the GROUP BY clause (SQL Server 2008 or later)
GROUP BY ROLLUP (VendorState, VendorCity )
Description
• The ROLLUP operator adds a su1n1nary row for each gro up specified. It also adds a
su1n1nary row to the end of the result set that su1n1narizes the entire result set. If the
GROUP BY clause specifies a single gro up, only the final su1n1nary row is added.
• The sort sequence in the ORDER BY clause is applied after the su1n1nary rows
are added. Because of that, yo u ' 11 want to sort gro uping colu1nns in descending
sequence so that the su1n1nary row for each group, which can contain null values,
appears after the other rows in the gro up.
• When yo u use the ROLLUP operator, yo u can 't use the DISTINCT keyword in any
of the aggregate functions.
• Yo u can use the GROUPING function with the ROLLUP operator to deter1nine if a
su1n1nary row has a null value assigned to a given colu1nn. See chapter 9 for details.
Another way to code the GROUP BY clause (SQL Server 2008 or later)
GROUP BY CUBE (VendorID )
A summary query that includes a summary row for each set of groups
SELECT VendorState, VendorCity, COUNT ( * ) AS QtyVendors
FROM Vendors
WHERE VendorState IN ( 'IA', 'NJ' )
GROUP BY VendorState, VendorCity WITH CUBE
ORDER BY VendorState DESC, VendorCity DESC;
VendorState VendorOty QtyVendors
1 .. NJ .................... _] Washington 1
2 NJ Fairfield 1
3 NJ East Brunswick 2
4 NJ NULIL 4 Summary row for state 'NJ '
5 IA 1N ashington 1
6 IA Fairfield 1
7 IA NULIL 2 - - - Summary row for state 'IA'
8 NULL Washington 2 - - - Summary row for city 'Washington '
9 NULL Fairfield 2 - - - Summary row for city 'Fairfield '
10 NULL East Brunswick 2 - - - Summary row for city 'East Brunswick'
11 NULL NULIL 6 - - - Summary row for all rows
Another way to code the GROUP BY clause (SQL Server 2008 or later)
GROUP BY CUBE (VendorState, VendorCity )
Description
• The CUBE operator adds a su1n1nary row fo r every co1nbination of groups specified.
It also adds a su1n1nary row to the end of the result set that su1n1narizes the entire
result set.
• When you use the CUBE operator, you can 't use the DISTINCT keyword in any of
the aggregate functions.
• You can use the GROUPING function with the CUBE operator to deter1nine if a
su1n1nary row has a null value assigned to a given colu1nn. See chapter 9 for details.
2 IA NULl 2
3 NULL Washington 2
4 NULL Fairfield 2
5 NULL East Brunswick 2
Description
• The GROUPING SETS operator creates a su1n1nary row for each specified gro up.
• Within the parentheses after the GROUPING SETS operator, yo u can add
additional sets of parentheses to create co1nposite gro ups.
• Within the parentheses after the GROUPING SETS operator, you can add an e1npty
set of parentheses to add a su1n1nary row that su1n1narizes the entire result set.
• For a co1nposite gro up, yo u can add the ROLLUP or CUBE operator to add
additional su1n1nary rows. This perfor1ns the ROLLUP or CUBE operation on the
co1nposite gro up, which also adds a su1n1nary row that su1n1narizes the entire result
set.
Description
• When used with the aggregate functions, the OVER clause lets yo u su1n1narize the
data in a result set while still returning the rows used to calculate the su1n1nary.
Perspective
In this chapter, you learned how to code queries that group and summarize
data. In most cases, you '11 be able to use the techniques presented here to get
the summary information you need. If not, you may want to find out about
another tool provided by SQL Server 2016 called Analysis Services. This tool
provides a graphical interface that lets you build complex data models based on
cubes. Then, you can use those models to analyze the database using complex
patterns and correlations. You can find out more about this tool by searching for
"Analysis Services" in the documentation for SQL Server.
Terms
scalar function scalar aggregate
aggregate function vector aggregate
column function cumulative total
summary query moving average
Exercises
1. Write a SELECT statement that returns two columns from the Invoices table:
VendorID and PaymentSum, where PaymentSum is the sum of the PaymentTotal
column. Group the result set by VendorID.
2. Write a SELECT statement that returns two columns: VendorName and
PaymentSum, where PaymentSum is the sum of the PaymentTotal column.
Group the result set by VendorName. Return only 10 rows, corresponding to
the 10 vendors who've been paid the most.
Hint: Use the TOP clause and join Vendors to Invoices.
3. Write a SELECT statement that returns three columns: VendorName,
lnvoiceCount, and lnvoiceSum. lnvoiceCount is the count of the number of
invoices, and lnvoiceSum is the sum of the lnvoiceTotal column. Group the
result set by vendor. Sort the result set so that the vendor with the highest
number of invoices appears first.
4. Write a SELECT statement that returns three columns: AccountDescription,
LineltemCount, and LineltemSum. LineltemCount is the number of entries in
the lnvoiceLineltems table that have that AccountNo. LineltemSum is the sum
of the lnvoiceLineltemAmount column for that AccountNo. Filter the result
set to include only those rows with LineltemCount greater than 1. Group the
result set by account description, and sort it by descending LineltemCount.
Hint: Join the GLAccounts table to the lnvoiceLineltems table.
5. Modify the solution to exercise 4 to filter for invoices dated from December 1,
2015 to February 29, 2016.
Hint: Join to the Invoices table to code a search condition based on lnvoiceDate.
Chapter 5 How to code summary queries 181
6. Write a SELECT statement that answers the following question: What is the
total amount invoiced for each AccountNo? Use the WITH ROLLUP operator
to include a row that gives the grand total.
Hint: Use the lnvoiceLineltemAmount column of the lnvoiceLineltems table.
7. Write a SELECT statement that returns four columns: VendorName,
AccountDescription, LineltemCount, and LineltemSum. LineltemCount is
the row count, and LineltemSum is the sum of the lnvoiceLineltemAmount
column. For each vendor and account, return the number and sum of line
items, sorted first by vendor, then by account description.
Hint: Use a four-table join.
8. Write a SELECT statement that answers this question: Which vendors are
being paid from more than one account? Return two columns: the vendor
name and the total number of accounts that apply to that vendor's invoices.
Hint: Use the DISTINCT keyword to count lnvoiceLineltems.AccountNo.
9. Write a SELECT statement that returns six columns:
VendorID From the Invoices table
lnvoiceDate From the Invoices table
lnvoiceTotal From the Invoices table
VendorTotal The sum of the invoice totals for each vendor
VendorCount The count of invoices for each vendor
VendorAvg The average of the invoice totals for each vendor
The result set should include the individual invoices for each vendor.
6
An introduction to subqueries
Since you know how to code SELECT statements, you already know how
to code a subquery. It's simply a SELECT statement that's coded within another
SQL statement. The trick to using subqueries, then, is knowing where and
when to use them. You'll learn the specifics of using subqueries throughout this
chapter. The two topics that follow, however, will give you an overview of where
and when to use them.
(2 1 rows)
Description
• A subquery is a SELECT state1nent that's coded within another SQL state1nent.
• A subquery can return a single value, a result set that contains a single colu1nn, or a
result set that contains one or 1nore colu1nns.
• A subquery that returns a single value can be coded, or introduced, anywhere an
expression is allowed. A subquery that returns a single colu1nn can be introduced
in place of a list of values, such as the values for an IN phrase. And a subquery that
returns one or 1nore colu1nns can be introd uced in place of a table in the FROM
clause.
• The syntax for a subquery is the sa1ne as for a standard SELECT state1nent.
However, a subquery doesn't typically include the GROUP BY or HAVING clause,
and it can't include an ORDER BY clause unless the TOP phrase is used.
• A subquery that's used in a WHERE or HAVING clause is called a subquery search
condition or a subquery predicate. This is the 1nost co1n1non use for a subquery.
• Although you can introd uce a subquery in a GROUP BY or ORDER BY clause,
you usually won't need to.
• Subqueries can be nested within other subqueries. However, subqueries that are
nested 1nore than two or three levels deep can be difficult to read and can result in
poor perfor1nance.
( 4 0 r ows }
Advantages of joins
• The result of a join operation can include colu1nns fro1n both tables. The result of a
query that includes a subquery can only include colu1nns fro1n the table na1ned in
the outer query. It can 't include colu1nns frorn the table na1ned in the subquery.
• A join tends to be 1nore intuitive when it uses an existing relationship between the
two tables, such as a pri1nary key to fo reign key relationship.
• A query with a join typically perfor1ns faster than the sa1ne query with a subquery,
especially if the query uses only inner joins.
Advantages of subqueries
• You can use a subquery to pass an aggregate value to the outer query.
• A subquery tends to be 1nore intuitive when iit uses an ad hoc relationship between
the two tables.
• Long, co1nplex queries can so1neti1nes be easier to code using subqueries.
Description
• Like a join, a subquery can be used to code queries that work with two or 1nore
tables.
• Most subqueries can be restated as joins and 1nost joins can be restated as
subqueries.
( 34 rows )
( 88 rows )
Description
• Yo u can introduce a subquery with the IN operator to provide the list of values that
are tested against the test expression.
• When yo u use the IN operator, the subquery 1nust return a single colu1nn of values.
• A query that uses the NOT IN operator with a subquery can typically be restated
using an outer join.
A query that returns invoices with a balance due less than the average
SELECT InvoiceNumber, InvoiceDate, InvoiceTotal,
InvoiceTotal - PaymentTotal - CreditTotal AS BalanceDue
FROM Invoices
WHERE InvoiceTotal - PaymentTotal - CreditTotal > 0
AND InvoiceTotal - PaymentTotal - CreditTotal <
(SELECT AVG(InvoiceTotal - PaymentTotal - CreditTotal)
FROM Invoices
WHERE InvoiceTotal - PaymentTotal - CreditTotal > 0)
ORDER BY InvoiceTotal DESC;
(9 rows)
Description
• You can use a co1nparison operator in a search condition to co1npare an expression
with the results of a subquery.
• If you code a search condition without the ANY, SOME, and ALL keywords, the
subquery 1nust return a single value.
• If you include the ANY, SOME, or ALL keyword, the subquery can return a list of
values. See figures 6-5 and 6-6 for 1nore infor1nation on using these keywords.
A query that returns invoices larger than the largest invoice for vendor 34
SELECT VendorName, InvoiceNumber, InvoiceTotal
FROM Invoices JOIN Vendors ON Invoices.vendorID = Vendors.vendorID
WHERE InvoiceTotal > ALL
(SELECT InvoiceTotal
FROM Invoices
WHERE VendorID = 34 )
ORDER BY VendorName;
(25 rows)
Description
• Yo u can use the ALL keyword to test that a co1nparison condition is true for all of the
values returned by a subquery. This keyword is typically used with the co1n parison
operators <, >, <=, and >=.
• If no rows are returned by the subquery, a co1n parison that uses the ALL keyword is
always true.
• If all of the rows returned by the subquery contain a null value, a co1nparison that
uses the ALL keyword is always false.
( 1 7 r ows )
Description
• You can use the ANY or SOME keyword to test that a condition is true for one or
1nore of the values returned by a subq uery.
• ANY and SOME are equivalent keywords. SOME is the ANSI-standard keyword,
but ANY is 1nore co1n 1no nly used.
• If no rows are returned by the subq uery or all of the rows returned by the subq uery
contain a null value, a co1n parison that uses the ANY or SOME keyword is always false.
Figure 6-6 How to use the ANY and SOME !keywo rds
196 Section 2 The essential SQL skills
( 3 6 rows )
Description
• A correlated subquery is a subquery that is executed once for each row processed
by the outer query. In contrast, a noncorrelated subquery is executed only once. All
of the subqueries you've seen so far have been noncorrelated subqueries.
• A correlated subquery refers to a value that's provided by a column in the outer
query. Because that value varies depending on the row that's being processed, each
execution of the subquery returns a different result.
• To refer to a value in the outer query, a correlated subquery uses a qualified column
name that includes the table name from the outer query. If the subquery uses the
same table as the outer query, an alias, or correlation name, must be assigned to
one of the tables to remove ambiguity.
Note
• Because a correlated subquery is executed once for each row processed by the outer
query, a query with a correlated subquery typically takes longer to run than a query
with a noncorrelated subquery.
( 88 rows )
Description
• You can use the EXISTS operator to test that one or 1nore rows are returned by the
subquery. You can also use the NOT operator along with the EXISTS operator to
test that no rows are returned by the subquery.
• When you use the EXISTS operator with a subquery, the subquery doesn 't actually
return any rows. Instead, it returns an indication of whether any rows 1neet the
specified condition.
• Because no rows are returned by the subquery, it doesn 't 1natter what colu1nns you
specify in the SELECT clause. So you typically just code an asterisk (*).
• Although you can use the EXISTS operator with either a correlated or a
noncorrelated subquery, it's used 1nost often with correlated subqueries. That's
because it's usually better to use a join than a noncorrelated subquery with
EXISTS.
Description
• A subquery that's coded in the FROM clause returns a result set called a derived
table. When yo u create a derived table, yo u rnust assign an alias to it. Then, yo u
can use the derived table within the outer q uery j ust as you wo uld any other table.
• When yo u code a subquery in the FROM clause, yo u 1nust assign na1nes to any
calculated values in the result set.
• Derived tables are 1nost useful when you need to further su1n1narize the results of a
su1n1nary query.
• A derived table is like a view in that it retrieves selected rows and colu1nns fro1n
one or 1nore base tables. Because views are stored as part of the database, they're
typically 1nore efficient to use than derived tables. However, it 1nay not always be
practical to construct and save a view in advance.
(122 rows)
Description
• When yo u code a subquery for a colu1nn specification in the SELECT clause, the
subquery 1nust return a single value.
• A subquery that's coded within a SELECT clause is typically a correlated subquery.
• A query that includes a subquery in its SELECT clause can typically be restated
using a join instead of the subquery. Because a join is usually faster and 1nore
readable, subqueries are seldo1n coded in the SELECT clause.
( 1 0 r ows )
( 1 0 rows )
How to work
with common table expressions
A common table expression (CTE) is a feature that was introduced with SQL
Server 2005 that allows you to code an expression that defines a derived table.
You can use CTEs to simplify complex queries that use subqueries. This can
make your code easier to read and maintain. In addition, you can use a CTE to
loop through nested structures.
( 1 0 rows )
Description
• A common table expression (CTE) is an expression (usually a SELECT state1nent)
that creates one or 1nore te1nporary tables that can be used by the following query.
• To use a CTE with a query, yo u code the WIT H keyword followed by the definition
of the CTE. Then, i1n1nediately after the CTE , yo u code the state1nent that uses it.
• To code 1nultiple CTEs, separate the1n with co1n1nas. Then, each CTE can refer to
itself and any previously defined CTEs in the sa1ne WITH clause.
• You can use CTEs with SELECT, INSERT, UPDATE, and DELETE state1nents.
However, yo u 're 1nost likely to use the1n with SELECT state1nents as shown in this
figure and in figure 6-14.
1 As Rank
FROM Employees
WHERE ManagerID IS NULL
UNION ALL
-- Recursive member
SELECT Employees.EmployeeID,
FirstName + ' ' + LastName,
Rank+ 1
FROM Employees
JOIN EmployeesCTE
ON Employees.ManagerID - EmployeesCTE.EmployeeID
)
SELECT*
FROM EmployeesCTE
ORDER BY Rank, EmployeeID;
Description
• A recursive query is a query that is able to loop through a result set and perfor1n
processing to return a final result set. A recursive CTE can be used to create a
recursive query.
• A recursive CTE 1nust contain at least two query definitions, an anchor member
and a recursive member, and these 1ne1nbers 1nust be connected by the UNION
ALL operator.
Perspective
As you've seen in this chapter, subqueries provide a powerful tool for
solving difficult problems. Before you use a subquery, however, remember
that a subquery can often be restated more clearly by using a join. In addition,
a query with a join often executes more quickly than a query with a subquery.
Because of that, you '11 typically use a subquery only when it can't be restated
as a join or when it makes the query easier to understand without slowing it
down significantly.
If you find yourself coding the same subqueries over and over, you should
consider creating a view for that subquery as described in chapter 13. This will
help you develop queries more quickly since you can use the view instead of
coding the subquery again. In addition, since views execute more quickly than
subqueries, this may improve the performance of your queries.
Terms
subquery derived table
introduce a subquery pseudocode
subquery search condition common table expression (CTE)
subquery predicate recursive query
nested subquery recursive CTE
correlated subquery anchor member
noncorrelated subquery recursive member
Exercises
1. Write a SELECT statement that returns the same result set as this SELECT
statement. Substitute a subquery in a WHERE clause for the inner join.
SELECT DISTINCT vendorName
FROM Vendors JOIN Invoices
ON vendors.vendorID = Invoices.vendorID
ORDER BY VendorName;
2. Write a SELECT statement that answers this question: Which invoices have
a PaymentTotal that's greater than the average PaymentTotal for all paid
invoices? Return the InvoiceNumber and InvoiceTotal for each invoice.
3. Write a SELECT statement that answers this question: Which invoices have
a PaymentTotal that's greater than the median PaymentTotal for all paid
invoices? (The median marks the midpoint in a set of values; an equal number
of values lie above and below it.) Return the InvoiceNumber and InvoiceTotal
for each invoice.
Hint: Begin with the solution to exercise 2, then use the ALL keyword in
the WHERE clause and code "TOP 50 PERCENT PaymentTotal" in the
subquery.
Chapter 6 How to code subqueries 213
4. Write a SELECT statement that returns two columns from the GLAccounts
table: AccountNo and AccountDescription. The result set should have one
row for each account number that has never been used. Use a correlated
subquery introduced with the NOT EXISTS operator. Sort the final result set
by AccountNo.
5. Write a SELECT statement that returns four columns: VendorName,
InvoiceID, InvoiceSequence, and InvoiceLineitemAmount for each invoice
that has more than one line item in the InvoiceLineitems table.
Hint: Use a subquery that tests for InvoiceSequence > 1.
6. Write a SELECT statement that returns a single value that represents the sum
of the largest unpaid invoices submitted by each vendor. Use a derived table
that returns MAX(InvoiceTotal) grouped by VendorID, filtering for invoices
with a balance due.
7. Write a SELECT statement that returns the name, city, and state of each
vendor that's located in a unique city and state. In other words, don't include
vendors that have a city and state in common with another vendor.
8. Write a SELECT statement that returns four columns: VendorName,
InvoiceNumber, InvoiceDate, and InvoiceTotal. Return one row per vendor,
representing the vendor's invoice with the earliest date.
9. Rewrite exercise 6 so it uses a common table expression (CTE) instead of a
derived table.
7
Description
• The INTO clause is a SQL Server extension that lets you create a new table based on
the result set defined by the SELECT state1nent. Since the definitions of the colu1nns in
the new table are based on the colu1nns in the result set, the colu1nn na1nes assigned in
the SELECT clause 1nust be unique.
• You can code the other clauses of the SELECT INTO state1nent just as you would for
any other SELECT state1nent.
• If you use calculated values in the select list, you 1nust na1ne the colu1nn since that
na1ne is used in the definition of the new table.
• The table you na1ne in the INTO clause 1nust not exist. If it does, you 1nust delete it
using the DROP TABLE state1nent before you execute the SELECT INTO state1nent.
Warning
• When you use the SELECT INTO state1nent to create a table, only the colu1nn definitions
and data are copied. That 1neans that definitions of pritnary keys, foreign keys, indexes,
default values, and so on are not included in the new table.
Figure 7-1 How to use the SELECT INTO statement to create test tables
218 Section 2 The essential SQL skills
An INSERT statement that adds the new row without using a column list
INSERT INTO InvoiceCopy
VALUES (97, 456789 1
2016-04-01 1
,
1 1
, 8344.50, 0, 0, 1, 1
2016-04-30 1
, NULL);
An INSERT statement that adds the new row using a column list
INSERT INTO InvoiceCopy
(VendorID, InvoiceNumber, InvoiceTotal, PaymentTotal, CreditTotal,
TermsID, InvoiceDate, InvoiceDueDate)
VALUES
(97, 456789
1
8344.50, 0, 0, 1,
1
, 2016-04-01 2016-04-30 1 1
,
1 1
);
(102, 109596
1
2016-04-01
1
22 . 97, 0, 0, 1,
,
1
2016-04-30
1
, NULL), 1 1
,
(72, 40319
1
2016-04-01
1
, 173.38, 0, 0, 1,
1 1
2016-04-30
, NULL); 1 1
,
Description
• You specify the values to be inserted in the VALUES clause. The values you
specify depend on whether you include a colu1nn list.
• If you don 't include a colu1nn list, you 1nust specify the colu1nn values in the sa1ne
order as they appear in the table, and you 1nust code a value for each colu1nn in the
table. The exception is an identity colu1nn, which 1nust be 01nitted.
• If you include a colu1nn list, you 1nust specify the colu1nn values in the sa1ne order
as they appear in the colu1nn list. You can 01nit colu1nns with default values and
colu1nns that accept null values, and you 1nust 01nit identity colu1nns.
Description
• If a colu1nn is defined so that it allows null values, you can use the NULL keyword in
the list of values to insert a null value into that colu1nn.
• If a colu1nn is defined with a default value, you can use the DEFAULT keyword in the
list of values to insert the default value for that colu1nn.
• If all of the colu1nns in a table are defined as either identity colu1nns, colu1nns
with default values, or colu1nns that allow null values, you can code the DEFAULT
keyword at the beginning of the VALUES clause and then 01nit the list of values.
• If you include a colu1nn list, you can 01nit colu1nns with default values and null
values. Then, the default value or null value iis assigned auto1natically.
Description
• To insert rows selected from one or more tables into another table, you can code a
subquery in place of the VALUES clause. Then, the rows in the derived table that
result from the subquery are inserted into the table.
• If you don't code a column list in the INSERT clause, the subquery must return
values for all the columns in the table where the rows will be inserted, and the
columns must be returned in the same order as they appear in that table. The
exception is an identity column, which must be omitted.
• If you include a column list in the INSERT clause, the subquery must return values
for those columns in the same order as they appear in the column list. You can omit
columns with default values and columns that accept null values, and you must
omit identity columns.
Description
• You use the UPDATE statement to modify one or more rows in the table named in
the UPDATE clause.
• You name the columns to be modified and the value to be assigned to each
column in the SET clause. You can specify the value for a column as a literal or an
expression.
• You can provide additional criteria for the update operation in the FROM clause,
which is a SQL Server extension. See figures 7-6 and 7-7 for more information.
• You can specify the conditions that must be met for a row to be updated in the
WHERE clause.
• You can use the DEFAULT keyword to assign the default value to a column that
has one, and you can use the NULL keyword to assign a null value to a column that
allows nulls.
• You can't update an identity column.
Warning
• If you omit the WHERE clause, all the rows in the table will be updated.
(1 row(s) affected)
An UPDATE statement that updates all the invoices for a vendor based
on the vendor's name
UPDATE InvoiceCopy
SET TermsID = 1
WHERE VendorID =
(SELECT VendorID
FROM VendorCopy
WHERE VendorName - 'Pacific Bell');
(6 row(s) affected)
Description
• You can code a subquery in the SET, FROM, or WHERE clause of an UPDATE
statement.
• You can use a subquery in the SET clause to return the value that's assigned to a
column.
• You can use a subquery in the FROM clause to identify the rows that are available
for update. Then, you can refer to the derived table in the SET and WHERE clauses.
• You can code a subquery in the WHERE clause to provide one or more values used
in the search condition.
Description
• If you need to specify colu1nn values or search conditions that depend on data in
a table other than the one na1ned in the UPDATE clause, you can use a join in the
FROM clause.
• You can use colu1nns fro1n the joined tables in the values you assign to colu1nns in
the SET clause or in the search condition of a WHERE clause.
A DELETE statement that removes all the rows from the lnvoiceCopy table
DELETE InvoiceCopy;
(114 row(s ) affec ted )
Description
• You can use the DELETE statement to delete one or more rows from the table you
name in the DELETE clause.
• You specify the conditions that must be met for a row to be deleted in the WHERE
clause.
• You can specify additional criteria for the delete operation in the FROM clause. See
figure 7-9 for more information.
Warning
• If you omit the WHERE clause from a DELETE statement, all the rows in the table
will be deleted.
Description
• You can use subqueries and joins in the FROM clause of a DELETE statement
to base the delete operation on the data in tables other than the one named in the
DELETE clause.
• You can use any of the columns returned by a subquery or a join in the WHERE
clause of the DELETE statement.
• You can also use subqueries in the WHERE clause to provide one or more values
used in the search condition.
Note
• The FROM clause is a SQL Server extension.
A WHEN clause that deletes rows that aren't matched by the source
WHEN NOT MATCHED BY SOURCE THEN
DELETE
Description
• The MERGE statement merges multiple rows from one table into another table.
Since this often involves updating existing rows and inserting new rows, the
MERGE statement is sometimes referred to as the upsert statement.
• When coding search conditions, you can use the AND keyword to create compound
search conditions.
• You can code one or more WHEN clauses that control when and how a row is
inserted, updated, or deleted.
• Within a WHEN clause, you can code a simplified INSERT, UPDATE, or DELETE
statement that doesn't include a table name or a WHERE clause.
• To signal the end of a MERGE statement, you must code a semicolon (;).
Perspective
In this chapter, you learned how to use the INSERT, UPDATE, and
DELETE statements to modify the data in a database. Now, if you want to
practice using these statements, please use one of the two options presented
at the start of this chapter so you won't corrupt a live database or a database
shared by others.
In chapters 10 and 11, you'll learn more about the table definitions that
can affect the way these statements work. If, for example, you delete a row
in a Vendors table that has related rows in an Invoices table, SQL Server may
delete all of the related rows in the Invoices table. But that depends on how
the relationship is defined. So, to complete your understanding of the INSERT,
UPDATE, and DELETE statements, you need to read chapters 10 and 11.
Finally, you should know that SQL Server 2005 and later allow you to use
the TOP clause with the INSERT, UPDATE, and DELETE statements to limit
the number of rows that are inserted, updated, or deleted. This works similarly
to using the TOP clause with a SELECT statement as described in chapter 3.
As a result, if you read chapter 3, you shouldn't have much trouble using the
TOP clause with the INSERT, UPDATE, and DELETE statements. For coding
details, you can search for "TOP clause" in the documentation for SQL Server.
Exercises
1. Write SELECT INTO statements to create two test tables named VendorCopy
and lnvoiceCopy that are complete copies of the Vendors and Invoices tables.
If VendorCopy and lnvoiceCopy already exist, first code two DROP TABLE
statements to delete them.
2. Write an INSERT statement that adds a row to the lnvoiceCopy table with the
following values:
VendorlD: 32
lnvoiceTotal: $434.58
TermslD: 2
lnvoiceNumber: AX-014-027
PaymentTotal: $0.00
lnvoiceDueDate: 07/8/2016
lnvoiceDate: 6/21/2016
CreditTotal: $0.00
PaymentDate: null
3. Write an INSERT statement that adds a row to the VendorCopy table for
each non-California vendor in the Vendors table. (This will result in duplicate
vendors in the VendorCopy table.)
4. Write an UPDATE statement that modifies the VendorCopy table. Change
the default account number to 403 for each vendor that has a default account
number of 400.
Chapter 7 How to insert, update, and delete data 237
How to work
with data types
So far, you have been using SQL statements to work with the three most
common types of data: strings, numbers, and dates. Now, this chapter takes
a more in-depth look at the data types that are available with SQL Server
and shows some basic skills for working with them. When you complete this
chapter, you '11 have a thorough understanding of the data types, and you '11
know how to use some functions to convert one data type to another.
Description
• SQL Server defines dozens of data types that are divided into the fo ur categories
shown above.
• The temporal data types are typically referred to as date/time data types, or si1nply
date data types.
• SQL Server supports 1nost, but not all, of the ANSI-standard data types.
• SQL Server provides a synony1n fo r each of the supported ANSI-standard data
types. Although you can use these synony1ns, I reco1n1nend you use the SQL Server
data types instead. The exception is rowversion, which you should use instead of
ti1nesta1np.
• When you use the synony1n fo r an ANSI data type, it's 1napped to the appropriate
SQL Server data type indicated in the table above.
in a future release so that it's compatible with the timestamp data type defined by
the standards. When it does that, it will also replace the current timestamp data
type with a new rowversion data type. Because of that, you '11 want to use the
rowversion synonym instead of the timestamp data type.
Description
• The integer data types are used to store whole nu1nbers, which are nu1nbers witho ut
any digits to the right of the deci1nal point.
• The decimal data types are used to store decii1nal values, which can include digits
to the right of the deci1nal point. The precision of a deci1nal value indicates the total
nu1nber of digits that can be stored, and the scale indicates the nu1nber of digits that
can be stored to the right of the deci1nal point.
• The integer and deci1nal data types are considered exact numeric data types
because their precision is exact.
• The real data types are used to store floating-point numbers, which have a li1nited
nu1nber of significant digits. These data types are considered approximate numeric
data types because they 1nay not represent a value exactly.
Description
• The string data types can be used to store standard characters that use a single byte
of storage or Unicode characters that use two bytes of storage.
• The char and nchar data types are typically used fo r .fixed-length strings. These data
types use the sa1ne a1no unt of storage regardless of the actual length of the string.
• The varchar and nvarchar data types are typically used fo r variable-length strings.
These data types use only the a1no unt of storage needed fo r a given string.
• Unless yo ur syste1n is used in a 1nulti-language environ1nent, yo u should use the
char and varchar data types rather than nchar and nvarchar data types.
Note
• The Unicode specification is a sche1ne that's used to encode characters used in
languages aro und the world. This reduces the possibility that a receiving syste1n
will translate the characters incorrectly. The Unicode data types support a wider
range of characters than the standard character data types, but they require twice as
1nuch space per character.
Description
• Yo u can specify a date/ti1ne value by coding a date/ti1ne literal. To code a date/ti1ne literal,
enclose the date/ti1ne value in single quotes.
• If you don 't specify a ti1ne when storing a date value, the ti1ne defaults to 12:00 a.in. If yo u
don 't specify a date when storing a ti1ne value, the date defaults to Jan uary 1, 1900.
• By default, the two-digit year cutoff is 50, which 1neans that 00 to 49 are interpreted as 2000
to 2049 and 50 thro ugh 99 are interpreted as 1950 through 1999.
• Yo u can specify a ti1ne using either a 12-hour or a 24-ho ur clock. For a 12-ho ur clock, a1n is
the default.
Figure 8-4 The date/time data types
248 Section 2 The essential SQL skills
in the 20th or the 21st century. By default, SQL Server interprets the years 00
through 49 as 2000 through 2049, and it interprets the years 50 through 99 as
1950 through 1999. Because the two-digit year cutoff can be modified, however,
you '11 want to find out what it is on your system before you use date literals with
two-digit years. Then, if you code a date literal outside the range, you '11 have
to use a four-digit year. Of course, you can always code all of your date literals
with four-digit years, just to be sure.
The large value data types for SQL Server 2005 and later
Type Description
varchar (max ) Works the same as the varchar type described in figure 8-3, but the max
specifier allows this data type to store up to 2,147,483,648 bytes of data.
nvarchar (max ) Works the same as the nva.rchar type described in figure 8-3, but the n1ax
specifier allows this data type to store up to 2,147,483,648 bytes of data.
varbinary (max ) Stores variable-length binary data up to a maximun1 of 2,147,483,648 bytes.
The number of bytes used to store the data depends on the actual length of
the data.
How the large value data types map to the old large object types
SQL Server 2005 and later Prior to 2005
varchar (max ) text
nvarchar (max ) ntext
varbinary (max ) image
Description
• The 1nax specifier can be used with the varchar, nvarchar, and varbinary data types
to increase the storage capacity of the colu1nn so it can store up to 2 gigabytes of
data.
• The varchar(1nax), nvarchar(1nax), and varbinary(1nax) data types are known as the
large value data types, and these data types can be used to store i1nages and other
types of large character or binary data. For 1nore infor1nation about working with
the varbinary(1nax) data type, see chapter 19.
• The text, ntext, and i1nage data types that were used prior to SQL Server 2005 have
been deprecated and will be re1noved in a future version of Microsoft SQL Server.
As a result, yo u should avoid using these data types fo r any new develop1nent.
• The large value data types work like their s1naller counterparts. As a result, once
yo u learn how to use the s1naller counterparts , yo u can use the sa1ne skills to work
with the large value data types. In addition, the large value data types don 't have as
1nany restrictions as the old text, ntext, and i1nage data types.
Description
• If yo u assign a value with one data type to a colu1nn with another data type, SQL
Server converts the value to the data type of the colu1nn using implicit conversion.
Not all data types can be converted i1nplicitly to all other data types.
• SQL Server also uses i1nplicit conversion when it evaluates an expression that
involves values with different data types. In that case, it converts the value whose
data type has lower precedence to the data type that has higher precedence. The
result of the expression is returned in this sarne data type.
• Each co1nbination of precision and scale for the deci1nal and nu1neric values is
considered a different data type, with higher precision and scale taking precedence.
• If you want to perfor1n a conversion that can 't be done i1nplicitly or yo u want to
convert a data type with higher precedence to a data type with lower precedence, yo u
can use the CAST or CONVERT function to perfor1n an explicit conversion.
Description
• You can use the CAST function to explicitly convert, or cast, an expression fro1n
one data type to another.
• When you perfor1n a division operation on two integers, the result is an integer. To
get a 1nore accurate result, you can cast one of the integer values as a deci1nal. That
way, the result will be a deci1nal.
• CAST is an ANSI-standard function and is used 1nore frequently than CONVERT,
which is unique to SQL Server. You should use CONVERT when you need the
additional for1natting capabilities it provides. See figure 8-8 for details.
Description
• You can use the CONVERT function to explicitly convert an expression fro1n one
data type to another.
• You can use the optional style argu1nent to specify the fo r1nat to be used fo r
date/ti1ne, real, and 1noney values converted to character data. For a co1nplete list of
codes, search fo r "cast and convert" in the SQL Server docu1nentation.
Description
• You can use the TRY_CONVERT function to explicitly convert an expression fro1n
one data type to another.
• If the TRY_ CONVERT function can 't convert the expression to the specified data
type, it returns a NULL value instead of generating an error.
• You can use the optional style argu1nent to specify the for1nat to be used for date/
ti1ne, real, and 1noney values converted to character data. See figure 8-8 for 1nore
infor1natio n.
Figure 8-9 How to convert data using the TRY _CONVERT function
258 Section 2 The essential SQL skills
US Posta l Servi ce
Attn: Sup t. Window Servi ces
Madi son, WI 537 07
Description
• The CHAR function is typically used to insert control characters into a character string.
• To code a Unicode value as a literal, precede the value with the character N.
Perspective
In this chapter, you learned about the different SQL Server data types. In
addition, you learned how to use some functions for converting data from one
type to another. In the next chapter, you '11 leam about some of the additional
functions for working with data.
Terms
data type exact numeric data types
string data type approximate numeric data types
numeric data type Unicode character
temporal data type Unicode specification
date/time data type national character
date data type fixed-length string
integer data type variable-length string
decimal data type bit
scale ASCII (American Standard Code
prec1s1on for Information Interchange)
real data type large value data types
fixed-point number implicit conversion
floating-point number explicit conversion
significant digits cast
single-precision number Universal Time Coordinate (UTC)
double-precision number Greenwich Mean Time
scientific notation
Exercises
1. Write a SELECT statement that returns four columns based on the lnvoiceTotal
column of the Invoices table:
• Use the CAST function to return the first column as data type decimal
with 2 digits to the right of the decimal point.
• Use CAST to return the second column as a varchar.
• Use the CONVERT function to return the third column as the same data
type as the first column.
• Use CONVERT to return the fourth column as a varchar, using style 1.
2. Write a SELECT statement that returns four columns based on the lnvoiceDate
column of the Invoices table:
• Use the CAST function to return the first column as data type varchar.
• Use the CONVERT function to return the second and third columns as
a varchar, using style 1 and style 10, respectively.
• Use the CAST function to return the fourth column as data type real.
9
Notes
• The start argu1n ent 1nust be an integer fro1n 1 to the length of the string.
• The ANSI standards specify a TRIM function that re1noves both leading and trailing
spaces fro1n a string. Although this function isn 't supported by SQL Server, yo u can
get the sa1ne result by co1n bining LTRIM and RTRIM (see the exa1nple in part 2 of
this figu re).
Description
• If you sort by a string colu1nn that contains nu1nbers, you 1nay receive unexpected
results. To avoid that, you can convert the string colu1nn to a nu1neric value in the
ORDER BY clause.
• If a string consists of two or 1nore co1nponents, you can parse it into its individual
co1nponents. To do that, you can use the CHARINDEX function to locate the
characters that separate the co1nponents. Then, you can use the LEFT, RIGHT,
SUBSTRING, and LEN functions to extract the individual co1nponents.
Figure 9-2 How to solve common problems that occur with string data
268 Section 2 The essential SQL skills
ISNUMERIC(-1.25 ) 1
ISNUMERIC('SQL Server' ) 0
ISNUMERIC( 2016-09-30
1 1
) 0
ABS(-1.25 ) 1.25
CEILING(-1.25 ) -1
FLOOR(-1.25 ) -2
CEILING(l.25 ) 2
FLOOR(l.25 ) 1
SQUARE(5.2786 ) 27.86361796
SQRT(l25.43 ) 11.199553562531
RAND ( ) 0.243729
Note
• To calculate the square or square root of a nu1n ber with a data type other than float or
real, you 1n ust cast it to a floating-point nu1n ber.
100% • I >
Description
• Because real values are approxi1nate, yo u ' 11 want to search fo r approxi1nate values
when retrieving real data. To do that, yo u can specify a range of values, or yo u can
use the ROUND function to search fo r rounded values.
• When yo u display real or deci1nal values, yo u 1nay want to for1nat the1n so they're
aligned on the right.
Figure 9-4 How to solve common problems that occur with nume ric data
272 Section 2 The essential SQL skills
DATEADD (datepart,number,date ) Returns the date that results fron1 adding the
specified nun1ber of datepart units to the date.
DATEDIFF ( datepart,startdate,enddate ) Returns the nun1ber of datepart units between
the specified start and end dates.
a date value for a given year, month, and day. In addition to this function, SQL
Server 2012 introduced other functions that let you create datetime,
smalldatetime, time, datetime2, and datetimeoffset values. For more information,
please search for "date and time functions" in the SQL Server documentation.
The last function (ISDATE) returns a Boolean value that indicates whether
an expression can be cast as a valid date/time value. This function is useful
for testing the validity of a date/time value before it's saved to a table. This is
illustrated by the last set of examples. Here, you can see that the first and third
expressions are valid dates, but the second and fourth expressions aren't. The
second expression isn't valid because the month of September has only 30 days.
And the fourth expression isn't valid because a time value can have a maximum
of 59 minutes and 59 seconds. Note that this function checks for both a valid
date/time format and a valid date/time value.
The first two sets of examples illustrate the differences between the functions
that return date/time values. To start, there's a 7 hour difference between the
datetime value that's returned by the GETDATE and GETUTCDATE functions.
That's because I ran these functions from California, which is 7 hours behind the
Universal Time Coordinate (UTC). In addition, note that the datetime2(7) value
that's returned by the SYSDATETIME function provides more precise fractional
second values than the datetime value that's returned by the GETDATE and
GETUTCDATE functions. Finally, note that the SYSDATETIMEOFFSET
function returns a datetimeoffset value that includes a time zone offset.
The third set of examples shows how you can use the date parts with the
DATEPART and DATENAME functions. To start, you don't need to specify a
date part when you use the MONTH function to return an integer value for the
month. However, you can get the same result with the DATEPART function by
specifying the month date part as the first argument. Or, if you want to return
the name of the month as a string of characters, you can specify the month date
part as the first argument of the DATENAME function. Finally, you can use an
abbreviation for a date part whenever that makes sense. However, I generally
prefer to avoid abbreviations as they tend to make the code more difficult to read
and understand.
The fourth set of examples shows how to use the EOMONTH and
DATEFROMPARTS functions that were introduced with SQL Server 2012.
Here, the first expression uses the EOMONTH function to return a date for the
last day of the month for February 1, 2016. Since 2016 is a leap year, this returns
February 29, 2016. The second expression is similar, but it adds two months
to the specified date. Finally, the last expression uses the DATEFROMPARTS
function to create a date with a year value of 2016, a month value of 4, and a day
value of 3.
Chapter 9 How to use functions 275
MONTH( 2016-09-30
1 1
) 9
DATEPART(month, 2016-09-30 1 1
) 9
DATENAME(month, 2016-09-30 1 1
) September
DATENAME(m, 2016-09-301 1
) September
EOMONTH('2016-02-01') 2016-02-29
EOMONTH('2016-02-01',2) 2016-04-30
DATEFROMPARTS(2016,4,3) 2016-04-03
ISDATE( 2016-09-30
1 1
) 1
ISDATE('2016-09-31') 0
ISDATE('23:59:59') 1
ISDATE( 23:99:99
1 1
) 0
Notes
• When you use weekday with the DATEPART function, it returns an integer that indicates
the day of the week where l =S unday, 2=Monday, etc.
• The DAY, MONTH, and YEAR functions are ANSI-standard functions. The DATEPART
and DATENAME functions are 1nore general-purpose functions provided by SQL Server.
Figure 9-6 How to parse dates and times
278 Section 2 The essential SQL skills
Description
• You can use the DATEADD function to subtract a specified nu1nber of date parts fro1n a
date by coding the nu1nber of date parts as a negative value.
• If the nu1nber of date parts you specify in the DATEADD function isn't an integer, the fractional
portion of the nu1nber is ignored.
• If the end date you specify in a DATEDIFF function is before the start date, the function
will return a negative value.
• You can also use the addition and subtraction operators to add and subtract days fro1n a
date value. To add and subtract days fro1n a date string, cast the string to a date/ti1ne value.
• You can also calculate the nu1nber of days between two dates by subtracting the date/ti1ne
values and converting the result to an integer.
A SELECT statement that searches for month , day, and year components
SELECT* FROM DateSample
WHERE MONTH( StartDate ) = 1 0 AND
DAY (StartDate ) = 28 AND
YEAR (StartDate ) = 2011;
A SELECT statement that uses the CAST function to remove time values
SELECT* FROM DateSample
WHERE CAST (CAST (StartDate AS char ( 11 )) AS datetime ) = 1
20 11-10 -28 1
;
A SELECT statement that uses the CONVERT function to remove time values
SELECT* FROM DateSample
WHERE CONVERT (datetime, CONVERT ( char ( 1 0) , StartDate, 110)) = 1
20 11-10 -28 1
;
Description
• If you perfor1n a search using a date string that doesn 't include the ti1ne, the date
string is converted i1nplicitly to a date/ti1ne value with a zero ti1ne co1nponent.
Then, if the date colu1nns you 're searching have non-zero ti1ne co1nponents, you
have to acco1n1nodate the ti1nes in the search condition.
Note that the second technique (searching for a range of dates) is the only
technique that doesn't use any functions in the WHERE clause. Because of that,
this is the most efficient technique for searching for dates. As a result, you may
want to use it even if you 're using SQL Server 2008 or later.
A SELECT statement that removes date values (prior to SQL Server 2008)
SELECT* FROM DateSample
WHERE CONVERT(datetime, CONVERT(ehar(12 } , StartDate, 8 }} >= 1 09:00:00 1 AND
CONVERT(datetime, CONVERT(char(12 ) , StartDate, 8 )) < 12:59:59:999 1 1
;
Description
• If you perfor1n a search using a date string that includes only a ti1ne, the date is
converted i1nplicitly to a date/ti1ne value with a default date co1nponent of
1900-01-01. Then, if the date colu1nns you 're searching have other dates, you have
to acco1n1nodate those dates in the search condition.
Description
• The si1nple CASE function tests the expression in the CASE clause against the
expressions in the WHEN clauses. Then, the function returns the result expression
associated with the first test that results in an equal condition.
• The searched CASE function tests the conditional expression in each WHEN clause
in sequence and returns the result expression for the first condition that evaluates to
true.
Description
• The IIF and CHOOSE functions are known as logical functions, and they were
introduced with SQL Server 20 12.
• The IIF function lets you test an expression and return one value if the expression
is true and another value if the expression is false. It provides a shorthand way of
coding a searched CASE function with a single WHEN clause and an ELSE clause.
• The CHOOSE function provides an index into a list of values. The index value
1n ust be a type that can be converted to an int value and it 1n ust range fro1n 1 to the
nu1nber of values in the list.
Description
• The COALESCE and ISNULL functions let you substitute non-null values fo r null
values.
• The COALESCE function returns the first expression in a list of expressions that
isn 't null. All of the expressions in the list 1n ust have the sa1n e data type. If all of
the expressions are null, this function returns a null value.
• The ISNULL function returns the expression if it isn 't null. Otherwise, it returns
the value you specify. The expression and the value 1n ust have the sa1n e data type.
• COALESCE is not an ANSI-standard function, but it's 1n ore widely supported than
ISNULL, which is unique to SQL Server.
2 NJ Fai.rfield 1
3 NJ East Brunswick 2
4 NJ AU 4
5 IA Washington 1
6 IA Fairfield 1
7 IA All 2
8 All All 6
Description
• You can use the GROUPING function to deter1nine when a null value is assigned to
a colu1nn as the result of the ROLLUP or CUBE operator. The colu1nn you na1ne in
this function 1nust be one of the colu1nns na1ned in the GROUP BY clause.
• If a null value is assigned to the specified col u1nn as the result of the ROLLUP or
CUBE operator, the GROUPING function returns a value of 1. Otherwise, it returns
a value of 0.
• You typically use the GROUPING function with the CASE function. Then, if the
GROUPING function returns a value of 1, you can assign a value other than null to
the colu1nn.
Description
• The ROW_NUMBER, RANK, DENSE_RANK, and NTILE functions are known
as ranking functions, and they were introduced with SQL Server 2005 .
• The ROW _NUMBER function returns the sequential nu1nber of a row within a
partition of a result set, starting at 1 for the first row in each partition.
• The ORDER BY clause of a ranking function specifies the sort order in which the
ranking function is applied.
• The optional PARTITION BY clause of a ranking function specifies the colu1nn
that's used to divide the result set into groups.
The third example shows how the RANK and DENSE_RANK functions
work. You can use these functions to rank the rows in a result set. In this
example, both the RANK and the DENSE_RANK functions sort all invoices in
the Invoices table by the invoice total. Since the first three rows have the same
invoice total, both of these functions give these three rows the same rank, 1.
However, the fourth row has a different value. To calculate the value for this row,
the RANK function adds 1 to the total number of previous rows. In other words,
since the first three rows are tied for first place, the fourth row gets fourth place
and is assigned a rank of 4.
The DENSE_RANK function, on the other hand, calculates the value for the
fourth row by adding 1 to the rank for the previous row. As a result, this function
assigns a rank of 2 to the fourth row. In other words, since the first three rows are
tied for first place, the fourth row gets second place.
The fourth example shows how the NTILE function works. You can use
this function to divide the rows in a partition into the specified number of
groups. When the rows can be evenly divided into groups, this function is easy
to understand. For example, if a result set returns 100 rows, you can use the
NTILE function to divide this result set into 10 groups of 10. However, when the
rows can't be evenly divided into groups, this function is a little more difficult
to understand. In this figure, for example, the NTILE function is used to divide
a result set that contains 5 rows. Here, the first NTILE function divides this
result into 2 groups with the first having 3 rows and the second having 2 rows.
The second NTILE function divides this result set into 3 groups with the first
having 2 rows, the second having 2 rows, and the third having 1 row. And so on.
Although this doesn't result in groups with even numbers of rows, the NTILE
function creates the number of groups specified by its argument.
In this figure, the examples for the RANK, DENSE_RANK, and NTILE
functions don't include PARTITION BY clauses. As a result, these functions are
applied to the entire result set. However, whenever necessary, you can use the
PARTITION BY clause to divide the result set into groups just as shown in the
second example for the ROW _NUMBER function.
Chapter 9 How to use functions 295
Description
• The RANK and DENSE_RANK functions both return the rank of each row within
the partition of a result set.
• If there is a tie, both of these functions give the sa1ne rank to all rows that are tied.
• To deter1nine the rank for the next distinct row, the RANK function adds 1 to the
total nu1nber of rows, while the DENSE_RANK function adds 1 to the rank for the
previous row.
Description
• The NTILE function divides the rows in a partition into the specified nu1nber of
groups.
• If the rows can ' t be evenly divided into groups, the later groups 1nay have one less
row than the earlier groups.
"
Description
• The FIRST_ VALUE, LAST_ VALUE, LEAD , LAG, PERCENT_RANK,
CUME_DIST, PERCENTILE_ CONT, and PERCENTILE_DISC functions are
known as analytic functions. They were introduced with SQL Server 20 12.
• The FIRST_ VALUE function returns the first value in a sorted set of values, and
the LAST_ VALUE function returns the last value in a sorted set of values. When
yo u use the PARTITION BY clause with LAST_ VALUE, yo u typically include the
ROWS or RANGE clause as well.
The LEAD and LAG functions let you refer to values in other rows of the
result set. The LAG function is illustrated in the second example in this figure.
Here, the OVER clause is used to group the result set by rep ID and sort it by
year. Then, the LAG function in the fourth column gets the sales total from one
row prior to the current row (the offset). Since the rows are sorted by year for
each sales rep, that means that the function retrieves the sales rep's sales for
the previous year. The fifth column uses the same function, but it subtracts the
result of this function from the current sales to show the change in sales from
the previous year. The LEAD function is similar, but it lets you refer to values in
following rows rather than preceding rows.
Notice that the value of the LAG function for the first row for each sales rep
is 0.00. That's because there isn't a row for the prior year. By default, this value
is NULL. Because I wanted to calculate the change for each row in the result set,
though, I set the third argument of the LAG function (default) to 0.
The third example in this figure shows how to use all four of the remaining
functions. Each of these functions groups the rows by year and sorts them by
sales total in ascending sequence. Notice, though, that the ORDER BY clause
for the PERCENTILE_CONT and PERCENTILE_DISC functions isn't
specified on the OVER clause. Instead, it's specified on the WITHIN GROUP
clause, which, unlike the OVER clause, allows for the result set to be sorted only
by a single column.
The PERCENT_RANK function calculates a percent that indicates the rank
of each row within a group. The result of this function is always a value between
0 and 1. If you study the results in this example, you shouldn't have any trouble
understanding how this function works.
The CUME_DIST function is similar, but it calculates the percent of values
that are less than or equal to the current value. This function represents the
cumulative distribution of the values. The cumulative distribution is calculated
by dividing the number of rows with the current value or a lower value by the
total number of rows in the group.
The PERCENTILE_CONT and PERCENTILE_DISC functions calculate
the value at the percentile you specify. The difference between these two
functions is that PERCENTILE_CONT is based on a continuous distribution of
values, and PERCENTILE_DISC is based on a discrete distribution of values.
This means that the value returned by PERCENTILE_CONT doesn't need to
appear in the result set, but the value returned by PERCENTILE_DISC does.
In this example, these functions are used to calculate the median of the
sales totals for each year (the value in the middle). Because there are an odd
number of rows for 2014 and 2015, both functions return the value in the middle
row. Because there are an even number of rows for 2016, though, there isn't
a middle value. In that case, the PERCENTILE_CONT function calculates
the median by adding the two middle values together and dividing by 2. As
you can see, the resulting value doesn't exist in the result set. In contrast, the
PERCENTILE_DISC function uses the CUME_DIST function to identify the
row with a cumulative distribution of .5 (the same percentile specified by the
PERCENTILE_DISC function), and it uses the value of that row as the result.
Chapter 9 How to use functions 299
Description
• The LEAD function retrieves data fro1n a subsequent row in a result set, and the LAG
function retrieves data fro1n a previous row in a result set.
• The PERCENT_RANK function calculates the rank of the values in a sorted set of
values as a percent. The CUME_DIST function calculates the percent of the values in a
sorted set of values that are less than or equal to the current value.
• The PERCENTILE_CONT and PERCENTILE_DISC functions calculate the value at
the specified percentile for a sorted set of val ues. PERCENTILE_CONT returns an exact
percentile, and PERCENTILE_DIST returns a value that exists in the sorted colu1nn.
Perspective
In this chapter, you learned about many of the functions that you can use
to operate on SQL Server data. At this point, you have all of the essential skills
you need to develop SQL code at a professional level.
However, there's a lot more to learn about SQL Server. In the next section
of this book, then, you '11 learn the basic skills for designing a database. Even
if you never need to design your own database, understanding this material
will help you work more efficiently with databases that have been designed by
others.
Terms
logical functions cumulative distribution
ranking functions continuous distribution
analytic functions discrete distribution
Exercises
1. Write a SELECT statement that returns two columns based on the Vendors
table. The first column, Contact, is the vendor contact name in this format:
first name followed by last initial (for example, "John S.") The second
column, Phone, is the VendorPhone column without the area code. Only
return rows for those vendors in the 559 area code. Sort the result set by first
name, then last name.
2. Write a SELECT statement that returns the InvoiceNumber and balance due
for every invoice with a non-zero balance and an InvoiceDueDate that's less
than 30 days from today.
3. Modify the search expression for InvoiceDueDate from the solution for
exercise 2. Rather than 30 days from today, return invoices due before the last
day of the current month.
4. Write a summary query WITH CUBE that returns LineitemSum (which
is the sum of InvoiceLineitemAmount) grouped by Account (an alias for
AccountDescription) and State (an alias for VendorState). Use the CASE and
GROUPING function to substitute the literal value"* ALL*" for the summary
rows with null values.
5. Add a column to the query described in exercise 2 that uses the RANK()
function to return a column named BalanceRank that ranks the balance due in
descending order.
Section 3
Database design
and implementation
In large programming shops, database administrators are usually
responsible for designing the databases that are used by production
applications, and they may also be responsible for the databases that are
used for testing those applications. Often, though, programmers are asked
to design, create, or maintain small databases that are used for testing. And
in a small shop, programmers may also be responsible for the production
databases.
So whether you 're a database administrator or a SQL programmer,
you need the skills and knowledge presented in this section. That's true
even if you aren't ever called upon to design or maintain a database. By
understanding what's going on behind the scenes, you '11 be able to use
SQL more effectively.
So, in chapter 10, you' 11 learn how to design a SQL Server database.
In chapter 11, you'll learn how to use the Data Definition Language (DDL)
statements to create and maintain the SQL Server objects of a database.
And in chapter 12, you'll learn how to use the Management Studio to do
the same tasks.
10
How to design a database
In this chapter, you'll learn how to design a new database. This is useful
information for the SQL programmer whether or not you ever design a
database on your own. To illustrate this process, I'll use the accounts payable
(AP) system that you've seen throughout this book because that will make it
easier for you to understand the design techniques.
People
Documents
►
Facilities
Other
••••
••••
~--··
;
Columns
■-■i,
systems
••••
--
The six basic steps for designing a data structure
Step 1: Identify the data ele1nents
Step 2 : Subdivide each ele1nent into its s1nallest useful co1nponents
Step 3 : Identify the tables and assign coluilnns
Step 4 : Identify the pri1nary and foreign keys
Step 5: Review whether the data structure is nor1nalized
Step 6 : Identify the indexes
Description
• A relational database syste1n should 1nodel the real-world environ1nent where it's
used. The job of the designer is to analyze the real-world syste1n and then 1nap it
onto a relational database syste1n.
• A table in a relational database typically represents an object, or entity, in the real
world. Each colu1nn of a table is used to store an attribute associated with the
entity, and each row represents one instance of the entity.
• To 1nodel a database and the relationships between its tables after a real-world
syste1n, you can use a technique called entity-relationship (ER) modeling. So1ne of
the diagra1ns you ' 11 see in this chapter apply the basic ele1nents of ER 1nodeling.
Description
• Depending on the nature of the system, you can identify data elements in a variety
of ways, including interviewing users, analyzing existing systems, and evaluating
comparable systems.
• The documents used by a real-world system, such as the invoice shown above, can
often help you identify the data elements of the system.
• As you identify the data elements of a system, you should begin thinking about
the entities that those elements are associated with. That will help you identify the
tables of the database later on.
Vendor sales contact first name Vendor sales contact last name
Ruben Goldberg
An address that's divided into street address, city, state, and zip code
Vendor address
1234 West Industrial Way, East Los Angeles , Californ ia 90022
Description
• If a data ele1nent contains two or 1nore co1nponents, you should consider
subdividing the ele1nent into those co1nponents. That way, you won 't need to parse
the ele1nent each ti1ne you use it.
• The extent to which you subdivide a data ele1nent depends on how it will be used.
Because it's difficult to predict all future uses for the data, 1nost designers subdivide
data ele1nents as 1nuch as possible.
• When you subdivide a data ele1nent, you can easily rebuild it when necessary by
concatenating the individual co1nponents.
Description
• After yo u identify and subdivide all of the data ele1nents for a database, yo u should
group the1n by the entities with which they're associated. These entities will later
beco1ne the tables of the database, and the ele1nents will beco1ne the colu1nns.
• If a data ele1nent relates to 1nore than one entity, yo u can include it under all of the
entities it relates to. Then, when yo u nor1nalize the database, yo u 1nay be able to
re1nove the duplicate ele1nents.
• As yo u assign the ele1nents to entities, yo u should 01nit ele1nents that aren't needed,
and yo u should add any additional ele1nents that are needed.
Description
• Most tables should have a pri1nary key that uniquely identifies each row. If
necessary, you can use a composite key that uses two or 1nore colu1nns to uniquely
identify each row.
• The values of the pri1nary keys should seldorn, if ever, change. The values should
also be short and easy to enter correctly.
• If a suitable colu1nn doesn 't exist, you can create an identity colu1nn that can be
used as the pri1nary key.
• If two tables have a one-to-1nany relationship, you 1nay need to add a foreign key
colu1nn to the table on the "1nany" side. The foreign key colu1nn 1n ust have the
sa1ne data type as the pri1nary key colu1nn it' s related to.
• If two tables have a 1nany-to-1nany relationship, you ' 11 need to define a linking
table to relate the1n. Then, each of the tables in the 1nany-to-1nany relationship will
have a one-to-1nany relationship with the linking table. The linking table doesn 't
usually have a pri1nary key.
• If two tables have a one-to-one relationship, they should be related by their pri1nary
keys. This type of relationship is typically used to i1nprove perfor1nance. Then,
colu1nns with large a1nounts of data can be stored in a separate table.
Figure 10-5 How to identify the primary and fore ign keys
314 Section 3 Database design and implementation
connecting table or an associate table. This table contains the primary key
columns from the two tables. Then, each table has a one-to-many relationship
with the linking table. Notice that the linking table doesn't have its own primary
key. Because this table doesn't correspond to an entity and because it's used only
in conjunction with the Employees and Committees tables, a primary key isn't
needed.
The third example in figure 10-5 illustrates two tables that have a one-to-one
relationship. With this type of relationship, both tables have the same primary
key, which means that the information could be stored in a single table. This
type of relationship is often used when a table contains one or more columns
with large amounts of data. In this case, the EmployeePhotos table contains a
large binary column with a photo of each employee. Because this column is used
infrequently, storing it in a separate table will make operations on the Employees
table more efficient. Then, when this column is needed, it can be combined with
the columns in the Employees table using a join.
Description
• Referential integrity 1neans that the relationships between tables are 1naintained
correctly. That 1neans that a table with a foreign key doesn 't have rows with foreign
key values that don 't have 1natching pri1nary key values in the related table.
• In SQL Server, yo u can enforce referential integrity by using declarative referential
integrity or by defining triggers.
• To use declarative referential integrity (DRI), yo u define foreign key constraints.
Yo u' ll learn how to do that in the next two chapters.
• When yo u define foreign key constraints, yo u can specify how referential integrity
is enforced when a row is deleted fro1n the pri1nary key table. The options are to
return an error or to delete the related rows in the foreign key table.
• Yo u can also specify how referential integrity is enforced when the pri1nary key of
a row is changed and foreign key constraints are in effect. The options are to return
an error or to change the foreign keys of all the related rows to the new value.
• If referential integrity isn 't enforced and a row is deleted fro1n the pri1nary key
table that has related rows in the foreign key table, the rows in the foreign key table
are said to be orphaned.
• The three types of errors that can occur when referential integrity isn 't enforced are
called the deletion anomaly, the insertion anomaly, and the update anomaly.
2 112897 SQL ad
3 112897 Library directory
4 97/ 522 Catalogs
5 97/522 SQLflyer I
L.....L• TermslD
TermsDescription
TermsDueDays
Description
• Normalization is a for1nal process yo u can use to separate the data in a data
structure into related tables. Nor1nalization reduces data redundancy, which can
cause storage and 1naintenance proble1ns.
• In an unnormalized data structure, a table can contain infor1nation abo ut two or
1nore entities. It can also contain repeating colu1nns, colu1nns that contain repeating
values, and data that's repeated in two or 1nore rows.
• In a normalized data structure, each table contains infor1nation abo ut a single
entity, and each piece of infor1nation is stored in exactly one place.
• To nor1nalize a data structure, yo u apply the normal form s in sequence. Altho ugh
there are a total of seven nor1nal for1ns , a data structure is typically considered
nor1nalized if the first three nor1nal for1ns are applied.
Description
• An index provides a way for SQL Server to locate information more quickly. When
it uses an index, SQL Server can go directly to a row rather than having to search
through all the rows until it finds the ones you want.
• An index can be either clustered or nonclustered. Each table can have one clustered
index and up to 249 nonclustered indexes.
• The rows of a table are stored in the sequence of the clustered index. By default,
SQL Server creates a clustered index for the primary key. If you don't identify a
primary key, the rows of the table are stored in the order in which they're entered.
• Indexes speed performance when searching and joining tables. However, they can't
be used in search conditions that use the LIKE operator with a pattern that starts
with a wildcard. And they can't be used in search conditions that include functions
or expressions.
• You can create composite indexes that include two or more columns. You should
use this type of index when the columns in the index are updated infrequently or
when the index will cover almost every search condition on the table.
• Because indexes must be updated each time you add, update, or delete a row, you
shouldn't create more indexes than you need.
Description
• Each nor1nal fo r1n assu1nes that the design is already in the previous nor1nal fo r1n.
• A database is typically considered to be nor1nalized if it is in third nor1nal fo r1n.
The other fo ur fo r1ns are not co1n1nonly used and are not covered in detail in this
book.
Description
• For a table to be in first nor1nal for1n, its colu1nns 1n ust not contain repeating
values. Instead, each colu1nn 1n ust contain a single, scalar value. In addition, the
table 1n ust not contain repeating colu1nns that represent a set of values.
• A table in first nor1nal for1n often has repeating values in its rows. This can be
resolved by applying the second nor1nal for1n.
1
InvoiceID InvoiceSequence Item Description
1 L,. . . . . . . . . . . .~ 1 VB ad
2 1 2 SQLad
3 1 3 Library directory
4 2 1 Catalogs
5 2 2 SQLflyer
6 3 1 Card revision
=
Description
• For a table to be in second normal form, every non-key column must depend on
the entire primary key. If a column doesn't depend on the entire key, it indicates
that the table contains information for more than one entity. This is reflected by the
table's composite key.
• To apply second normal form, you move columns that don't depend on the entire
primary key to another table and then establish a relationship between the two
tables.
• Second normal form helps remove redundant row data, which can save storage
space, make maintenance easier, and reduce the chance of storing inconsistent data.
L.....L.• TermslD
Terms Description
Terms Due Days
Description
• For a table to be in third nor1n al fo r1n, every non-key colu1n n 1nust depend o nly o n
the pri1n ary key.
• If a colu1n n doesn't depend only o n the pri1n ary key, it i1n plies that the colu1n n is
assigned to the wro ng table or that it can be co1n puted fro1n other colu1n ns in the
table. A colu1n n that can be co1nputed fro1n o ther colu1n ns co ntains derived data.
When to denormalize
• When a colu1nn fro1n a joined table is used repeatedly in search criteria, you should
consider 1noving that colu1nn to the pri1nary key table if it will eli1ninate the need
for a join.
• If a table is updated infrequently, you should consider denor1nalizing it to i1nprove
efficiency. Because the data re1nains relativel y constant, you don ' t have to worry
about data redundancy errors once the initial data is entered and verified.
• Include colu1nns with derived values when those values are used frequently in
search conditions. If you do that, you need to be sure that the colu1nn value is
always synchronized with the value of the colu1nns it's derived fro1n.
Description
• Data structures that are nor1nalized to the fourth nor1nal for1n and beyond typically
require 1nore joins than tables nor1nalized to the third nor1nal for1n.
• Most designers denormalize data structures to so1ne extent, usually to the third
nor1nal f or1n.
• Denormalization can result in larger tables, red undant data, and red uced
perfor1nance.
• Only denor1nalize when necessary. It is better to adhere to the nor1nal for1ns unless
it is clear that perfor1nance will be i1nproved by denor1nalizing.
Perspective
Database design is a complicated subject. Because of that, it's impossible
to teach you everything you need to know in a single chapter. With the skills
you've learned in this chapter, however, you should now be able to design
simple databases of your own. More important, you should now be able to
evaluate the design of any database that you work with. That way, you can be
sure that the queries you code will be as efficient and as effective as possible.
One aspect of database design that isn't covered in this chapter is
designing the security of the database. Among other things, that involves
creating login IDs and database users and assigning permissions. It may also
involve organizing the tables and other objects in the database into two or
more schemas. You'll learn more about how to implement database security in
chapter 17.
Terms
data structure deletion anomaly
entity normalization
attribute data redundancy
instance unnormalized data structure
entity-relationship (ER) modeling normalized data structure
CASE (computer-aided software normal forms
engineering) index
composite key table scan
linking table clustered index
connecting table nonclustered index
associate table composite index
referential integrity covering index
declarative referential integrity Boyce-Codd normal form
(DRI) transitive dependency
foreign key constraints multivalued dependency
triggers domain-key normal form
orphaned row derived data
update anomaly denormalized data structure
insertion anomaly denormalization
Chapter 10 How to design a database 331
Exercises
1. Design a database diagra1n for a product orders database with four tables.
Indicate the relationships between tables and identify the pri1nary key and
foreign keys in each table. Explain your design decisions.
Customers Orders Orderlineltems
CustomerlD OrderslD Ord erlD
CustomerName CustomerlD Ord erSequence
CustomerAddress OrderDate ProductlD
CustomerPhone ShipAddress Quantity
ShipDate UnitPrice
Products
Produ ctlD
ProductName
QtyPerUnit
UnitPrice
In Stock
OnOrder
2. Add the two tables below into the design for exercise 1. Create additional
tables and colu1nns, if necessary. Explain your design decisions.
Shippers Employees
ShipperlD Empl oyeelD
Sh ipperName FirstName
Sh ipperAddress LastName
Sh ipperPhone SSN
Hire Date
3. Modify your design for exercise 2 to identify the colu1nns that should be
indexed, and explain your decision.
4. Design a database diagra1n that allows individuals to be assigned 1ne1nbership
in one or 1nore groups. Each group can have any nu1nber of individuals and
each individual can belong to any nu1nber of groups. Create additional tables
and colu1nns, if necessary. Explain your design decisions.
5. Modify your design for exercise 4 to keep track of the role served by each
individual in each group. Each individual can only serve one role in each
group. Each group has a unique set of roles that 1ne1nbers can fulfill. Create
additional tables and colu1nns, if necessary. Explain your design decisions.
11
An introduction to DDL
All of the SQL statements that you've seen so far have been part of the data
manipulation language, or DML. But now, you'll learn how to use the SQL
statements that are part of the data definition language. You use these statements
to define the objects of a database.
Description
• Yo u use the data definition language (DDL) state1nents to create, 1nodify, and
delete database objects such as the database itself, the tables contained in a
database, and the indexes for those tables.
• Typically, a database ad1ninistrator is responsible for using the DDL state1nents on
production databases in a large database syste1n. However, every SQL progra1n1ner
should be co1nfortable using these state1nents so that they can create and work with
s1nall databases for testing.
• In 1nost cases, yo u '11 use the graphical user interface of the Manage1nent Studio
to create and 1naintain database objects as described in chapter 12. Altho ugh the
Manage1nent Studio generates DDL state1nents for yo u, yo u 1nay need to verify or
correct these state1nents. To do that, yo u need to understand their syntax and use.
• If yo u use a SQL database other than SQL Server, it 1nay not have a graphical tool
for 1nanaging database objects. In that case, yo u 1nust use the DDL state1nents.
Description
• The name of an object in SQL Server is called its identifier. Most objects are
assigned an identifier when they're created. Then, the identifier can be used to refer
to the object.
• SQL Server provides for two classes of identifiers. Regular identifiers follow the
formatting rules for identifiers. Delimited identifiers are enclosed in brackets([]) or
1111
double quotation marks ( and may or may not follow the formatting rules. If an
)
Description
• The CREATE DATABASE statement creates a new, empty database on the current
server. Although the ANSI standards don't include this statement, it's supported by
virtually all SQL database systems. The optional clauses shown here, however, are
supported only by SQL Server.
• If you code this statement without any options, the new database is created using
the default settings and the database files are stored in the default directory on the
hard drive. For most small database projects, these settings are acceptable.
• One of the files SQL Server creates when it executes the CREATE DATABASE
statement is a transaction log file. This file is used to record modifications to the
database. SQL Server generates the name for this file by appending "_log" to the
end of the database name. The database name is limited to 123 characters.
• If you have a copy of a database file that you'd like to work with on your server,
you can use the FOR ATTACH clause in addition to the ON PRIMARY clause to
attach the file as a database to the current server.
• Most of the optional clauses that have been omitted from this syntax are used to
specify the underlying file structure of the database. These clauses are used by
DBAs to tune the performance of the database. See the SQL Server documentation
for details.
Warning
• On some systems, the CREATE DATABASE statement can overwrite an existing
database. Because of that, you '11 want to check with the DBA before using this
statement.
Description
• The CREATE TABLE state1nent creates a table based on the colu1nn definitions,
colu1nn attributes, and table attributes yo u specify. A database can contain as 1nany
as two billion tables.
• A table can contain between one and 1,024 colu1nns. Each colu1nn 1nust have a
unique na1ne and 1nust be assigned a data type. In addition, yo u can assign one or
1nore of the colu1nn attributes shown above.
• Yo u can also assign one or 1nore constraints to a colu1nn or to the entire table. See
fig ures 11-7, 11-8, and 11-9 for details.
• For the co1nplete syntax of the CREATE TABLE state1nent, refer to the SQL Server
docu1nentation.
values, you should only use it when a column contains a high percentage of
null values. As a general guideline, it usually makes sense to use the SPARSE
attribute when at least 60% of the column's values are null.
Description
• You use the CREATE INDEX statement to create an index for a table. An index can
improve performance when SQL Server searches for rows in the table.
• SQL Server automatically creates a clustered index for a table's primary key. If
that's not what you want, you can drop the primary key constraint using the ALTER
TABLE statement shown in figure 11-11 and then recreate the primary key with a
nonclustered index.
• Each table can have a single clustered index and up to 249 nonclustered indexes.
SQL Server automatically creates a nonclustered index for each unique key other
than the primary key.
• By default, an index is sorted in ascending sequence. If that's not what you want,
you can code the DESC keyword. The sequence you use should be the sequence in
which the rows are retrieved most often when using that index.
• A full-table index is an index that applies to every row in the table.
• A filtered index is a type of nonclustered index that includes a WHERE clause that
filters the rows that are included in the index. Filtered indexes were introduced with
SQL Server 2008.
• A filtered index can improve performance when the number of rows in the index is
small compared to the total number of rows in the table.
• For more details about working with filtered indexes, refer to the SQL Server
documentation.
100 % •
100 % .,
Description
• Transact-SQL snippets help you write state1nents fo r creating database objects.
• To insert a Transact-SQL snippet, right-click in the Query Editor window and select
the Insert Snippet co1n1nand fro1n the resulting 1nenu. Then, use the snippet picker
to select a snippet.
• To select a snippet using the snippet picker, do uble-click on the folder for the
object you want to create, then do uble-click on a snippet in the list that's displayed.
Alternatively, you can select the folder or snippet and then press the Tab or Enter
key.
• O nce a snippet has been inserted, you can replace the highlighted portions with
your own code and add any other req uired code. To 1nove fro1n one highlighted
portion of code to the next, press the Tab key. To 1nove to the previous highlighted
portion, press the Shift+Tab keys.
An introduction to constraints
Figure 11-7 summarizes the five types of constraints provided by SQL
Server. Except for NOT NULL, each of these constraints can be coded at either
the column level or the table level. You've already seen how to code a primary
key constraint at the column level, and you can code a unique key constraint in
the same way. Now, the first example in this figure shows how to code a primary
key constraint at the table level.
In this example, the primary key consists of two columns. Because of that,
it can't be defined at the column level. Notice that when you code a constraint
at the table level, you must code a comma at the end of the preceding column
definition. If you don't, SQL Server will try to associate the constraint with the
preceding column, and an error will result.
Two types of constraints you haven't seen yet are check constraints and
foreign key constraints. You'll learn more about these types of constraints in the
next two topics. To illustrate the difference between column-level constraints
and table-level constraints, however, the second and third examples in this
figure show two ways you can code the same two check constraints. The first
example uses column-level constraints to limit the values in the InvoiceTotal
and PaymentTotal columns to numbers greater than or equal to zero. The second
example uses a compound condition to specify both constraints at the table level.
Although the first technique is preferred, the second example illustrates that a
table-level constraint can refer to any of the columns in a table. In contrast, a
column-level constraint can refer only to the column that contains the constraint.
Chapter 11 How to create a database and its tables with SQL statements 347
The same statement with the check constraints coded at the table level
CREATE TABLE Invoices2
( InvoiceID INT NOT NULL IDENTITY PRIMARY KEY,
InvoiceTotal MONEY NOT NULL,
PaymentTotal MONEY NOT NULL DEFAULT 0 ,
CHECK (( Invo i c eTo tal >= 0 ) AND ( PaymentTo tal
Description
• Constraints are used to enforce the integrity of the data in a table by defining rules abo ut
the values that can be stored in the colu1nns of the table. Constraints can be used at the
colu1nn level to restrict the value of a single colu1nn or at the table level to restrict the
value of one or 1nore colu1nns.
• Yo u code a column-level constraint as part of the definition of the colu1nn it constrains.
Yo u code a table-level constraint as if it were a separate colu1nn definition, and yo u na1ne
the colu1nns it constrains within that definition.
• Constraints are tested before a new row is added to a table or an existing row is updated.
If the new or 1nodified row 1neets all of the constraints, the operation succeeds. Otherwise,
an error occurs and the operation fails.
Description
• Check constraints li1nit the values that can be stored in the colu1nns of a table.
• The condition you specify for a check constraint is evaluated as a Boolean expres-
sion. If the expression is true, the insert or update operation proceeds. Otherwise, it
fails.
• A check constraint that's coded at the colu1nn level can refer only to that colu1nn. A
check constraint that's coded at the table level can refer to any colu1nn in the table.
Description
• You use the FOREIGN KEY clause to define aforeign key constraint, also called a
reference constraint. A foreign key constraint defines the relationship between two
tables and enforces referential integrity.
• A foreign key constraint that's coded at the colu1nn level can only relate a single colu1nn
in the new table to a single colu1nn in the related table. A constraint that's coded at the
table level can relate two tables by two or 1nore colu1nns.
• Typically, a foreign key constraint refers to the pri1nary key of the related table. However,
it can also refer to a unique key.
• The ON DELETE clause specifies what happens to rows in the table if the row in the
related table with the sa1ne key value is deleted. The ON UPDATE clause specifies what
happens to rows in the table if the key of the related row is updated.
• The CASCADE keyword causes the rows in this table to be deleted or updated to 1natch
the row in the related table. This is known as a cascading delete or a cascading update.
• The NO ACTION keyword prevents the row in the related table fro1n being deleted
or updated and causes an error to be raised. T his is usually the preferred option.
Description
• You can use the DROP INDEX statement to delete one or more indexes from one
or more tables in any database on the current server.
• You can use the DROP TABLE statement to delete one or more tables from any
database on the current server. To delete a table from a database other than the
current database, you must qualify the table name with the database name.
• You can use the DROP DATABASE statement to delete one or more databases
from the current server.
• You can't delete a table if a foreign key constraint in another table refers to that
table.
• When you delete a table, all of the data, indexes, triggers, and constraints are
deleted. Any views or stored procedures associated with the table must be deleted
explicitly.
• You can't delete an index that's based on a primary key or unique key constraint. To
do that, you have to use the ALTER TABLE statement. See figure 11-11 for details.
Warnings
• You can't undo a delete operation. For this reason, you may want to back up the
database before you use any of these statements so you can restore it if necessary.
• You should never use these statements on a production database without first
consulting the DBA.
Description
• You use the ALTER TABLE statement to modify an existing table. You can use this
statement to add columns or constraints, drop columns or constraints, or change the
definition of an existing column, including changing the column's data type.
• Before SQL Server changes the data type of a column, it checks to be sure that no
data will be lost. If it will, the operation isn't performed.
• You can modify a column to allow null values as long as the column isn't defined
as the primary key. You can modify a column so that it doesn't allow null values as
long as none of the existing rows contain null values in that column.
• You can add a column that doesn't allow null values only if you specify a default
value for that column.
• To delete a constraint, you must know its name. If you let SQL Server generate the
name for you, you can use the Management Studio as shown in the next chapter to
look up the name.
• By default, SQL Server verifies that existing data satisfies a new check or foreign
key constraint. If that's not what you want, you can code the WITH NOCHECK
keywords.
Warning
• You should never alter a table in a production database without first consulting the DBA.
l._ 11 0 ...........................J
Description
• You use the CREATE SEQUENCE state1nent to generate integer values for a
colu1nn in one or 1nore tables.
• By default, the CREATE SEQUENCE state1nent creates a sequence with the bigint
data type that starts with the 1nini1nu1n value for the data type, is incre1nented by
a value of 1, has 1nini1nu1n and 1naxi1nu1n values based on the data type, doesn 't
specify the cache size, and doesn 't restart the sequence when the end is reached.
• You can use the NEXT VALUE FOR function to get the next value in the sequence.
• You can query the sys.sequences table to get infor1nation about a sequence.
gets the next value from the sequence named TestSequence3 so it can be inserted
into the SequenceNo column.
The last example in figure 11-12 shows how to use the sys.sequences catalog
view to get information about a sequence. You'll learn about catalog views in
chapter 13. For now, just realize that the SELECT statement shown here retrieves
the current value for the sequence from this view. If you review the starting value
and the increment for the sequence, you'll see how this works.
Description
• You can use the DROP SEQUENCE statement to delete a sequence. A sequence
can't be deleted if it's used as the default value for a column.
• You can use the ALTER SEQUENCE statement to alter the attributes of a
sequence. However, you can't change the data type, and you can't set the minimum
and maximum values so they don't make sense.
• If you omit the WITH value of the RESTART clause, the sequence is restarted
based on the current definition of the sequence.
USE AP;
CREATE TABLE Terms
(TermsID INT NOT NULL PRIMARY KEY,
TermsDescription VARCHAR ( 5 0) NOT NULL,
TermsDueDays SMALLINT NOT NULL ) ;
Note
• The Ter1ns and GLAcco unts tables are created first so the other tables can define
foreign keys that refer to the1n. Si1nilarly, the Vendors table is created before the
Invoices table, and the Invoices table is created before the l nvoiceLinel te1ns table
(see part 2).
Also notice that most of the columns in this database are assigned the NOT
NULL constraint. The exceptions are the VendorAddressl, VendorAddress2,
VendorPhone, VendorContactLName, and VendorContactFName columns in the
Vendors table and the PaymentDate column in the Invoices table. Because not all
vendor addresses will require two lines and because some vendors won't provide
a street address at all, a null value can be assigned to both address columns to
indicate that they're not applicable. Similarly, you may not have a phone number
and contact information for each vendor. For this reason, you could assign a null
value to one of these columns to indicate an unknown value. Finally, an invoice
wouldn't be assigned a payment date until it was paid. Until that time, you could
assign a null value to the PaymentDate column to indicate that it hasn't been
paid.
I could also have used a default date to indicate an unpaid invoice. To do
that, I could have defined the PaymentDate column like this:
PaymentDate SMALLDATETIME NOT NULL DEFAULT '1900-01-01'
In this case, the date January 1, 1900 would be stored in the PaymentDate
column unless another value was assigned to that column. Usually, a null value
is a more intuitive representation of an unknown value than a default such as
this, but either representation is acceptable. Keep in mind, though, that the
technique you use will affect how you query the table.
Since at least 60% of the values for the VendorAddress2 column are likely to
contain a null value, this column uses the SPARSE attribute to optimize storage
of null values. Although this attribute isn't critical, it can significantly reduce the
amount of storage required for this column.
Because each of the five tables in this database has a primary key, SQL
Server creates a clustered index for each table based on that key. In addition,
this script creates seven additional indexes to improve the performance of the
database. The first five of these indexes are based on the foreign keys that each
referring table uses to relate to another table. For example, since the VendorID
column in the Invoices table references the VendorID column in the Vendors
table, I created a nonclustered index on VendorID in the Invoices table. Similarly,
I created indexes for TermsID in the Invoices table, DefaultTermsID and
DefaultAccountNo in the Vendors table, and AccountNo in the lnvoiceLineltems
table. Finally, I created indexes for the VendorName column in the Vendors table
and the lnvoiceDate column in the Invoices table because these columns are
frequently used to search for rows in these tables.
As you may have noticed, I created an index for each column that
appears in a foreign key constraint except one: the lnvoicelD column in the
lnvoiceLineltems table. Since this column is part of the composite primary
key for this table, it's already included in the clustered index. For this reason,
the addition of a nonclustered index on InvoicelD by itself won't improve
performance.
Chapter 11 How to create a database and its tables with SQL statements 363
Notes
• The InvoiceLineitems table has a composite primary key that consists of the
InvoiceID and InvoiceSequence columns. For this reason, the PRIMARY KEY
constraint must be defined as a table-level constraint.
• In addition to the five indexes that SQL Server automatically creates for the primary
key of each table, this script creates seven additional indexes. The first five are
indexes for the foreign keys that are used in the REFERENCES constraints. The last
two create indexes on the VendorName column and the InvoiceDate column since
these columns are used frequently in search conditions.
Perspective
Now that you've completed this chapter, you should be able to create
and modify databases, tables, and indexes by coding DDL statements. This
provides a valuable background for working with any database. In practice,
though, you may sometimes want to use the Management Studio to perform the
functions that are done by DDL statements, so that's what you '11 learn to do in
the next chapter.
Terms
data definition language (DDL) column-level constraint
database objects table-level constraint
identifier check constraint
transaction log file foreign key constraint
attach a database reference constraint
full-table index cascading delete
filtered index cascading update
snippet sequence
snippet picker script
constraint batch
Chapter 11 How to create a database and its tables with SQL statements 365
Exercises
1. Create a new database na1ned Meinbership.
2. Write the CREATE TABLE state1nents needed to i1nple1nent the following
design in the Me1nbership database. Include foreign key constraints. Define
lndividualID and Gro uplD as identity colu1nns. Decide which colu1nns should
allow null values, if any, and explain your decision. Define the Dues colu1nn
with a default of zero and a check constraint to allow only positive values.
Individuals GroupMembership Groups
lndividuallD, int ---, GrouplD, int ••----◄ GrouplD, int
FirstName, varchar Y lnd ividuallD, int GroupName, varchar
LastName, varchar Dues, money
Address, varchar
Phone, varchar
~ Options
~ F'degroups Database name: INew_AP I
Owner: l<default> I CJ
Database files:
Logical Name Rle Type Rlegroup Initial Size (MB) Autogrowth / Maxsize
New_AP ROWS ... PRIMARY !l...........
3 l By 1 MB. Unlimited
........'
New_AP_log LOG Not Applicable 1 By 10 percent. Un6mited
Connection
Server:
localhost\SQLEXPRESS
Connection:
RAY-PC\Ray
~ View connection properties
Proi,ess
I Add 11 R ve I
-
I OK IL CanoetJ
RAY-PC\SQLEXPRESS...AP · dbo.lnvoices X
Column Name Data Type Allow Nulls
►~ i lnvoicelD
;
8 @ localhost\ SQLEXPRESS (SQL Server 13.0.9C " '
; int
! □
B Data bases
(B System Databases
VendorlD int
□
lnvoiceDate smalldatetime 0
l±l (j AP
l±J O Examples InvoiceTotal money 0
8 (j New_AP
1±) ~ Database Diag rams
□
8 Tables Column Properties
1±) System Tables
l±l Ll FileTables
1±) □ dbo.l nvoices v Identity Specification Yes
1±) □ dbo.Vendors (Is Identity) Yes
Ill Views Identity Increment 1
1±) Synonyms
Identity Seed 1
1±) D Prog ram mability
Ill Service Broker
1±) L] Storage
Indexable
Is Columnset
Yes
No
r
Is Sparse No
Ill Security
1±) (j ProductOrders
1±) Security
1B Server Objects ...,
Note
• When you create a table using the Manage1nent Studio, the table is auto1natically stored
in the default sche1na. If you want to transfer the table to a different sche1na, you can
use the ALTER SCHEMA state1nent. See chapter 17 for details.
The Foreign Key Relationships dialog box for the Invoices table
Foreign Key Relationships ? X
Selected Relationship:
Editing properties for new rel ationship. The 'Ta bles And Columns
Specification' property needs to be fill ed in before the new relationship will be
accepted.
v (GeneraO
Check Existing Data On Creati Yes
'> Tables And Columns Specific;
v Identity
(Name) FK_lnvoices_Vendors
Description
v Table Designer
Enforce For Replication Yes
Enforce Foreig n Key Constrair Yes
v INSERT And UPDATE Specific,
Delete Rule No Action
Relationship name:
I FK_l nvoices_Vendors
Primary key table:: Foreign key table:
[vendors I Invoices
Vendorl D
Description
• To display the Foreign Key Relationships dialog box for a table, display the table
in the Table Designer and click on the Relationships button in the toolbar.
• To add a new foreign key relationship, click on the Add button. To delete an
existing relationship, select the relationship and click on the Delete button.
• To specify the tables and colu1nns that define the relationship, select the
relationship, select the Tables And Colu1nns Specification property, and click the
button that appears to display the Tables and Colu1nns dialog box. Then, use this
dialog box to specify the pri1nary key table and the appropriate colu1nns in both
tables.
• To set other properties for a relationship, select the relationship and use the
properties grid to change the properties.
v (GeneraO
Columns VendorName (ASC)
"
Is Un iqu e No
Type Index
v Identity
(Name) IX_VendorName
Description
v Table Designer
Create As Clustered No
> Data Space Specification PRIMARY
> Fill Specification
Description
• To display the Indexes/Keys dialog box for a table, display the table in the Table
Designer and click on the Indexes and Keys button in the Table Designer toolbar.
• To add a new index, click the Add button, use the Colu1nns property to specify
the colu1nn na1ne and sort order for each colu1nn in the index, and use the Na1ne
property to enter the na1ne you want to use for the index.
• To view or edit an existing index, select the index fro1n the list box on the left side
of the dialog box. Then, you can view its properties on the right side of the dialog
box.
• To create a unique key and an index that's based on that key, use the Type property
to select the Unique Index option. When you do, the Is Unique property will
auto1natically be set to Yes.
• To create an index without creating a unique key, use the Type property to select the
Index option and set the Is Unique property to No.
• To create a clustered index, set the Create As Clustered property to Yes. If a table
already contains a clustered index, this property is grayed out to show that it isn't
available.
• The other options in this dialog box are used for perfor1nance tuning. In 1nost
cases, the default values for these options are acceptable. For 1nore infor1nation, see
Books Online.
v (Ge ne raO
Expression (InvoiceTota l > 0)
v Identity
(Name) CK_lnvoiceTotal
Description
v Table Designer
Check Existing Data On Creati Yes.
Enforce For INSERTs And UPD Yes.
Enforce For Replication Yes.
Description
• To display the Check Constraints dialog box for a table, display the table in the
Table Designer and click on the Check Constraints button in the Table Designer
toolbar.
• To add a new constraint to the table, click the Add button. Then, you 1n ust enter the
expression that defines the constraint in the Expression property, and you usually
want to use the Na1ne property to provide a 1neaningful na1ne for the constraint.
• To delete a constraint, select the constraint and click the Delete button.
• To view or edit the properties for an existing constraint, select the constraint fro1n
the list that's displayed on the left side of the dialog box.
• By default, SQL Server checks existing data when you add a new check constraint
to be sure it satisfies the constraint. If that's not what you want, you can set the
Check Existing Data On Creation Or Re-Enabling property to No.
• By default, SQL Server enforces the constraint for insert and update operations.
If that's not what you want, you can set the Enforce For INSERTs And UPDATEs
property to No.
• By default, SQL Server enforces the constraint when the database is replicated. If
that's not what you want, you can set the Enforce For Replication property to No.
Dependencies
s . •□ Mll·i·lt◄
El·· □ Invoices
L.., □ lnvoiceLJneltems
.._._
-Connedion
Server:
localhost\SQ LEXPRESS
Connection:
RAY-PC\Ray
~ View connection properties
Selected object
Pr
Name: I[RAY-PC\SQLEXPRESS).[AP).[dbo).[Vendors) I
Type:
Ready !Table
0 Dependency type :
ISchema-bound dependency I
I
I OK II Cancel ;
Description
• To view the dependencies for a table, right-click the table and select View
Dependencies to display the Object Dependencies dialog box.
• To expand or collapse a dependency, click on the plus (+) or 1nin us sign (-) that's
displayed to the left of the dependency.
• You should check table dependencies before you delete or 1nodify a colu1nn or an
entire table.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Description
• You can use the Management Studio to generate scripts to create, drop, or alter most
objects that are contained in the database. You can send each script to Management
Studio's Query Editor, a file, or to the clipboard.
• To generate a script that creates a database, right-click on the database and select
Script Database as ➔CREATE To. Then, select New Query Editor Window, File, or
Clipboard.
• To generate a script that creates a table, right-click on the table and select
Script Table as ➔ CREATE To. Then, select New Query Editor Window, File, or
Clipboard.
If you experiment with scripts, you ''11 find that you can send them to a new
Query Editor window, to a file, or to the clipboard. Most of the time, it's easiest
to send the generated script to a Query Editor window. Then, you can review
the script before you run it, save it, or copy it to the clipboard. In some cases,
though, you may want to send a script directly to a file without viewing it first.
Or, you may want to send the script to the clipboard without viewing it first so
you can paste it into another tool and use that tool to view, save, or run the script.
r To prevent any potential data loss issues, you should review this script in deta il before n "
BEGIN TRANSACTION
SET QUOTED_IDENTIFIER ON
SET ARITHABORT ON
SET NUMERJC_ROUNDABORT OFF
SET CONCAT_N ULL_YIELDS_NU LL ON
SET ANSI_NULLS ON
SET ANSI_PADDING ON
SET ANSI_WARNINGS ON
COMMIT
BEGIN TRANSACTION -
GO
ALTER TABLE dbo.lnvoices SET
< I >
.___
ve_s _ 11=-
..... No J
Description
• If you use the Table Designer to 1nodify the design of a table, you can click the
Generate Change Script button in the toolbar to display the Save Change Script
dialog box shown above. You can use this dialog box to exa1nine or save the SQL
script that the Manage1nent Studio uses to alter the table.
• If you check the Auto1natically Generate Change Script On Every Save box, the
Manage1nent Studio will pro1npt you with a Save Change Script dialog box each
ti1ne you atte1npt to save changes to the design of a table.
Perspective
In this chapter, yo u learned how to use the Manage1nent Studio to create
and work with database objects, such as tables, keys, indexes, and constraints
as well as the database itself. Now that yo u know how to use the Manage1nent
Studio to work with the design of a database, yo u 1nay be wondering when yo u
should use it for database design and when yo u should code the DDL state1nents
yo urself.
Altho ugh it's often a 1natter of preference, 1nost SQL progra1n1ners find it
easier to use the Manage1nent Studio to create and work with database objects.
That way, they don't have to worry abo ut the exact syntax of the DDL
state1nents, which they 1nay use infrequently.
However, so1ne experienced database progra1n1ners prefer to enter the
DDL state1nents the1nselves. That way, they have 1nore control over how these
scripts are coded. In addition, they can save a copy of the script that creates
the database for future reference, which 1nay be helpful if the database design
ever needs to be ported to another type of database 1nanage1nent syste1n such as
Oracle, DB2, or MyS QL.
Terms
Table Designer
replication
dependencies
Exercises
1. Use the Manage1nent Studio to create a new database called Me1nbership2
using the default settings. (If the database already exists, use the Manage1nent
Studio to delete it and then recreate it.)
2. Use the Manage1nent Studio to create the following tables and relationships in
the Me1nbership database. Define l ndivid ualID and Gro uplD as IDENTITY
colu1nns. Allow Address and Phone to accept null values; none of the other
colu1nns should allow null values. Define the Dues colu1nn with a default of
zero and a check constraint to allow only positive values. Define the DuesPaid
colu1nn with a default Boolean value of False.
Individuals GroupMembership Groups
lndividuallD, int ---, GrouplD, int ••-----4
◄ GrouplD, int
FirstName, varchar l......11111 lndividuallD, int GroupName, varchar
LastName, varcha r Dues , money
Add ress, varchar
Phone, varchar
DuesPaid , bit
3. Use the Manage1nent Studio to index the Gro upMe1nbership table. Create a
clustered index on the GrouplD colu1nn, a nonclustered index on the
lndivid ualID colu1nn, and a unique index and constraint on both colu1nns.
Section 4
An introduction to views
In chapter 1, you learned the basics of how views work. In the next topic,
then, I'll just review this information. Then, I'll present some of the benefits of
views so you'll know when and why you should use them.
1 (800) 555-1205 -
[._US. Postal _Service······································] WI
2 National lnfonnation Data Qr DC (301) 555-&950
3 Register of Copyrights DC NULL
4 Jobtrak CA (800) 555-8725
5 Newbrige Book Oubs NJ (800) 555-9:980
6 California O,amber Of Commerce CA (916) 555-6670
7 Towne Advertiser's Mailing Svcs CA NULL
8 BFI Industries CA (559) 555-1551
( 122 rows )
Description
• A view consists of a SELECT state1nent that's stored as an object in the database.
The tables referenced in the SELECT state1nent are called the base tables for the
view.
• When you create a view, the query on which it's based is opti1nized by SQL Server
before it's saved in the database. Then, you can refer to the view anywhere you
would nor1nally use a table in any of the data 1nanipulation state1nents: SELECT,
INSERT, UPDATE, and DELETE.
• Although a view behaves like a virtual table, it doesn 't store any data. Since the
view refers back to its base tables, it always returns current data.
• A view can also be referred to as a viewed table because it provides a view to the
underlying base tables.
(5 rows )
Description
• Yo u can create a view based on ahnost any SELECT state1nent. That 1n eans that
yo u can code views that join tables, su1n1n arize data, and use subqueries and
functions.
• Yo u can restrict access to the data in a table by including selected colu1n ns in the
SELECT clause for a view, or by including a WHERE clause in the SELECT
state1nent so that only selected rows are retrieved by the view.
Description
• You use the CREATE VIEW statement to create a view. The name you give the
view must not be the same as the name of any existing table or view.
• The SELECT statement within the view can refer to as many as 256 tables, and it
can use any valid combination of joins, unions, or subqueries.
• You can create a view that's based on another view rather than on a table, called a
nested view. SQL Server views can be nested up to 32 levels deep.
• The SELECT statement for a view can't include an INTO clause, and it can't
include an ORDER BY clause unless the TOP clause or the OFFSET and FETCH
clauses are also used. To sort the rows in a view, you have to include the ORDER
BY clause in the SELECT statement that uses the view.
• You can name the columns in a view by coding a list of names in parentheses
following the view name or by coding the new names in the SELECT clause. A
column must be named if it's calculated from other columns or if a column with the
same name already exists. Otherwise, the name from the base table can be used.
• You can use the WITH ENCRYPTION clause to keep users from examining the
SQL code that defines the view.
• You can use the WITH SCHEMABINDING clause to bind a view to the database
schema. Then, you can't drop the tables on which the view is based or modify the
tables in a way that would affect the view.
• If you include the WITH SCHEMABINDING clause, you can't use the all columns
operator(*) in the SELECT statement. In addition, you must qualify the names of
tables and views in the FROM clause with the name of the schema that contains
them.
• You can use the WITH CHECK OPTION clause to prevent a row from being
updated through a view if it would no longer be included in the view. See figure
13-7 for details.
A statement that names just the calculated column in its SELECT clause
CREATE VIEW Outstandinginvoices
AS
SELECT InvoiceNumber, InvoiceDate, InvoiceTotal,
InvoiceTotal - PaymentTotal - CreditTotal AS BalanceDue
FROM Invoices
WHERE InvoiceTotal - PaymentTotal - CreditTotal > 0;
Note
• If you name the columns of a view in the CREATE VIEW clause, you have to name
all of the columns. In contrast, if you name the columns in the SELECT clause, you
can name just the columns you need to rename.
Description
• An updatable view is one that can be used in an INSERT, UPDATE, or DELETE
statement to modify the contents of a base table that the view refers to. If a view is
not updatable, it's called a read-only view.
• The requirements for coding updatable views are more restrictive than for coding
read-only views. That's because SQL Server must be able to unambiguously
determine which base tables and which columns are affected.
• You can also insert, update, and delete data through a view using an INSTEAD OF
trigger. See chapter 15 for details.
Description
• To delete a view from the database, use the DROP VIEW statement.
• To modify the definition of a view, you can delete the view and then create it again,
or you can use the ALTER VIEW statement to specify the new definition.
• When you delete a view, any permissions that are assigned to the view are also
deleted.
• If you delete a table, you should also delete any views that are based on that table.
Otherwise, an error will occur when you run a query that refers to one of those
views. To find out what views are dependent on a table, display the table's
dependencies as described in chapter 12.
• If you specify the WITH SCHEMABINDING option when you create or modify a
view, you won't be able to delete the base tables without first deleting the view.
Note
• ALTER VIEW isn't an ANSI-standard statement. Although it's supported on other
SQL-based systems, its behavior on each system is different.
6 Federal Express Corporation 263253273 2016-03-22 00:00:00 NULL 30.75 0.00 0.00
7 Malloy Lithographing Inc P-0608 2016-03-23 00:00:00 NULL 20551 .18 1200.00 0.00
-
8 Ford Motor Credit Company 9982771 2016-03-24 00:00:00 NULL 503.20 0.00 0.00
9 Cardinal Business Media. I... 134116 2016-03-28 00:00:00 NULL 90.36 0.00 0.00
10 Malloy Lithographing Inc 0-2436 2016-03-31 00:00:00 NULL 10976.06 0.00 0.00 ..,
- see
=
A statement that updates the Invoices table through the view
UPDATE VendorPayment
SET PaymentTotal = 19351.18, PaymentDate = '2 016- 0 4- 0 2'
WHERE VendorName = 'Malloy Lithograph ing Inc' AND InvoiceNumber - 'P- 0 60 8';
102 102 110 P-0608 2016-03-23 00:00:00 20551.18 19351.18 1200.00 3 2016-04-22 {
103 103 122 989319-417 2016-03-23 00:00:00 2051 .59 2051 .59 0.00 3 2016-04-22 {
104 104 123 263253243 2016-03-23 00:00:00 44.44 44.44 0.00 3 2016-04-22 {
105 105 106 9982771 2016-03-24 00:00:00 503.20 0.00 0.00 3 2016-04-23 {
106 106 110 0-2060 2016-03-24 00:00:00 23517.58 21221.63 2295.95 3 2016-04-23 { "
< >
= = ,J
Description
• You can use the UPDATE state1nent to update a table through a view. To do that,
you na1ne the view in the UPDATE clause.
• The view you na1ne in the UPDATE state1nent 1nust be updatable. In addition, the
UPDATE state1nent can 't update data in 1nore than one base table.
• If you don 't specify WITH CHECK OPTION when you create a view, a change you
1nake through the view can cause the 1nodified rows to no longer be included in the view.
• If you specify WITH CHECK OPTION when you create a view, an error will occur if
you try to 1nodify a row in such a way that it would no longer be included in the view.
Description
• You can use the INSERT statement to insert rows into a base table through a view.
To do that, you name the view in the INSERT clause. Both the view and the INSERT
statement must include all of the columns from the base table that require a value.
• If the view names more than one base table, an INSERT statement can insert data into
only one of those tables.
• You can use the DELETE statement to delete rows from a base table through a view.
To do that, you name the table in the DELETE clause. For this to work, the view must
be based on a single table.
A SELECT statement that retrieves the name and schema of each table
SELECT sys.tables.name AS TableName, sys.schemas.name AS SchemaName
FROM sys.tables INNER JOIN sys.schemas
ON sys.tables.schema_id = sys.schemas.schema_id;
Description
• Yo u can use the catalog views to exa1nine the system catalog, which lists all of the
syste1n objects that define a database, including tables, views, colu1nns, keys, and
constraints. Catalog views were introd uced with SQL Server 2005.
• So1ne catalog views inherit colu1nns fro1n other catalog views. In that case, the
catalog view fro1n which the colu1nns are inherited is called the base view, and the
catalog view that inherits the colu1nns is called the derived view.
• For a co1nplete listing of the catalog views, refer to SQL Server docu1nentation.
Note
• Yo u can also use information schema views, which were available with earlier
releases of SQL Server, to exa1nine the syste1n catalog. However, we reco1n1nend
yo u use the catalog views instead.
Figure 13-1O How to use the Management Studio to work with vi ews
408 Section 4 Advanced SQL skills
Perspective
In this chapter, you learned how to create and use views. As you've seen,
views provide a powerful and flexible way to predefine the data that can be
retrieved from a database. By using them, you can restrict the access to a
database while providing a consistent and simplified way for end users and
application programs to access that data.
Terms
view read-only view
viewed table catalog views
base table base view
nested view derived view
database schema system catalog
updatable view information schema view
Exercises
1. Write a CREATE VIEW statement that defines a view named lnvoiceBasic
that returns three columns: VendorName, lnvoiceNumber, and lnvoiceTotal.
Then, write a SELECT statement that returns all of the columns in the view,
sorted by VendorName, where the first letter of the vendor name is N, 0, or P.
2. Create a view named Topl0Paidlnvoices that returns three columns for each
vendor: VendorName, Lastlnvoice (the most recent invoice date), and
SumOflnvoices (the sum of the lnvoiceTotal column). Return only the 10
vendors with the largest SumOflnvoices and include only paid invoices.
3. Create an updatable view named VendorAddress that returns the VendorID,
both address columns, and the city, state, and zip code columns for each
vendor. Then, write a SELECT query to examine the result set where
VendorlD=4. Next, write an UPDATE statement that changes the address so
that the suite number (Ste 260) is stored in VendorAddress2 rather than in
VendorAddressl. To verify the change, rerun your SELECT query.
4. Write a SELECT statement that selects all of the columns for the catalog
view that returns information about foreign keys. How many foreign keys are
defined in the AP database?
5. Using the Management Studio, modify the lnvoiceBasic view created in
exercise 1 to sort the result set by VendorName. What clause does the system
automatically code to allow the use of an ORDER BY clause in the view?
14
How to code scripts
At the end of chapter 11, you saw a simple script that defines the AP database
and the tables it contains. Now, this chapter teaches you how to code more
complex scripts. With the skills you '11 learn in this chapter, you '11 be able to
code scripts with functionality that's similar to the functionality provided by
procedural programming languages like C#, Visual Basic, and Java.
If you have experience with another procedural programming language,
you shouldn 't have any trouble with the skills presented in this chapter.
However, you should know that the programming power of Transact-SQL
is limited when compared to other languages. That's because Transact-SQL
is designed specifically to work with SQL Server databases rather than as a
general-purpose programming language. For its intended use, Transact-SQL
programming is powerful and flexible.
An introduction to scripts
To start, this chapter reviews and expands on the script concepts you learned
in chapter 11. Then, it summarizes the Transact-SQL statements you can use
within scripts. Most of these statements will be presented in detail later in this
chapter.
USE ClubRoster;
Description
• A script is a series of SQL statements that you can store in a file. Each script can
contain one or more batches that are executed as a unit.
• To signal the end of a batch, you use the GO command. A GO command isn't
required after the last batch in a script or for a script that contains a single batch.
• If a statement must be executed before the statements that follow can succeed, you
should include a GO command after it.
• The statements within a batch are executed in the order that they appear in the
batch. Because of that, you need to code statements that depend on other statements
after the statements they depend on.
• If you create a database within a script, you have to execute the batch that contains
the CREATE DATABASE statement before you can execute other statements that
refer to the database.
• The five statements listed above (CREATE VIEW, CREATE PROCEDURE,
CREATE FUNCTION, CREATE TRIGGER, and CREATE SCHEMA) can't be
combined with other statements in a batch.
• If a script will be used with a production database, you should include documentation
as shown above. Additional information should be included when appropriate.
Description
• These state1nents are used within SQL scripts to add functionality si1nilar to that
provided by procedural progra1n1n ing languages.
• These state1nents are part of the Transact-SQL, or T-SQL, language and aren 't
available on SQL-based syste1ns other than SQL Server.
Description
• A variable is used to store data. To create a variable, you use the DECLARE
statement. The initial value of a variable is always null.
• A scalar variable is defined with a standard data type and contains a single value.
You can also create table variables to store an entire result set.
• The name of a variable must always start with an at sign (@). Whenever possible,
you should use long, descriptive names for variables.
• The scope of a variable is the batch in which it's defined, which means that it can't
be referred to from outside that batch. Because of that, variables are often called
local variables.
• To assign a value to a variable, you can use the SET statement. Alternatively, you
can use the SELECT statement to assign a value to one or more variables.
• You can use a variable in any expression, but you can't use it in place of an object
name or a keyword.
INSERT @BigVendors
SELECT VendorID, VendorName
FROM vendors
WHERE VendorID IN
(SELECT VendorID FROM Invoices WHERE InvoiceTotal > 5000);
Description
• A table variable can store an entire result set rather than a single value. To create a
table variable, use a DECLARE statement with the table data type.
• You use the same syntax for defining the columns of a table variable as you do
for defining a new table with the CREATE TABLE statement. See figure 11-4 in
chapter 11 for details.
• Like a scalar variable, a table variable has local scope, so it's available only within
the batch where it's declared.
• You can use a table variable like a standard table within SELECT, INSERT,
UPDATE, and DELETE statements. The exception is that you can't use it within
the INTO clause of a SELECT INTO statement.
Description
• A temporary table exists only during the current database session. In the Management
Studio, that means that the table is available until you close the window where you
created the table.
• Temporary tables are stored in the system database named tempdb.
• If you need to drop a temporary table before the end of the current session, you can do
that using the DROP TABLE statement.
• Temporary tables are useful for testing queries or for storing data temporarily in a
complex script.
• A local temporary table is visible only within the current session, but a global temporary
table is visible to all sessions. To identify a local temporary table, you prefix the name
with a number sign ( #).To identify a global temporary table, you prefix the name with
two number signs ( ##).Temporary table names are limited to 116 characters.
• Because derived tables result in faster performance than temporary tables, you should
use derived tables whenever possible. See figure 14-6 for details.
Description
• Within a Transact-SQL script, yo u often need to work with table objects other than
the base tables in yo ur database.
• The scope of a table object deter1nines what code has access to that table.
• Standard tables and views are stored per1nanently on disk until they are explicitly
deleted, so they have the broadest scope and are therefore always available for use.
• Derived tables and table variables are generally stored in 1ne1nory, so they can
provide the best perfor1nance. In contrast, standard tables and te1nporary tables are
always stored on disk and therefore provide slower perfor1nance.
• To i1nprove the perfor1nance of yo ur scripts, use a derived table instead of creating
a table variable. However, if yo u need to use the table in other batches, create a
te1nporary table. Finally, if the data needs to be available to other connections to the
database, create a standard table or, if possible, a view.
• Altho ugh a view isn ' t a table, it can be used like one. Views provide fast
perfor1nance since they're predefined, and high availability since they're per1nanent
objects. For these reasons, yo u should try to use a view rather than create a table
whenever that's possible. However, if yo u need to insert, delete, or update the data
in the table object witho ut affecting the base tables of yo ur database, then yo u can ' t
use a view.
• A co1n1non table expression (CTE) is a type of derived table. For 1nore infor1nation
abo ut CTEs, see chapter 6.
An enhanced version of the same script that uses an IF... ELSE statement
USE AP;
DECLARE @MininvoiceDue money, @MaxinvoiceDue money;
DECLARE @EarliestinvoiceDue smalldatetime, @LatestinvoiceDue smalldatetime;
SELECT @MininvoiceDue = MIN(InvoiceTotal - PaymentTotal - CreditTotal),
@MaxinvoiceDue = MAX(InvoiceTotal - PaymentTotal - CreditTotal),
@EarliestinvoiceDue = MIN(InvoiceDueDate),
@LatestinvoiceDue = MAX(InvoiceDueDate)
FROM Invoices
WHERE InvoiceTotal - PaymentTotal - CreditTotal > 0;
IF @EarliestinvoiceDue < GETDATE()
BEGIN
PRINT 'Outstanding invoices overdue!';
PRINT 'Dated' + CONVERT(varchar,@EarliestinvoiceDue,1) +
' through ' + CONVERT(varchar,@LatestinvoiceDue,1) + '. ';
PRINT 'Amounting from$' + CONVERT(varchar,@MininvoiceDue,1) +
' to$' + CONVERT(varchar,@MaxinvoiceDue,1) + ' . ' ;
END;
ELSE --@EarliestinvoiceDue >= GETDATE()
PRINT 'No overdue invoices.';
Description
• You use the IF ... ELSE statement to test a conditional expression. If that expres-
sion is true, the statements that follow the IF keyword are executed. Otherwise, the
statements that follow the ELSE keyword are executed if that keyword is included.
• If you need to execute two or more SQL statements within an IF or ELSE clause,
enclose them within a BEGIN ... END block.
• You can nest IF... ELSE statements within other IF... ELSE statements. Although
SQL Server doesn't limit the number of nested levels, you should avoid nesting so
deeply that your script becomes difficult to read.
The syntax for the IF EXISTS clause (SQL Server 2016 and later)
DROP OBJECT_TYPE IF E.X ISTS object_name;
Description
• With SQL Server 2016 and later, you can add the IF EXISTS clause to a DROP
statement to check whether an object exists before you drop it.
• With earlier versions of SQL Server, you can use the OBJECT_ID and DB_ID
functions within IF statements to check whether an object exists.
• You can use the OBJECT_ID function to check for the existence of a table, view,
stored procedure, user-defined function, or trigger. You use the DB_ID function
to check for the existence of a database. Both functions return a null value if the
object doesn't exist. Otherwise, they return the object's identification number.
• To test for the existence of a temporary table, you must qualify the table name with
the database that contains it: tempdb. Since this is a system database, though, you
can omit the schema name as shown above.
A script that tests and adjusts credit amounts with a WHILE loop
USE AP;
IF OBJECT_ID ( 'tempdb •• #InvoiceCopy' ) IS NOT NULL
DROP TABLE #InvoiceCopy;
Description
• To execute a SQL state1nent repeatedly, yo u use the WHILE state1nent. This
state1nent is executed as long as the conditional expression in the WHILE clause is
true.
• If you need to execute two or 1nore SQL state1nents within a WHILE loop, enclose
the state1nents within BEGIN and END keywords.
• To exit fro1n a WHILE loop i1n1nediately witho ut testing the expression, use the
BREAK state1nent. To return to the beginning of a WHILE loop witho ut executing
any additional state1nents in the loop, use the CONTINUE state1nent.
Warning
• This script takes a few seconds to execute.
The syntax
Declare a cursor
DECLARE cursor_name CURSOR FOR select_statement;
Get column values from the row and store them in a series of variables
FETCH NEXT FROM cursor_name INTO @variablel [, @variable2] [, @variable3] ••• ;
OPEN Invoices_Cursor;
CLOSE Invoices_Cursor;
DEALLOCATE Invoices_Cursor;
PRINT I I ,
•
Description
• The @ @FETCH_STATUS system function returns O if the row was fetched
successfully or -1 if the row can't be fetched because the end of the result set has been
reached.
Description
• SQL Server 2005 introduced a TRY ... CATCH state1nent that yo u can use to
provide error handling (also known as exception handling). This works si1nilarly to
exception handling state1nents provided by C# and Visual Basic.
• A TRY block 1nust be followed i1n1nediately by a single CATCH block.
• When an error occurs in a state1nent within a TRY block, control is passed to the
CATCH block where the error can be processed. If no error occurs inside the TRY
block, the CATCH block is skipped.
• Errors that have a severity of 10 or lower are considered warnings and are not
handled by TRY ... CATCH blocks. Errors that have a severity of 20 or higher and
cause the database connection to be closed are not handled by TRY ... CATCH
blocks.
• Within a CATCH block, yo u can use the functions shown in this fig ure to return
data abo ut the error that caused the CATCH block to be executed.
100 % •_ < I I )
9 ~ l'IIHILE.l.forJditiot i
10 B BEGIN
11 I
12 - UPDATE #InvoiceCopy
13 SET Credit Total = CreditTotal + . 05
14 1-JHERE InvoiceTotal - CreditTotal - PaymentTot al > 0 ;
15
16 El IF ( SELECT MAX(CreditTotal ) FROt1 #InvoiceCopy) > 3000
17 BREAK;
18 ELSE --(SELECT HAX(CreditTotal) FROt1 #InvoiceCopy ) <= 3000
19 COITTINUE;
20
21 END V
100 % • < )
Description
• Surround- with snippets 1nake it easy to enclose a block of state1nents in a BEGIN .. .
END, IF, or WHILE state1nent.
• To insert a surround-with snippet, select the state1nents yo u want to enclose. Then,
right-click on the state1nents, select the Surround With co1n1nand fro1n the resulting
1nenu, and select the snippet yo u want to insert fro1n the list that's displayed.
• To select a snippet fro1n the list, do uble-click on it. Alternatively, yo u can use the
Up and Down arrow keys to select the snippet and then press the Tab or Enter key.
• If yo u insert a snippet for an IF or WHILE state1nent, yo u will need to co1nplete
the state1nent by replacing the highlighted condition. Yo u can also enter an ELSE
clause for an IF state1nent.
• When yo u insert a snippet for an IF or WHILE state1nent, a BEGIN .. . END
state1nent is added auto1natically.
IF @MyRowCount = 1
INSERT Invoices
VALUES ( @Myidentity, 'BA- 0 199', 2 0 16- 0 5- 0 1
1 1
, 4598.23,
0 , 0 , 4, 2 0 16-0 6-3 0
1
NULL ) ;
1
,
( 1 row( s ) affected )
Description
• The system functions return infor1n ation abo ut SQL Server values, objects, and
settings. They can be used anywhere an expression is allowed.
• Syste1n functions are useful in writing scripts. In addition, so1ne of these functions
can be used to provide a value for a DEFAULT constraint on a colu1n n.
• Syste1n functions used to be called global variables, but that na1n e is no longer
used.
• In general, it's better to store the value returned by a syste1n function in a variable
than to use the syste1n function directly. That's because the value of a syste1n
function can change when subsequent state1nents are executed.
Description
• You use the SET state1nent to change configuration settings for the current session.
These settings control the way queries and scripts execute.
• If the ANSI_NULLS option is set to ON, yo u can only test for null values in a
colu1nn by using the IS NULL clause. See figure 3-15 in chapter 3 for details.
• In a future version of SQL Server, the ANSI_NULLS and ANSI_PADDING options
will always be on and you won 't be able to turn the1n off. Because of that, you
shouldn 't use these options in new scripts that you write.
• Instead of using the SET ROWCOUNT state1nent to li1nit the nu1nbers of rows that
are processed by a query, you should use the TOP clause. See chapter 3 for
infor1nation on how to use this clause with the SELECT state1nent. For infor1nation
on how to use it with the INSERT, UPDATE, and DELETE state1nents, see the SQL
Server docu1nentation.
• In a future version of SQL Server, the SET ROWCOUNT state1nent won 't affect
INSERT, UPDATE, and DELETE state1nents.
• For a co1nplete list of the Transact-SQL state1nents for changing session settings, see
the topic on the SET state1nent in the SQL Server docu1nentation.
E.XEC (@DynamicSQL ) ;
Description
• The EXEC state1nent executes the SQL state1nent contained in a string. Because
you define the SQL string within the script, you can create and execute SQL code
that changes each ti1ne the script is run. This is called dynamic SQL.
• You can use dyna1nic SQL to perfor1n operations that can 't be acco1nplished using
any other technique.
USE AP;
Description
• A SELECT INTO statement is used to retrieve information from the tables,
columns, and types catalog views and store it in a temporary table named
#TableSummary. This table has one row for each column in each table of the
database that includes the table name, column name, and data type.
• A CREATE TABLE statement is used to create a temporary table named
#AllUserTables. Then, an INSERT statement is used to insert rows into this table
that contain the name of each table in the database. This information is retrieved
from the catalog view named tables. Each row also contains a sequence number
that's generated by SQL Server.
• The system table named dtproperties and the two temporary tables themselves are
omitted from both SELECT queries.
Part 2 of this script includes a WHILE loop that uses dynamic SQL to insert
an additional row into #TableSummary for each table in #AllUserTables. Each of
these rows indicates the total number of rows in one of the base tables. The
@LoopMax variable used by this loop is set to the maximum value of the
TableID column in #AllUserTables. The @LoopVar variable is set to 1, which
is the minimum value of TableID. The WHILE loop uses @LoopVar to step
through the rows of #AllUserTables.
Within the loop, the SELECT statement sets @TableNameVar to the value
of the TableName column for the current table. Then, @ExecVar is built by
concatenating each of the clauses of the final SQL string. This string consists of
three statements. The DECLARE statement is used to create a variable named
@CountVar that will store the number of rows in the current table. Note that
because this variable is created within the dynamic SQL statement, its scope is
limited to the EXEC statement. In other words, it isn't available to the portion of
the script outside of the EXEC statement.
The SELECT statement within the dynamic SQL statement retrieves the row
count from the current table and stores it in the @CountVar variable. Then, the
INSERT statement inserts a row into the #TableSummary table that includes the
table name, a literal value that indicates that the row contains the row count, and
the number of rows in the table. You can see the contents of the SQL string that's
created for one table, the ContactUpdates table, in this figure.
After the SQL string is created, it's executed using an EXEC statement.
Then, @LoopVar is increased by 1 and the loop is executed again. When the
loop completes, the script executes a SELECT statement that retrieves the data
from the #TableSummary table. That result set is also shown in this figure.
Chapter 14 How to code scripts 443
SET @Loopvar = 1;
The contents of the SQL string for one iteration of the loop
DECLARE @Countvar int; SELECT @Countvar = COUNT(*) FROM ContactUpdates;
INSERT #TableSummary VALUES ('ContactUpdates','*Row Count*', @Countvar);
Description
• The WHILE statement loops through the tables in the #AllUserTables table. For
each table, it creates a dynamic SQL string that contains a SELECT statement and
an INSERT statement. The SELECT statement retrieves the number of rows in the
table, and the INSERT statement inserts a new row into the #TableSummary table
that indicates the number of rows.
• The final SELECT statement retrieves all of the rows and columns from the
#TableSummary table sorted by column name within table name.
Description
• Yo u can use the SQLCMD utility to run T-SQL scripts fro1n a co1n1nand line. This
provides a way to use a DOS batch file to run a script.
• To open a Co1runand Pro1npt window, select Co1n1nand Pro1npt fro1n the Start 1nenu.
On Windows 7, it's in the All Progra1ns ➔Accessories gro up. On Windows 10, it's in the
All Apps ➔ Windows Syste1n gro up.
• To start the SQLCMD utility, enter "sqlc1nd" at the C:\> pro1npt along with the
appropriate co1n1nand line switches.
• Yo u 1nust begin 1nost co1n1nands with the -S switch to specify the na1ne of a valid server.
• To log in, yo u can use the -E switch for Windows authentication, or yo u can use the
-U and -P switches for SQL Server authentication.
• Once yo u've started the SQLCMD utility and logged in, yo u can enter the state1nents
yo u want to execute followed by the GO co1n1nand.
• To exit fro1n the SQLCMD utility, enter "exit" at the SQLCMD pro1npt.
Perspective
In this chapter, you've learned how to code procedural scripts in T-SQL. By
using the techniques you've learned here, you '11 be able to code scripts that are
more general, more useful, and less susceptible to failure. In particular, when
you use dynamic SQL, you'll be able to solve problems that can't be solved
using any other technique.
In the next chapter, you '11 expand on what you've learned here by learning
how to code stored procedures, functions, and triggers. These objects are
basically one-batch scripts that are stored with the database. But they provide
special functionality that gives you greater control over a database, who has
access to it, and how they can modify it.
Terms
script WHILE loop
batch cursor
T-SQL statement error handling
variable exception handling
scalar variable surround-with snippets
local variable system function
table variable global variable
temporary table dynamic SQL
local temporary table SQLCMD
global temporary table OSQL
scope Windows PowerShell
nested IF... ELSE statements
Chapter 14 How to code scripts 447
Exercises
1. Write a script that declares and sets a variable that's equal to the total
outstanding balance due. If that balance due is greater than $10,000.00, the
script should return a result set consisting of VendorName, InvoiceNumber,
InvoiceDueDate, and Balance for each invoice with a balance due, sorted
with the oldest due date first. If the total outstanding balance due is less than
$10,000.00, the script should return the message "Balance due is less than
$10,000.00."
2. The following script uses a derived table to return the date and invoice total
of the earliest invoice issued by each vendor. Write a script that generates the
same result set but uses a temporary table in place of the derived table. Make
sure your script tests for the existence of any objects it creates.
USE AP;
3. Write a script that generates the same result set as the code shown in exercise
2, but uses a view instead of a derived table. Also write the script that creates
the view. Make sure that your script tests for the existence of the view. The
view doesn't need to be redefined each time the script is executed.
4. Write a script that uses dynamic SQL to return a single column that repre-
sents the number of rows in the first table in the current database. The script
should automatically choose the table that appears first alphabetically, and it
should exclude tables named dtproperties and sysdiagrams. Name the column
CountOITable, where Table is the chosen table name.
Hint: Use the sys.tables catalog view.
15
Scripts
Of the four types of procedural programs, only scripts can contain two or
more batches. That's because only scripts can be executed by SQL Server tools
such as the Management Studio and the SQLCMD utility. In addition, only
scripts are stored in files outside of the database. For these reasons, scripts tend
to be used most often by SQL Server programmers and database administrators.
Description
• You can write procedural progra1ns with Transact-SQL using scripts, stored
procedures, user-defined functions, and triggers.
• Scripts are useful fo r those users with access to the SQL Server client tools, such as
the Manage1nent Studio. Typically, these tools are used by SQL progra1n1ners and
DBAs, not by application progra1n1ners or end users.
• Stored procedures, user-defined functions, and triggers are all executable database
objects that contain SQL state1nents. Although they differ in how they're executed
and by the kinds of values they can return, they all provide greater control and
better perfor1nance than a script.
• Stored procedures give the SQL progra1n1ner control over who accesses the
database and how. Since so1ne application progra1n1ners don't have the expertise to
write certain types of co1nplex SQL queries, stored procedures can si1nplify their
use of the database.
• User-defined functions are 1nost often used by SQL progra1n1ners within the stored
procedures and triggers that they write, although they can also be used by
application progra1n1ners and end users.
• Triggers are special procedures that execute when an action query, such as an
INSERT, UPDATE, or DELETE state1nent, is executed. Like constraints, you can
use triggers to prevent database errors, but triggers give you greater control and
flexibility.
• Since procedures, functions, and triggers are database objects, the SQL state1nents
you use to create, delete, and 1nodify the1n are considered part of the DDL.
Description
• A stored proced ure is an executable database object that contains SQL state1nents.
A stored proced ure is also called a sproc (prono unced either as one word or as
"ess-proc") or a procedure.
• Stored procedures are precompiled. That 1neans that the execution plan for the SQL
code is co1npiled the first ti1ne the proced ure is executed and is then saved in its
co1npiled fo r1n. For this reason, stored proced ures execute faster than an equivalent
SQL script.
• Yo u use the EXEC state1nent to run, or call, a proced ure. If this state1nent is the
first line in a batch, yo u can 01nit the EXEC keyword and code j ust the procedure
na1ne. To 1nake your code easier to read, however, yo u should always include the
EXEC keyword.
• Yo u can call a stored procedure fro1n within another stored procedure. Yo u can even
call a stored proced ure fro1n within itself. This technique, called a recursive call or
recursion, is seldo1n used in SQL progra1n1ning.
• One of the advantages of using proced ures is that application progra1n1ners and end
users don 't need to know the structure of the database or how to code SQL.
• Another advantage of using procedures is that they can restrict and control access
to a database. If yo u use proced ures in this way, yo u can prevent both accidental
errors and 1nalicious da1nage.
Description
• You use the CREATE PROC statement to create a stored procedure in the current
database. The name of a stored procedure can be up to 128 characters and is
typically prefixed with the letters sp.
• The CREATE PROC statement must be the first and only statement in a batch. If
you're creating the procedure within a script, then, you must code a GO command
following any statements that precede the CREATE PROC statement.
• To create a temporary stored procedure, prefix the procedure name with a number
sign (#) for a local procedure or two number signs (##) for a global procedure. A
temporary stored procedure only exists while the current database session is open.
• You can use parameters to pass one or more values from the calling program to the
stored procedure or from the procedure to the calling program. See figures 15-4 and
15-5 for more information on working with parameters.
• The AS clause contains the SQL statements to be executed by the stored procedure.
Since a stored procedure must consist of a single batch, a GO command is inter-
preted as the end of the CREATE PROC statement.
• The RECOMPILE option prevents the system from precompiling the procedure,
which means that it has to be compiled each time it's run. Since that reduces system
performance, you don't typically use this option.
• The ENCRYPTION option prevents users from viewing the code in a stored
procedure. See figure 15-11 for more information on viewing stored procedures.
• The EXECUTE_AS_clause option was introduced with SQL Server 2005. You can
use this option to allow users to execute the stored procedure with the permissions
specified by the EXECUTE AS clause. For more information, look up "EXECUTE
AS clause" in the SQL Server documentation.
Description
• To declare a para1neter within a stored proced ure, you code the na1ne of the
para1neter followed by its data type. The para1neter na1ne 1n ust start with an at sign
( @), and the data type can be any type except table. Para1neters are always local to
the procedure.
• Input parameters accept values passed fro1n the calling progra1n .
• Output parameters store values that are passed back to the calling progra1n . You
identify an output para1neter by coding the OUTPUT keyword after the para1neter
na1ne and data type
• Optional parameters are para1neters that do not require that a value be passed fro1n
the calling progra1n . To declare an optional para1neter, you assign it a default value.
Then, that value is used if one isn 't passed fro1n the calling progra1n.
• A stored procedure can declare up to 2100 para1neters. If you declare two or 1nore
para1neters, the declarations 1nust be separated by co1n1nas.
• It's a good progra1n1ning practice to code your CREATE PROC state1nents so they
list required para1neters first, followed by optional para1neters.
IF @Datevar IS NULL
SELECT @Datevar - MIN(InvoiceDate) FROM Invoices;
Description
• To call a procedure that accepts parameters, you pass values to the procedure
by coding them following the procedure name. You can pass the parameters by
position or by name.
• To pass parameters by position, list them in the same order as they appear in the
CREATE PROC statement and separate them with commas. When you use this
technique, you can omit optional parameters only if they're declared after any
required parameters.
• To pass parameters by name, code the name of the parameter followed by an equal
sign and the value. You can separate multiple parameters with commas. When you
use this technique, you can list the parameters in any order and you can easily omit
optional parameters.
• To use an output parameter in the calling program, you must declare a variable to
store its value. Then, you use the name of that variable in the EXEC statement, and
you code the OUTPUT keyword after it to identify it as an output parameter.
IF @Datevar IS NULL
SELECT @Datevar = MIN ( InvoiceDate ) FROM Invoices;
RETURN @InvCount;
Description
• The RETURN state1nent i1n1nediately exits the procedure and returns an optional
integer value to the calling progra1n. If you don ' t specify a value in this state1nent,
the return value is zero.
• To use the return value in the calling progra1n, you 1nust declare a variable to store
its value. Then, you code that variable na1ne followed by an equals sign and the
na1ne of the procedure in the EXEC state1nent.
END TRY
BEGIN CATCH
PRINT 'An error occurred.';
PRINT 'Message: I + CONVERT(varchar, ERROR_MESSAGE( )) ;
IF ERROR_NUMBER() >= 50000
PRINT 'This is a custom error message.';
END CATCH;
Description
• The process of checking the values in one or 1nore colu1nns is known as data validation.
It's a good practice to validate the data within a stored procedure whenever possible.
• The THROW state1nent 1nanually raises an error. Unless this error is caught by a
TRY ... CATCH state1nent within the stored procedure, the error will be returned to the
caller just like an error that's raised by the database engine.
• You use the state argu1nent to identify how serious an error is. The severity of an error
that's raised with the THROW state1nent is always 16.
• A THROW state1nent that's coded within a block 1nust be preceded by a se1nicolon.
• A THROW state1nent that doesn 't include any para1neters 1nust be coded in a CATCH
block.
A stored procedure
that manages insert operations
Figure 15-8 presents a stored procedure that might be used by an application
program that inserts new invoices into the Invoices table. This should give you a
better idea of how you can use stored procedures.
This procedure starts with a comment that documents the stored procedure.
This documentation includes the author's name, the date the procedure was
created, the dates it was modified, who it was modified by, and a general
description of the procedure's purpose. Since this procedure returns a value, the
return value is briefly described in the comments too. Of course, you can include
any other information that you feel is useful.
This procedure uses nine parameters that correspond to nine of the columns
in the Invoices table. All of these parameters are input parameters, and each
parameter is assigned the same data type as the matching column in the Invoices
table. This means that if the calling program passes a value that can't be cast into
the proper data type, an error will be raised as the procedure is called. In other
words, this type of error won't be caught by the procedure.
If the calling program was to pass a value of 13-15-89 to the @lnvoiceDate
parameter, for example, an error would occur because this value can't be cast as
a date. To handle this type of error within the procedure, you could define each
parameter with the varchar data type. Then, the procedure could test for invalid
data types and raise appropriate errors when necessary.
All of the input parameters are also assigned a default value of NULL. Since
most of the columns in the Invoices table can't accept null values, this might
seem like a problem. As you '11 see in a minute, however, the procedure tests the
value of each parameter before the insertion is attempted. Then, if the parameter
contains an invalid value, an appropriate error is returned to the calling program
and the insert operation is never performed. By coding the procedure this way,
you can fix some errors by supplying default values, and you can return custom
error messages for other errors.
Chapter 15 How to code stored procedures, functions, and triggers 465
USE AP;
GO
Description
• The nine parameters used in this procedure correspond nine of the columns in the
Invoices table.
After the AS keyword, a series of IF statements are used to test the values
in each input parameter. The first IF statement, for example, tests the value
of @VendorID to determine if that vendor exists in the Vendors table. If not,
a THROW statement is used to raise a custom error that indicates that the
VendorID is invalid. This statement also exits the stored procedure and returns
the custom error to the calling program.
For the first IF statement, the custom error contains a short message that
says, "Invalid VendorID." However, this message could easily be enhanced to
display a more helpful and descriptive message such as "The specified VendorID
value does not exists in the Vendors table. Please specify a valid VendorID."
The next five IF statements check for null values. In addition, the IF
statement for the @lnvoiceDate parameter checks to be sure that it falls between
the current date and 30 days prior to the current date, and the IF statement for
the @lnvoiceTotal parameter checks to be sure that it's greater than zero. If not,
a custom error is raised.
Instead of returning an error if the @CreditTotal or @PaymentTotal
parameter contains a null value, this procedure sets the value of the parameter to
zero. It also checks that the credit total isn't greater than the invoice total, and it
checks that the payment total isn't greater than the invoice total minus the credit
total.
The next IF statement checks the value of the @TermsID parameter to see if
a row with this value exists in the Terms table. If not, this parameter is set to the
value of the DefaultTermsld column for the vendor if the parameter contains a
null value. If it contains any other value, though, a custom error is raised.
This procedure also sets the @lnvoiceDueDate parameter if a due date isn't
passed to the procedure. To do that, it adds the value of the TermsDueDays
column in the Terms table to the value in the @lnvoiceDate parameter. If a due
date is passed to the procedure, the procedure checks that the date is after the
invoice date but isn't more than 180 days after the invoice date. Finally, the
procedure checks the @PaymentDate parameter to be sure that it's not less than
the invoice date or more than 14 days before the current date.
As you can see, some of the data validation performed by this procedure
duplicates the constraints for the Invoices table. If you didn't check the VendorID
to be sure that it existed in the Vendors table, for example, the foreign key
constraint would cause an error to occur when the row was inserted. By testing
for the error before the insertion, however, the stored procedure can raise a
custom error message that might be more easily handled by the calling program.
Some of the data validation performed by this procedure goes beyond the
constraints for the columns in the table. For example, all three of the date values
are tested to determine whether they fall within an appropriate range. This
illustrates the flexibility provided by using stored procedures to validate data.
Chapter 15 How to code stored procedures, functions, and triggers 467
Description
• A series of IF statements is used to validate the data in each column of the new
invoice row. If the value in a column is invalid, a THROW statement is used to
return a custom error to the calling program. This terminates the stored procedure.
• Some of the conditions tested by this code could be accomplished using constraints.
However, testing these conditions before the INSERT statement is executed
prevents system errors from occurring and allows you to return a user-friendly
custom error message. Other conditions tested by this code can't be enforced using
constraints.
If the input parameters pass all of the validation tests, the INSERT statement
is executed. Since the data has already been validated, the INSERT statement
should execute successfully most of the time and insert the row. Then, the
following statement uses the @@IDENTITY function to get the new invoice ID
value that's generated when the row is inserted, and it returns that value to the
calling program.
However, even though the data for the insert has been validated, it's still
possible for an unexpected system error to occur. In that case, SQL Server will
raise a system error and end the stored procedure.
In most cases, a stored procedure like this would be called from an
application program. Since the details of doing that are beyond the scope of
this book, however, this figure presents a SQL script that calls the procedure.
This script includes processing similar to what might be used in an application
program. In short, this script uses a TRY ... CATCH statement to catch any errors
that have been raised and to handle them appropriately. In many cases, handling
an error is as simple as displaying a message that describes the error and
indicates what can be done to fix the problem. In this figure, for example, the
CATCH block uses three PRINT statements to indicate that an error occurred,
to display the error number, and to display the error message. In other cases,
though, error handling can include additional processing such as saving data or
exiting the program as gracefully as possible.
Chapter 15 How to code stored procedures, functions, and triggers 469
Description
• If the data in all of the columns of the new row is valid, the procedure executes an
INSERT statement to insert the row. If the insert succeeds, this procedure gets the
new InvoiceID value and returns it to the calling program, which ends the
procedure. Otherwise, the database engine raises a system error, returns a value of
zero, and ends the procedure.
• If this procedure was called by an application program, the program would need
to handle any errors that occur. This includes custom errors raised by this stored
procedure and unexpected system errors raised by SQL Server if it can't execute
the INSERT statement.
Description
• If you want to pass a table as a parameter to a stored procedure or a user-defined
function, you must create a user-defined table type for the table.
• A user-defined table type can only be used as an input parameter, not as an output
parameter.
• Creating a user-defined table type is similar to creating a regular table. However,
you can't define foreign keys for the table.
Description
• To delete a stored procedure from the database, use the DROP PROC statement.
• To modify the definition of a procedure, you can delete the procedure and then
create it again, or you can use the ALTER PROC statement to specify the new
definition.
• When you delete a procedure, any security permissions that are assigned to the
procedure are also deleted. If that's not what you want, you can use the ALTER
PROC statement to modify the procedure and preserve the permissions.
1 CREATE PROC
...........................
,,...,.,
splnvoiceReport
.............................................................................,.................,...........!'
...................
2 AS
3
4 SELECT VendorName. lnvoiceNumber. Invoice Date. I...
5 FROM Invoices JOIN Vendors
6 ON lnvoices.VendorlD = Vendors.VendorlD
7 WHERE Invoice Total -Credit Total· PaymentTotal > 0
8 ORDER BYVendorName;
Description
• Microsoft SQL Server includes 1nany system stored procedures that yo u can use to
perfor1n useful tasks on a database. These procedures are identified by the prefix
sp_. Yo u can use these procedures in the scripts and procedures yo u write.
• Syste1n stored procedures are stored in the Master database, but yo u can execute
the1n on any database. These procedures operate within the current database context
that yo u' ve set with the USE state1nent.
• SQL Server has hundreds of syste1n stored procedures. To view the co1nplete list,
look up "syste1n stored procedures" in the SQL Server docu1nentation.
• Yo u can also create yo ur own syste1n stored procedures. To do that, give the
procedure a na1ne that begins with sp_ and create it in the Master database.
Description
• A user-defined function, also called a UDF or just afunction, is an executable
database object that contains SQL state1nents.
• The na1ne of a function can be up to 128 characters and is typically prefixed with
the letters fn.
• Functions always return a value. A scalar-valued function returns a single value of
any T-SQL data type. A table-valued function returns an entire table.
• A table-valued function can be based on a single SELECT state1nent, in which case
it's called a simple table-valued function, or it can be based on two or 1nore
state1nents, in which case it's called a multi-statement table-valued function.
• A function can ' t have a per1nanent effect on the database. In other words, it can 't
run an action query against the database.
• Yo u can call, or invoke, a scalar-valued function fro1n within any expression. Yo u
can invoke a table-valued function anywhere yo u'd refer to a table or a view.
• Unlike other database objects, yo u 1nust specify the na1ne of the sche1na when
invoking a UDF.
Description
• Functions can be defined with from zero to 1024 input parameters. You specify
these parameters in parentheses after the name of the function in the CREATE
FUNCTION statement. Each parameter can be assigned an optional default value.
• A function can't contain output parameters. Instead, you specify the data type of
the data to be returned by the function in the RETURNS clause.
• You code the statements that define the function within a BEGIN ... END block.
This block includes a RETURN statement that specifies the value to be returned.
• When you invoke a function, you list the parameters within parentheses after the
name of the function. To use the default value of a parameter, code the DEFAULT
keyword in place of the parameter value. You can't pass function parameters by
name.
• When you create a function, it's stored in the schema associated with the current
user if you don't specify a schema name. When you invoke the function, however,
you must specify the schema name.
• The SCHEMABINDING option binds the function to the database schema.
This prevents you from dropping or altering tables or views that are used by the
function. This option is more commonly used for table-valued functions.
• The ENCRYPTION option prevents users from viewing the code in the function.
• The EXECUTE_AS_clause option specifies the security context under which the
function is executed.
Figure 15-13 How to create and use a scalar-valued function
480 Section 4 Advanced SQL skills
Description
• You create a simple table-valued function, also called an inline table-valued
function, by coding the table data type in the RETURNS clause of the CREATE
FUNCTION statement. Then, you code a SELECT statement that defines the table
in the RETURN statement.
• To use a simple table-valued function, code the function name in place of a table
name or a view name. If you use a table-valued function in a join operation, you '11
want to assign a correlation name to it as shown above.
1 ...~.1.~.~..~~?.................................................! 224.00
2 Cardinal Business Media. Inc. 90.36
3 Data Reproductions Corp 85.31
4 Federal Express Corporation 210.89 I
Warning
• Because this code must loop through the Invoices table thousands of times, this
function can take a long time to execute.
Description
• To delete a user-defined function from the database, use the DROP FUNCTION
statement.
• To modify the definition of a function, you can delete the function and then create
it again, or you can use the ALTER FUNCTION statement to specify the new
definition.
• When you delete a function, any security permissions that are assigned to the
function and any dependencies between the function and the tables and views
it uses are also deleted. If that's not what you want, you can use the ALTER
FUNCTION statement to modify the function and preserve the permissions and
dependencies.
Description
• A trigger is a special kind of procedure that executes, or fires, in response to an
action query. Unlike a stored procedure, yo u can 't invoke a trigger directly, yo u
can 't pass para1neters to a trigger, and a trigger can 't pass back a return value.
• A trigger is associated with a single table or view, which yo u identify in the ON
clause. The trigger can be set to fire on INSERT, UPDATE, or DELETE state1nents
or on a co1nbination of these state1nents.
• A trigger can be set to fire after the action query (AFTER) or instead of the action
query (INSTEAD OF). A FOR trigger is the sa1ne as an AFTER trigger.
• A table can have 1nultiple AFTER triggers, even for the sa1ne action. A view can 't
have an AFTER trigger. A table or view can have only one INSTEAD OF trigger
for each action.
• To hide the code for the trigger fro1n the user, include the ENCRYPTION option.
• To execute a trigger under a specific security context, include the
EXECUTE_AS_clause option.
• It's a co1n1non progra1n1ning practice to na1ne triggers based on the table or view
and the actions that will cause the trigger to fire.
• Within a trigger, yo u can refer to two tables that are created by the syste1n: Inserted
and Deleted. The Inserted table contains the new rows for insert and update operations.
The Deleted table contains the original rows for update and delete operations.
Description
• An AFTER trigger fires after the action query is executed. If the action query
causes an error, the AFTER trigger never fires.
• AFTER triggers can be used to archive deleted data.
INSERT Invoices
(VendorID, InvoiceNumber, InvoiceDate, InvoiceTotal,
TermsID, InvoiceDueDate, PaymentDate)
VALUES (@VendorID, @InvoiceNumber, @InvoiceDate,
@InvoiceTotal, @TermsID, @InvoiceDueDate, NULL);
END;
END;
ELSE
THROW 50027, 'Limit INSERT to a single row.', 1;
Description
• An INSTEAD OF trigger is executed instead of the action query that causes it to
fire. Because the action query is never executed, the trigger typically contains code
that performs the operation.
• INSTEAD OF triggers are typically used to provide for updatable views. They can
also be used to prevent errors, such as constraint violations, before they occur.
• Each table or view can have only one INSTEAD OF trigger for each type of
action. However, if a table is defined with a foreign key constraint that specifies the
CASCADE UPDATE or CASCADE DELETE option, INSTEAD OF UPDATE
and INSTEAD OF DELETE triggers can't be defined for the table.
Description
• Triggers can be used to enforce database rules for data consistency that can't be
enforced by constraints.
• Triggers can also be used to enforce the same rules as constraints, but with more
flexibility.
Description
• In the ON clause, yo u can specify the DATABASE keyword to fire the trigger only
for the current database, or yo u can specify the ALL SERVER keywords to fire the
trigger for any database on the current server.
• To specify a DDL state1nent for a trigger, you can code the na1ne of the DDL
state1nent, replacing any spaces with underscores.
• The EVENTDATA function returns an XML docu1nent of the x1nl data type. If
necessary, yo u can use the skills presented in chapter 18 to parse this docu1nent.
Description
• To delete a trigger from the database, use the DROP TRIGGER statement.
• To modify the definition of a trigger, you can locate the trigger in the Object
Explorer of SQL Server Management Studio by expanding the table the trigger is
associated with and then expanding the Triggers folder. Finally, you can right-click
on the trigger and choose modify.
• To modify the definition of a DDL trigger, you can locate the trigger in the
Object Explorer by expanding the Programmability folder and then expanding the
Database Triggers folder. Finally, you can right-click on the trigger and choose
modify.
• When you delete a trigger, any security permissions that are assigned to the trigger
are also deleted. If that's not what you want, you can use the ALTER TRIGGER
statement to modify the trigger and preserve the permissions.
• Unless a trigger and its corresponding table or view belong to the default schema,
you must include the schema name on the DROP TRIGGER and ALTER
TRIGGER statements.
Perspective
In this chapter, you've learned how to create the three types of executable
database objects supported by SQL Server using SQL statements. Stored
procedures are the most flexible of the three because you can use them in so many
different ways. You can code procedures to simultaneously simplify and restrict
a user's access to the database, to verify data integrity, and to ease your own
administrative tasks.
Although they're generally less flexible than stored procedures, functions
and triggers are powerful objects. You can use them to solve problems that
otherwise would be difficult or impossible to solve. In particular, table-valued
functions are one of the most useful extensions provided by Transact-SQL
because they behave like views but can accept parameters that can change the
result set.
In addition to using SQL statements to work with stored procedures,
functions, and triggers, you can use the Management Studio. You '11 find all
three of these object types in folders within the Programmability folder for
a database. Then, you can add, modify, and delete objects using the menus
that appear when you right-click on a folder or object. You can use this same
technique to work with the user-defined table types you use with stored
procedures.
Terms
stored procedure required parameter
user-defined function (UDF) optional parameter
trigger passing parameters by position
sproc passing parameters by name
call a procedure return value
precompiled data validation
execution plan user-defined table type
recursive call system stored procedure
recursion scalar-valued function
temporary stored procedure table-valued function
local procedure simple table-valued function
global procedure multi-statement table-valued function
parameter invoke a function
input parameter inline table-valued function
output parameter fire a trigger
Chapter 15 How to code stored procedures, functions, and triggers 499
Exercises
1. Create a stored procedure named spBalanceRange that accepts three optional
parameters. The procedure should return a result set consisting of
VendorName, lnvoiceNumber, and Balance for each invoice with a balance
due, sorted with largest balance due first. The parameter @VendorVar is a
mask that's used with a LIKE operator to filter by vendor name, as shown in
figure 15-5. @BalanceMin and @BalanceMax are parameters used to specify
the requested range of balances due. If called with no parameters or with a
maximum value of 0, the procedure should return all invoices with a balance
due.
2. Code three calls to the procedure created in exercise 1:
(a) passed by position with @VendorVar='Mo/o' and no balance range
(b) passed by name with @VendorVar omitted and a balance range from
$200 to $1000
(c) passed by position with a balance due that's less than $200 filtering for
vendors whose names begin with C or F
3. Create a stored procedure named spDateRange that accepts two parameters,
@DateMin and @DateMax, with data type varchar and default value null.
If called with no parameters or with null values, raise an error that describes
the problem. If called with non-null values, validate the parameters. Test
that the literal strings are valid dates and test that @DateMin is earlier than
@DateMax. If the parameters are valid, return a result set that includes the
lnvoiceNumber, lnvoiceDate, lnvoiceTotal, and Balance for each invoice for
which the lnvoiceDate is within the date range, sorted with earliest invoice
first.
4. Code a call to the stored procedure created in exercise 3 that returns invoices
with an lnvoiceDate between December 10 and December 20, 2015. This
call should also catch any errors that are raised by the procedure and print the
error number and description.
5. Create a scalar-valued function named fnUnpaidlnvoicelD that returns the
lnvoicelD of the earliest invoice with an unpaid balance. Test the function in
the following SELECT statement:
SELECT VendorName, InvoiceNumber, InvoiceDueDate,
InvoiceTotal - CreditTotal - PaymentTotal AS Balance
FROM vendors JOIN Invoices
ON vendors.vendorID = Invoices.vendorID
WHERE InvoiceID = dbo.fnUnpaidinvoiceID();
6. Create a table-valued function named fnDateRange, similar to the stored
procedure of exercise 3. The function requires two parameters of data type
smalldatetime. Don't validate the parameters. Return a result set that includes
the lnvoiceNumber, lnvoiceDate, lnvoiceTotal, and Balance for each invoice
for which the lnvoiceDate is within the date range. Invoke the function
from within a SELECT statement to return those invoices with lnvoiceDate
between December 10 and December 20, 2015.
500 Section 4 Advanced SQL skills
7. Use the function you created in exercise 6 in a SELECT statement that returns
five columns: VendorName and the four columns returned by the function.
8. Create a trigger for the Invoices table that automatically inserts the vendor
name and address for a paid invoice into a table named ShippingLabels. The
trigger should fire any time the PaymentTotal column of the Invoices table is
updated. The structure of the ShippingLabels table is as follows:
CREATE TABLE ShippingLabels
(VendorName varchar ( 50) ,
VendorAddressl varchar ( 50) ,
vendorAddress2 varchar ( 50) ,
VendorCity varchar ( 50) ,
vendorState char(2),
vendorZipCode varchar(20));
Use this UPDATE statement to test the trigger:
UPDATE Invoices
SET PaymentTotal = 67.92, PaymentDate = '2016-04-23'
WHERE InvoiceID = 100;
9. Write a trigger that prohibits duplicate values except for nulls in the
NoDupName column of the following table:
CREATE TABLE TestUniqueNulls
(RowID int IDENTITY NO'T NULL,
NoDupName varchar(20) NULL);
(Note that you can't do this by using a unique constraint because the
constraint wouldn't allow duplicate null values.) If an INSERT or UPDATE
statement creates a duplicate value, roll back the statement and return an error
message.
Write a series of INSERT statements that tests that duplicate null values are
allowed but duplicates of other values are not.
16
How to manage
transactions and locking
If you've been working with a stand-alone copy of SQL Server, you've been
the only user of your database. In the real world, though, a database is typically
used by many users working simultaneously. Then, what happens when two
users try to update the same data at the same time?
In this chapter, you'll learn how SQL Server manages concurrent changes.
But first, you '11 learn how to combine related SQL statements into a single
unit, called a transaction. By learning these skills, you '11 be able to write code
that anticipates these conflicts.
Description
• A transaction is a group of database operations that are co1nbined into a logical
unit. By default, each SQL state1nent is treated as a separate transaction. However,
you can co1nbine any nu1nber of SQL state1n ents into a single transaction as shown
above.
• When you commit a transaction, the operations perfor1ned by the SQL state1nents
beco1ne a pennanent part of the database. Until it's co1n1nitted, you can undo all of
the changes 1nade to the database since the beginning of the transaction by rolling
back the transaction.
• A transaction is either co1n1nitted or rolled back in its entirety. Once you co1n1nit a
transaction, it can 't be rolled back.
For some systems, however, a violation of data integrity such as this one
is critical. For instance, consider the classic example of a transfer between two
accounts in a banking system. In that case, one update reduces the balance in the
first account and another update increases the balance in the second account. If
one of these updates fails, either the bank or the customer gets an unexpected
windfall. Because an error like this could cause problems even during the short
period of time it may take to fix it, these two updates should be coded as a
transaction.
DELETE Invoices
WHERE VendorID = 34;
IF @@ROWCOUNT > 1
BEGIN
-------
ROLLBACK TRAN;
PRINT 'More invoices than expected. Deletions rolled back.';
END;
ELSE
BEGIN
------
COMMIT TRAN;
PRINT 'Deletions committed to the database.';
END;
Description
• Altho ugh yo u can 01nit the TRAN keyword fro1n the COMMIT and ROLLBACK
state1nents, it's generally included for readability.
• By default, SQL Server is in autocommit mode. Then, unless yo u explicitly start
a transaction using the BEGIN TRAN state1nent, each state1nent is auto1natically
treated as a separate transaction. If the state1nent causes an error, it's auto1natically
rolled back. Otherwise, it's auto1natically co1n1nitted.
• Even if yo u don 't explicitly start a transaction, yo u can roll it back using the
ROLLBACK TRAN state1nent. However, you can 't explicitly co1n1nit an i1nplicit
transaction.
• When yo u use save points, yo u can roll a transaction back to the beginning or to a
particular save point. See fig ure 16-4 for details on using save points.
• Altho ugh yo u can na1ne a transaction in the BEGIN TRAN state1nent and yo u can
refer to that na1ne in the COMMIT TRAN and ROLLBACK TRAN state1nents,
yo u 're not likely to do that.
PRINT ,I I •
Description
• You can nest transactions by coding nested B EGIN T RAN state1nents. Each ti1ne
this state1nent is executed, it incre1nents the @ @TRANCOUNT syste1n function
by 1. Then, you can query this function to deter1nine how 1nany levels deep the
transactions are nested.
• If you execute a COMMIT T RAN state1nent when @@TRANCOUNT is equal to
1, all of the changes 1nade to the database during the transaction are co1n1nitted and
@@TRANCOUNT is set to zero. If @@TR ANCOUNT is greater than 1, however,
the changes aren ' t co1n1nitted. Instead, @@TRANCOUNT is si1nply decre1nented
by 1.
• The ROLLBACK T RAN state1nent rolls back all active transactions regardless of
the nesting level where it's coded. It also sets the value of @@TRANCOUNT back
to 0.
• Since there are few progra1n1ning proble1ns that you can only solve using nested
transactions, you probably won 't use the1n often.
VendorlD VendorName
1 t..2 ...................... 1 National Information Data Or
2 3 Register of CopyTights
3 4 Jobtrak ,_
VendorlD VendorName
1 l. 2....................1 National Information Data Qr
2 3 Register of CopyTights
3 4 Jobtrak 'I
"""'
Description
• You can partially roll back a transaction if you use save points. If you code a save
point na1ne in the ROLLBACK TRAN state1nent, the syste1n rolls back all of the
state1nents to that save point.
• If you don 't code a save point na1ne, the ROLLBACK TRAN state1nent rolls back
the entire transaction.
• Since you can 't code a save point na1ne in a COMMIT TRAN state1nent, the
syste1n always co1n1nits the entire transaction.
• As with nested transactions, there are few practical progra1n1ning proble1ns that you
can solve using save points.
An introduction to concurrency
and locking
When two or more users have access to the same database, it's possible for
them to be working with the same data at the same time. This is called
concurrency. Concurrency isn't a problem when two users retrieve the same
data at the same time. If they then try to update that data, however, that can be a
problem. In the topics that follow, you 'II learn more about concurrency and how
SQL Server uses locking to prevent concurrency problems. You '11 also learn how
you can control the types of problems that are allowed.
Two transactions that retrieve and then modify the data in the same row
Transaction A
BEGIN TRAN;
DECLARE @InvoiceTotal money, @PaymentTotal money, @CreditTotal money;
SELECT @InvoiceTotal - InvoiceTotal, @CreditTotal = CreditTotal,
@PaymentTotal = PaymentTotal FROM Invoices WHERE InvoiceID = 112;
UPDATE Invoices
SET InvoiceTotal - @InvoiceTotal, CreditTotal = @CreditTotal + 317.40,
PaymentTotal - @PaymentTotal WHERE InvoiceID = 112;
COMMIT TRAN;
Transaction B
BEGIN TRAN;
DECLARE @InvoiceTotal money, @PaymentTotal money, @CreditTotal money;
SELECT @InvoiceTotal - InvoiceTotal, @CreditTotal = CreditTotal,
@PaymentTotal = PaymentTotal FROM Invoices WHERE InvoiceID = 112;
UPDATE Invoices
SET InvoiceTotal = @InvoiceTotal, CreditTotal = @CreditTotal,
PaymentTotal = @InvoiceTotal - @CreditTotal,
PaymentDate = GetDate() WHERE InvoiceID = 112;
COMMIT TRAN;
Description
• Concurrency is the ability of a system to support two or more transactions working
with the same data at the same time.
• Because small systems have few users, concurrency isn't generally a problem on
these systems. On large systems with many users and many transactions, however,
you may need to account for concurrency in your SQL code.
• Concurrency is a problem only when the data is being modified. When two or more
transactions simply read the same data, the transactions don't affect each other.
• You can avoid some database concurrency problems by using locks, which delay
the execution of a transaction if it conflicts with a transaction that's already
running. Then, the second transaction can't use the data until the first transaction
releases the lock.
• Although SQL Server automatically enforces locking, you can write more efficient
code by understanding and customizing locking in your programs.
Description
• In a large syste1n with 1nany users, you should expect for these kinds of proble1ns
to occur. In general, you don ' t need to take any action except to anticipate the
proble1n . In 1nany cases, if the query is resub1nitted, the proble1n goes away.
• On so1ne syste1ns, if two transactions overwrite each other, the validity of the
database is co1npro1nised and resub1nitting one of the transactions will not
eli1ninate the proble1n . If you 're working on such a syste1n, you 1n ust anticipate
these concurrency proble1ns and account for the1n in your code.
• You should consider these locking proble1ns as you write your code. If one of these
proble1ns would affect data integrity, you can change the default locking behavior
by setting the transaction isolation level as shown in the next figure.
Figu re 16-6 The four concu rre ncy problems that locks can prevent
514 Section 4 Advanced SQL skills
Description
• Since SQL Server 1nanages locking auto1natically, yo u can 't control every aspect of
locking for yo ur transactions. However, yo u can set the isolation level in yo ur code.
• The transaction isolation level controls the degree to which transactions are isolated
fro1n one another. The server isolates transactions by using 1nore restrictive locking
behavior. If yo u isolate yo ur transactions fro1n other transactions, concurrency
proble1ns are reduced or eli1ninated.
• Yo u specify the transaction isolation level by changing the ISOLATION LEVEL
session setting. The default transaction isolation level is READ COMMITTED. At
this level, so1ne lost updates can occur, but this is acceptable for 1nost transactions.
• The READ UNCOMMITTED isolation level doesn ' t set any locks and ignores locks
that are already held. Setting this level results in the highest possible perfor1nance for
your query, but at the risk of every kind of concurrency proble1n. For this reason, yo u
should only use this level for data that is rarely updated.
• The REPEATABLE READ level places locks on all data that's used in a transaction,
preventing other users fro1n updating that data. However, this isolation level still
allows inserts, so phanto1n reads can occur.
• The SNAPSHOT level was introd uced with SQL Server 2005. It uses ro w versioning
rather than locks to provide read consistency. To use this level, yo u use the ALTER
DATABASE state1nent to set the ALLOW_SNAPSHOT_ISOLATION option on.
• The SERIALIZABLE level places a lock on all data that's used in a transaction.
Since each transaction 1nust wait for the previous transaction to co1n1nit, the
transactions are handled in sequence. This is the 1nost restrictive of the five isolation
levels.
• Yo u can also use row versioning with the READ COMMITTED isolation level. To
do that, yo u 1nust set the READ_COMMITTED _SNAPSHOT database option on.
• With row versioning, each ti1ne a transaction 1nodifies a row, SQL Server stores an
ilnage of the row as it existed before the 1nodification. That way, read operations
that use row versioning retrieve the row as it existed at the start of the transaction
(SNAPSHOT) or state1nent (READ COMMITTED).
Description
• SQL Server can lock data at vario us levels, known as lockable resources. The ten
levels fo r1n a hierarchy based on granularity, which refers to the a1no unt of data
the resource enco1npasses. A resource that enco1npasses 1nore data than another
resource is said to be less gran ular, or coarser, than the other resource.
• A coarse-grain lock affects 1nore data than a fine-grain lock. For this reason, 1nore
transactions are locked out when the lock is less gran ular. Since this slows database
perfor1nance, the server assigns locks of the finest possible gran ularity.
• Locking is auto1natically enabled and controlled by a SQL Server application called
the lock manager. This progra1n generates locking events and handles the setting
and releasing of locks.
• Maintaining several fine-grain locks requires greater server resources than
1naintaining one coarse-grain lock. For this reason, the lock 1nanager will
auto1natically convert 1nultiple fine-grain locks on the sa1ne resource into a single
coarse-grain lock. This is known as lock escalation.
Description
• SQL Server auto1natically deter1nines the appropriate lock mode for your transaction.
In general, retrieval operations acquire shared locks, and update operations acquire
exclusive locks. As a single transaction is being processed, its lock 1nay have to be
converted, or promoted, fro1n one lock 1node to a 1nore exclusive lock 1node.
• An Update (U) lock is acquired during the first part of an update, when the data
is being read. Later, if the data is changed, the Update lock is pro1noted to an
Exclusive (X) lock. This can prevent a co1n1non locking proble1n called a deadlock.
• An intent lock indicates that SQL Server intends to acquire a shared lock or an
exclusive lock on a finer-grain resource. For exa1nple, an Intent Shared (IS) lock
acquired at the table level 1neans that the transaction intends to acquire shared locks
on pages or rows within that table. This prevents another transaction fro1n acquiring
an exclusive lock on the table containing that page or row.
• Schema locks are placed on a table's design. Sche1na Modification (Sch-M) locks
are acquired when the design is being changed with a DDL state1nent. Sche1na
Stability (Sch-S) locks are acquired when co1npiling a query to prevent a sche1na
change while the query is co1npiling.
• The B ulk Update (BU) lock 1node is acquired for the BULK INSERT state1nent
and by the bulk copy progra1n (bcp). Since these operations are typically done by
DBAs, neither is presented in this book.
The three intent locks differ based on the portion of the resource and the
type of lock that the transaction intends to acquire. An Intent Shared (IS) lock
indicates that the transaction intends to acquire a shared lock on some, but
not all, of the finer-grained resource. Likewise, an Intent Exclusive (IX) lock
indicates an intent to acquire an exclusive lock on some, but not all, of the
resource. Finally, a Shared with Intent Exclusive (SIX) lock indicates an intent to
acquire both an exclusive lock on some of the resource and a shared lock on the
entire resource.
The Bulk Update (BU) lock mode is used exclusively for copying large
amounts of data in bulk into a database using either the BULK INSERT
statement or the bulk copy program. Since bulk copies are usually done by
DBAs to create databases based on other sources, they're not presented in this
book.
Description
• If a reso urce is already locked by a transaction, a request by another transaction
to acquire a lock on the sa1ne reso urce will be granted or denied depending on the
co1npatibility of the two lock 1nodes.
• For exa1nple, if a transaction has a Shared (S) lock on a table and another
transaction requests an Exclusive (X) lock on the sa1ne table, the lock isn't granted.
The second transaction 1n ust wait until the first transaction releases its lock.
• Intent locks can help itnprove perfortnance since the server only needs to exatnine
the high-level locks rather than exa1nining every low-level lock.
WAITFOR DELAY 1
00 : 00 : 0 5 1
;
Description
• A deadlock occurs when neither of two transactions can be co1n1nitted because they
each have a lock on a resource needed by the other.
• SQL Server auto1natically detects deadlocks and allows one of the transactions to
co1n1nit. The other transaction is rolled back and raises error nu1nber 1205. This
transaction is known as the deadlock victim.
Note
• To test this exa1nple, yo u 1nust execute transaction A first and then execute
transaction B within five seconds.
Make large changes when you can be assured of nearly exclusive access
• If you need to change millions of rows in an active table, don't do so during hours
of peak usage.
• If possible, give yourself exclusive access to the database before making large
changes.
Perspective
In this chapter, you've learned the ways that SQL Server protects your data
from the problems that can occur on a real-world system. Since the failure of
one or more related SQL statements can violate data integrity, you learned how
to prevent these problems by grouping the statements into transactions. Since
multiple transactions can simultaneously modify the same data, you learned
how to prevent concurrency problems by setting the transaction isolation level
to change the default locking behavior. And since changing the isolation level
can increase the chances of deadlocks, you learned defensive programming
techniques to prevent deadlocks.
Terms
transaction row vers1on1ng
commit a transaction granularity
roll back a transaction fine-grain lock
autocommit mode coarse-grain lock
nested transactions lock manager
save point lock escalation
concurrency lock mode
locking shared lock
lost update exclusive lock
dirty read intent lock
nonrepeatable read schema lock
phantom read lock promotion
transaction isolation level deadlock
lockable resource deadlock victim
Exercises
1. Write a set of action queries coded as a transaction to reflect the following
change: United Parcel Service has been purchased by Federal Express
Corporation and the new company is named Fed UP. Rename one of the
vendors and delete the other after updating the VendorID column in the
Invoices table.
2. Write a set of action queries coded as a transaction to move rows from the
Invoices table to the lnvoiceArchive table. Insert all paid invoices from
Invoices into lnvoiceArchive, but only if the invoice doesn't already exist
in the lnvoiceArchive table. Then, delete all paid invoices from the Invoices
table, but only if the invoice exists in the lnvoiceArchive table.
17
How to manage
database security
If you've been using a stand-alone copy of SQL Server installed on your own
computer, the security of the system hasn't been of concern. When you install
SQL Server for use in a production environment, however, you must configure
security to prevent misuse of your data. In this chapter, you 'II learn how to do
that using either the Management Studio or Transact-SQL.
or
►
SQL Server authentication
(uses SQL Server login ID)
Specific SQL
DDL statement
II
Description
• Typically, a network user 1nust log on to the network at a PC using a login ID and
password. If the client PC uses Windows, SQL Server can use the Windows login
ID defined for the user. Otherwise, yo u can create a separate SQL Server login ID.
• Once a user is logged on to SQL Server, the security configuration deter1nines
which database objects the user can work with and which SQL state1nents the user
can execute.
• Permissions deter1nine the actions a user can take on a database object, such as a
table, view, or stored procedure, on the objects in a sche1na, on a database, and on a
server.
• A role is a collection of per1nissions that yo u can assign to a user by assigning the
user to that role.
• Yo u can create a collection of users in Windows called a group. Then yo u can
assign per1nissions and roles either to individual users or to a gro up of users.
• The users, gro ups, logins, and roles that have access to a server are called
principals. The entities that can be secured on a server, including the server itself,
are called securables.
• If yo u need to set up a new syste1n with 1nany users, it's often easier to code SQL
scripts using the SQL security state1nents. The Manage1nent Studio is better for
1naking changes to an existing syste1n or for setting up a s1nall syste1n.
• Even if yo u use the Manage1nent Studio to 1nanage security, yo u should know how
to 1nanage security with Transact-SQL state1nents. That will help yo u understand
the underlying structure of SQL Server security.
0 None
@ Fai ed logins only
0 Successful logins only
■
.._.._ o. . . . ~ ace" ..,
-Connedion
Server:
localhost\SQ LEXPRESS
Pass---O"d
Options
l.
Connection:
RAY-PC\Ray
O Enable C2 audit tracing
~ View connection properties
O Cross database ownership chai~ng
Pr
Ready
I OK II Cancel ;
Description
• To change the SQL Server authentication mode, right-click on the server in the
Object Explorer of the Manage1nent Studio, select the Properties co1n1nand to
display the Server Properties dialog box, then display the Security page.
• When yo u use Windo ws authentication, access to SQL Server is controlled via the
security integrated into Windows. This si1nplifies login because Windows users
only have to log on once.
• When yo u use SQL Server authentication, access to SQL Server is controlled via the
separate security built into SQL Server. The user has a login ID and password that
are distinct fro1n their Windows login ID and password, so they have to log on twice.
Description
• You use the CREATE LOGIN statement to create a new SQL Server login ID or to
create a new login ID from a Windows account. This statement was introduced with
SQL Server 2005.
• If you don't specify a default database when you create a login, the default is set
to master. If you don't specify a default language, the default is set to the default
language of the server. Unless it's been changed, the server language default is
English.
• The password you specify for a SQL Server login ID should be a strong password.
A strong password is not easy to guess and cannot easily be hacked. A password
can have up to 128 characters.
• If you include the MUST_CHANGE option, SQL Server will prompt the user for a
new password the first time the login ID is used.
• The CHECK_EXPIRATION option determines whether SQL Server enforces
password expiration policy. The CHECK_POLICY option determines if password
policies, such as strong passwords, are enforced. These options are enforced only if
SQL Server is running on Windows Server 2003 or later.
stored procedure to add a new SQL Server login ID. Although these stored
procedures are still supported by SQL Server 2016, they will be dropped in a
future release of SQL Server. So you should use the statements presented in this
chapter instead of the equivalent stored procedures.
Statements that use the ALTER LOGIN and DROP LOGIN statements
A statement that changes the password for a SQL Server login ID
ALTER LOGIN JohnDoe WITH PASSWORD= 'lg22A%G45x';
Description
• You use the ALTER LOGIN statement to enable or disable a login ID, change the
name for a login ID, or change the default database or language. For a SQL Server
login ID, you can also change the password and the password options.
• You use the DROP LOGIN statement to drop a login ID.
• The ALTER LOGIN and DROP LOGIN statements were introduced with SQL
Server 2005.
Description
• You use the CREATE USER statement to create a user for a login ID for the current
database. If the login name is the same as the user name, you can omit the FOR
LOGIN clause.
• When you create a database user, you can specify a default schema. Then, SQL
Server will look in this schema when it searches for objects for the database user
before it looks in the default schema (dbo ).
• The ALTER USER statement lets you change the name of an existing database user
or change the default schema for a user.
• You use the DROP USER statement to delete a user from the current database.
• Since all three of these statements work on the current database, you must change
the database context using the USE statement before executing any of these
statements.
• The CREATE USER, ALTER USER, and DROP USER statements were
introduced with SQL Server 2005.
Description
• You use the CREATE SCHEMA statement to create a schema in the current
database. You can also create tables and views within the new schema, and you can
grant, revoke, or deny permissions for those tables and views.
• After you create a schema, you can create any object within that schema by
qualifying the object name with the schema name.
• You use the ALTER SCHEMA statement to transfer an object from one schema to
another.
• You can't transfer an object from one schema to another if any views or functions
are bound to it.
• When you transfer an object from one schema to another, all the permissions that
were associated with that object are dropped.
• You use the DROP SCHEMA statement to delete a schema. The schema you delete
must not contain any objects.
• The CREATE SCHEMA, ALTER SCHEMA, and DROP SCHEMA statements
were introduced with SQL Server 2005.
A GRANT statement that grants SELECT permission for the Invoices table
GRANT SELECT
ON Invoices
TO SusanRoberts;
Description
• You use this GRANT statement format to give a user permission to work with a
database object. This format of the REVOKE statement takes object permissions
away. See figure 17 -8 for a list of the standard permissions that can be granted for
objects.
• The object_name argument specifies the object for which the permission is being
granted or revoked and can specify a table, a view, a stored procedure, or a
user-defined function. If you specify a table, a view, or a table-valued function,
you can also list the columns for which SELECT, UPDATE, or REFERENCES
permissions are granted or revoked.
• The database_principal argument in the TO and FROM clauses can be the name
of a database user or a user-defined role.
• The WITH GRANT OPTION clause gives a user permission to grant this
permission to other users.
• The REVOKE statement includes two clauses that undo WITH GRANT OPTION.
GRANT OPTION FOR revokes the user's permission to grant the permission to
others. CASCADE revokes the permission from any other users who were given
the permission by this user.
• Since both the GRANT and REVOKE statements work on the current database,
you must first change the database context using the USE statement.
Description
• Yo u can only grant per1nissions that are appropriate for the object or sche1na.
• Yo u can grant or revoke SELECT, UPDATE, or REFERENCES per1nission to
specific colu1nns in a table, view, or table-valued function. However, a view is
typically a better way to li1nit access to specific colu1nns.
Description
• You use this format of the GRANT statement to give a user permission to work
with all the objects in a database schema. This format of the REVOKE statement
takes schema permissions away. These statements work just as they do for object
perm1ss1ons.
• To create an object in a schema or to delete an object from a schema, the user must
have ALTER permission to the schema. To create an object, the user must also have
CREATE permission to the database that contains the object. See figure 17 -10 for
information on database permissions.
• You can also grant or revoke the CREATE SEQUENCE permission on a schema.
• The ON clause in the GRANT and REVOKE statements includes a class name
(SCHEMA) and a scope qualifier(::). Although class names and scope qualifiers
can be used with other Transact-SQL statements, they're not usually required.
Description
• In addition to granting or revoking permissions for objects and schemas, you can
grant or revoke permissions for databases.
• The list of SQL statements shown above only includes those discussed in this book.
For a complete list, refer to the "GRANT Database Permissions (Transact-SQL)"
topic in the SQL Server documentation.
Description
• You can also use the GRANT and REVOKE state1nents to grant and revoke
per1nissions for the entire server. When yo u do that, yo u specify a login or server
role on the TO or FROM clause.
• For a co1nplete list of server per1nissions, refer to the "GRANT Server Per1nissions
(Transact-SQL)" topic in the SQL Server docu1nentation.
Description
• A role is a collection of permissions you can assign to a user or group of users. By
assigning a user to a role, you grant that user all of the permissions of the role. You
can use roles to simplify user and security administration.
• SQL Server has built-in, or fixed, roles defined at the server level and at the
database level. In addition, you can create user-defined roles for your server or
database.
• Each role is assigned a set of permissions. For example, the dbcreator role can
execute CREATE DATABASE, ALTER DATABASE, DROP DATABASE, and
RESTORE DATABASE statements. This role can also add new members to the
role.
• You use the ALTER SERVER ROLE statement to add a user to or remove a user
from a server role. You can also use this statement to rename a user-defined server
role.
• The fixed server roles are intended for users who are involved in the administration
of the server. For a complete list of the fixed server roles, see the "Server-level
Roles" topic in the SQL Server documentation.
• The ALTER SERVER ROLE statement was introduced with SQL Server 2012. In
previous versions of SQL Server, you used the sp_AddSrvRoleMember system
stored procedure to add a user to a server role, and you used the
sp_DropSrvRoleMember procedure to remove a user from a server role.
Description
• You use the CREATE SERVER ROLE statement to create a user-defined server
role. Role names can be up to 128 characters in length and can include letters,
symbols, and numbers, but not the backslash(\) character.
• The AUTHORIZATION clause lets you specify a login or fixed server role that
owns the user-defined role. If you omit this clause, the role will be owned by the
login that executes the statement.
• Once you create a server role, you can grant permissions to or revoke permissions
from the role. To do that, the current database must be master.
• To add members to a user-defined server role or delete members from the role, you
use the ALTER SERVER ROLE statement shown in figure 17-12.
• You use the DROP SERVER ROLE statement to delete a user-defined server role.
You can't delete a fixed server role or the public server role.
• Before you can delete a server role, you must delete all of its members. To find out
how to list the members of a role, see figure 17 -14.
• The CREATE SERVER ROLE and DROP SERVER ROLE statements were
introduced with SQL Server 2012.
2 sysadmin 3 1
3 securityadmin 4 1
4 serveradmin 5 1 i
5 setupadmin 6 1
6 processadmin 7 1
7 diskadmin 8 1
8 dbcreator 9 1
9 bulkadmin 10 1
10 Consultant 271 0
Description
• The sys.server_principals catalog view contains information about each principal
defined on the server. To display information about just the server roles, use a
SELECT statement with a WHERE clause that checks for a type of 'R'.
• The sys.server_role_members catalog view contains a list of each role
principal/member principal combination. To display information about the
members of a server role, join this view with the sys.server_role_member view
and restrict the results to the principal ID of the role whose members you want to
display.
• To display information about just the fixed server roles and members, you can use
the sp_HelpSrvRole and sp_HelpSrvRoleMember system stored procedures.
Figure 17-14 How to display information about server roles and role members
556 Section 4 Advanced SQL skills
Description
• The fixed database roles are added to each database yo u create. Yo u can add and
delete 1ne1nbers fro1n these roles, but yo u can 't delete the roles.
• Yo u use the ALTER ROLE state1nent to assign a user to or re1nove a user fro1n a
database role in the current database. Yo u can also use this state1nent to change the
na1ne of a user-defined database role.
• The database_principal para1neter can be the na1ne of a database user, a
user-defined database role, or a Windows login or gro up. If yo u specify a Windows
login or gro up that doesn 't have a corresponding database user, a database user is
created.
• The users yo u specify are assigned to or re1noved fro1n the role yo u na1ne in the
current database. Because of that, yo u should be sure to change the database
context before executing one of these stored procedures.
• SQL Server also provides a public database role. Any user that's not given specific
per1nissions on a securable is given the per1nissions assigned to the public role.
• Prior to SQL Server 2012, yo u could use the ALTER ROLE state1nent only to
change the na1ne of a user-defined database role. To add or drop a role, yo u used
the sp_AddRoleMe1nber or sp_DropRoleMe1nber syste1n stored procedure.
Description
• You use the CREATE ROLE statement to create a user-defined database role. Role
names can be up to 128 characters in length and can include letters, symbols, and
numbers, but not the backslash (\) character.
• Once you create a database role, you can grant permissions to or revoke
permissions from the role. Then, you grant or revoke permissions for every member
of the role.
• To add members to a user-defined database role, delete members from the role, or
rename the role, you use the ALTER ROLE statement shown in figure 17-15.
• You use the DROP ROLE statement to delete user-defined database roles. You can't
delete a fixed database role or the public database role.
• Before you can delete a database role, you must delete all of its members. To find
out how to list the members of a role, see figure 17 -17.
• The CREATE ROLE and DROP ROLE statements were introduced with SQL
Server 2005.
Description
• To display infor1nation about the roles defined in the current database, use the
sp_HelpRole syste1n stored procedure. If you don 't specify a role na1ne on this
procedure, infor1nation about all of the roles in the database is returned.
• To display infor1nation about the 1ne1nbers of a database role, use the
sp_HelpRoleMe1nber syste1n stored procedure. If you don 't specify the role na1ne
on this procedure, infor1nation about the 1ne1nbers of all of the roles in the database
that have at least one 1ne1nber is returned.
• You can display additional infor1nation about database roles using the
sys.database_principals and sys.database_role_1ne1nbers catalog views. These
views are si1nilar to the sys.server_principals and sys.server_role_1ne1nbers views
described in figure 17 -14.
Figure 17-17 How to display information about database roles and role members
562 Section 4 Advanced SQL skills
Description
• The per1nissions granted to individual users are granted by two sources: per1nissions
granted to their user na1nes or login IDs and per1nissions granted through any roles to
which they are 1ne1nbers.
• The DENY state1nent differs fro1n the REVOKE state1nent in that DENY prevents the
per1nission fro1n being granted by role 1ne1nbership. A denied per1nission can 't be granted
by role 1ne1nbership, but a revoked per1nission can.
GRANT SELECT
ON Invoices
TO AppinvoiceQuery;
Description
• An application role is a special type of user-define database role. It can 't contain any
1ne1nbers, but it's activated when a connection executes the sp_SetAppRole syste1n
stored procedure.
• Once the connection activates an application role, the nor1nal security for the login ID set
by the per1n issions for the ID and its roles is ignored. Instead, the connection assu1nes a
new security profile as defined by the per1nissions for the application role.
• Once a connection activates an application role, the application role re1nains in effect
until the connection is closed or until the sp_UnsetAppRole procedure is executed. To
use sp_UnsetAppRole, you 1n ust create a cookie when you execute sp_SetAppRole.
• Application roles are typically used by application progra1ns that 1nanage their own
security. Then, those progra1ns can control the users that can log on to the server.
Mapped Credentials
I
Credential Provider
I Add 1
Connection:
RAY-PC\Ray
~ View connection properties
Pr I
Ready
- I
[<default> vi
I Default language:
I OK II Cancel ;
Description
• To create a new login ID, expand the Security folder for the server in the Object
Explorer. Then, right-click the Logins folder and select New Login to display the
Login - New dialog box.
• Select the type of authentication you want to use and then specify the appropriate
settings. The settings that are available depend on whether you select Windows or
SQL Server authentication.
• To 1nodify a login ID, right-click the ID in the Object Explorer and select
Properties to display the Login Properties dialog box. The General page of this
dialog box lets you change all the settings for the login ID except for the login
na1ne and the authentication 1node.
• You can use the options on the Status page of the Login Properties dialog box to
deny or grant a login ID per1nission to connect to SQL Server. You can also disable
or enable a login ID.
• To delete a login ID, right-click the ID in the Object Explorer and select Delete to
display the Delete Object dialog box. Click the OK button to delete the login ID.
Connedion
Server:
localhost\SQ LEXPRESS
Connection:
RAY-PC\Ray
~ View connection properties
Pr
Ready
OK !I Cancel
Description
• To work with the server roles fo r a login ID, right-click the ID in the Object
Explorer and select Properties to display the Login Properties dialog box. Then,
display the Server Roles page. The roles that the login ID is currently assigned to
are checked in the list that's displayed.
• To add or re1nove a login ID fro1n a server role, select or deselect the role.
Figure 17-21 How to work with the server roles for a login ID
570 Section 4 Advanced SQL skills
OK !I Cancel
~ Ovmed Schemas
~ Membership User name: IJohnDoe I
~ Securables r-
~ Extended Properties Securables: Search ...
~
Schema Name Type
~ Fdes
~ Filegroups Server name: IDESKTOP-8TASCl2\SQLEXPRESS I
~ Options
View server permissions
~ Change Tracking
~ Permissions Database name: IAP
~ Ex!ended Properties
~ Query Store Users or roles: L Search .. 7
Name Type
~ /\pplnvoiceOuery /\pplication role
InvoiceEntry Database role
.......................................................
£ i JohnOoe .............·i User riJ
£ MartinRey User
public Oat.abase role
,. -
I OK IL Cancel7
..
-
Description
• To display the per1nissions for a database, right-click the database in the Object
Explorer, select Properties to display the Database Properties dialog box, and
display the Per1n issions page.
• By default, all database users except for guest are included in the Users or roles list.
To add the guest user or any syste1n or user-defined roles, click the Search button
and select the users and roles fro1n the dialog box that's displayed.
• To grant a user or role per1n ission to perfor1n a database operation, select the user
or role and then select the Grant option for the per1n ission. Yo u can also select the
With Grant option to allow the user or role to grant the per1nission to other users
and roles.
• To revoke a user or role per1nission to perfor1n a database operation, deselect the
Grant option.
• To deny the user per1n ission to a database operation, select the Deny option.
Perspective
Although managing security on a server can be complex, SQL Server
provides useful tools to simplify the job. In this chapter, you've learned how to
manage security for your server and database using both Transact-SQL and the
Management Studio. Once you 're familiar with both of these techniques, you
can use the one that's easiest for the security task at hand.
Unfortunately, the techniques presented in this chapter don't secure your
data if a thief is able to steal a hard drive or backup tape that contains the
data files for the database. In that case, the thief can attach the data files to a
different server and gain access to the data. To close this security hole, you
can encrypt the data files and store the encryption key in a different location.
That way, even if the data files are stolen, the thief won't be able to open them
without the key. In the past, implementing encryption was a complicated
process that involved modifying the structure of the database. Starting with
SQL Server 2008, however, transparent data encryption (TDE) makes it easy
to encrypt the entire database without affecting existing applications. For more
information about TDE, you can refer to the SQL Server documentation.
Terms
login ID Windows authentication
perm1ss1ons SQL Server authentication
object permissions strong password
schema permissions scope qualifier
database permissions fixed role
server perm1ss1ons fixed server role
role user-defined server role
group fixed database role
principal user-defined database role
securable application role
authentication mode
Chapter 17 How to manage database security 577
Exercises
1. Write a script that creates a user-defined database role named PaymentEntry
in the AP database. Give UPDATE permission to the new role for the Invoices
table, UPDATE and INSERT permission for the lnvoiceLineltems table, and
SELECT permission for all user tables.
2. Write a script that (1) creates a login ID named "AAaron" with the password
"aaar9999"; (2) sets the default database for the login to the AP database; (3)
creates a user named "Aaron" for the login; and (4) assigns the user to the
PaymentEntry role you created in exercise 1.
3. Write a script that creates four login IDs based on the contents of a new table
called NewLogins:
CREATE TABLE NewLogins
(LoginName varchar(128));
INSERT NewLogins
VALUES ( ' BBrown' ) , ( 'CChapl in ' ) , ( 'DDyer' ) , ( 'EE.b bers ' ) ;
Use dynamic SQL and a cursor to perform four actions for each row in this
table: (1) create a login with a temporary password based on the first four
letters of the login name followed by "9999"; (2) set the default database to the
AP database; (3) create a user for the login with the same name as the login;
and (4) assign the user to the PaymentEntry role you created in exercise 1.
4. Using the Management Studio, create a login ID named "FFalk" with the
password "ffal9999," and set the default database to the AP database. Then,
grant the login ID access to the AP database, create a user for the login ID
named "FFalk", and assign the user to the PaymentEntry role you created in
exercise 1.
Note: If you get an error that says "The MUST_CHANGE option is not
supported", you can deselect the "Enforce password policy" option for the
login ID.
5. Write a script that removes the user-defined database role named
PaymentEntry. (Hint: This script should begin by removing all users from this
role.)
6. Write a script that (1) creates a schema named Admin, (2) transfers the table
named ContactUpdates from the dbo schema to the Admin schema, (3)
assigns the Admin schema as the default schema for the user named Aaron
that you created in exercise 2, and (4) grants all standard privileges except for
REFERENCES and ALTER to AAaron for the Admin schema.
18
How to work with XML
In this chapter, you'll learn how to use SQL Server to work with XML data.
That includes using the xml data type, using an XML schema to validate the
data that's stored in an xml type, and converting relational data to XML and
XML to relational data. Many of the features presented in this chapter were
introduced with SQL Server 2005, and they make it easier to work with XML.
An introduction to XML
Before you learn how to use SQL Server to work with XML, you need to
understand some basic XML concepts. In particular, you need to understand how
XML can be used to structure data, and you need to understand how an XML
schema can be used to validate XML data.
An XML document
XML (Extensible Markup Language) can be used to create an XML
document that contains data that has been structured with XML tags. For
example, figure 18-1 shows an XML document that contains data about an event
that caused a DDL trigger to fire. You learned how to return an XML document
like this one in chapter 15 using the EVENTDATA function within a DDL
trigger.
Within an XML document, an element begins with a start tag and ends with
an end tag . In this figure, for example, the <EventType> tag marks the start of
the EventType element, and the </EventType> tag marks the end of this element.
Within a start tag, one or more attributes can be coded. In this figure, for
example, the start tag for the SetOptions element contains five attributes:
ANSI_NULLS, ANSI_NULL_DEFAULT, ANSI_PADDING,
QUOTED_IDENTIFIER, and ENCRYPTED. Here, each attribute consists of an
attribute name, an equal sign, and a string value in quotes.
Although values can be assigned to attributes, a value can also be coded
between the start and end tags for an element. That's the case with most of the
elements in this figure. The EventType element, for example, contains the string
value "CREATE_TABLE."
Elements can also contain other elements. An element that's contained
within another element is known as a child element. Conversely, the element that
contains a child element is known as the child's parent element. In this figure,
for example, the SetOptions element is a child element of the TSQLCommand
element, and the TSQLCommand element is the parent element of the
SetOptions element. Although it's not shown here, a child element can also
repeat within a parent element.
The highest-level element in an XML document is known as the root
element. In this figure, the EVENT _INSTANCE element is the root element. A
well-formed XML document can have only one root element.
Chapter 18 How to work with XML 581
An XML document
<EVENT_INSTANCE>
<EventType>CREATE_TABLE</EventType>
<PostTime>2016-0l-05Tl2:38:23.147</PostTime>
<SPID>54</SPID>
<ServerName>RAY-PC\SQLE.XPRESS< /ServerName>
<LoginName>MicrosoftAccount\rhalliday@murach.com</LoginName>
<UserName>dbo</UserName>
<DatabaseName>AP</DatabaseName>
<SchemaName>dbo</SchemaName>
<ObjectName>VendorsTest</ObjectName>
<ObjectType>TABLE</ObjectType>
<TSQLCommand>
<SetOptions ANSI_NULLS="ON" ANSI_NULL_DEFAULT="ON" ANSI_PADDING="ON"
QUOTED_IDENTIFIER="ON" ENCRYPTED="FALSE" />
<CommandText>
CREATE TABLE VendorsTest
(VendorID int, VendorName varchar(S0));
</CommandText>
</TSQLCommand>
</EVENT_INSTANCE>
Description
• XML (Extensible Markup Language) is used to structure data using XML tags. An
XML tag begins with< and ends with>.
• An XML document contains data that has been structured with XML tags.
• An element begins with a start tag and ends with an end tag. The start tag provides
the name of the element and can contain one or more attributes. An attribute
consists of an attribute name, an equal sign, and a string value in quotes. The end
tag repeats the name, prefixed with a slash (/).
• Text can also be coded between an element's start and end tags. This text is referred
to as the element's content.
• Elements can contain other elements. An element that's contained within another
element is known as a child element. The element that contains a child element is
known as the child's parent element. Child elements can also repeat within a parent
element.
• The highest-level element in an XML document is known as the root element. An
XML document can have only one root element.
• The EVENTDATA function described in chapter 15 returns an xml data type that
contains an XML document like the one shown in this figure.
An XML schema
The XML Schema Definition (XSD) language can be used to define an XML
schema, which is a set of rules that an XML document must follow to be valid.
Although there are several languages for defining XML schemas, the XSD
language is the only one that you can use with SQL Server. Figure 18-2 shows
an XML schema that can be used to validate the XML document shown in figure
18-1. In addition, you may notice that the schema itself is an XML document.
To start, this XML schema uses the schema element to specify some attributes
that apply to the entire schema. That includes the xmlns attribute that defines the
prefix for the XML namespace that's used throughout the rest of the schema to
qualify the name of each element. Then, this schema defines each of the elements
and attributes that are used by the XML document shown in figure 18-1. This
definition specifies whether an element can contain other elements, the sequence
of the elements, and the name and data type of each element.
Unfortunately, the details of the XSD language are beyond the scope of
this book. As a result, the examples in this chapter only use the XML schema
presented in this figure. Fortunately, if you 're working with an industry standard
XML document, an XSD has probably already been created for it. As a result,
you may be able to get the XSD from a colleague, or you may be able to find the
XSD by searching the Internet.
If you need to create an XML schema for an XML document, you can use the
Management Studio's XML Editor to generate one as described in figure 18-4.
Then, if necessary, you can edit the generated XML schema so it's appropriate
for your XML document. To do that, however, you may need to learn more about
the XSD language by searching the Internet or by getting a book about working
with XML.
Chapter 18 How to work with XML 583
Description
• The XML Schema Definition (XSD) language can be used to define an XML schema,
which is a set of rules that an XML document must follow to be valid.
• You may be able to find an XSD for some types of XML documents by searching
the Internet. If not, you can use the Management Studio's XML Editor to generate
an XSD for an XML document as described in figure 18-4. The details for working
with the XSD language are beyond the scope of this book.
• SQL Server can use the XML schema shown in this figure to validate the XML
document shown in figure 18-1.
Description
• You can use the x1nl data type just as you use 1nost other SQL Server data types. In
particular, you can use it as the type for a colu1nn in a table or a variable in a script,
procedure, function, or trigger.
• Within a DDL trigger, the EVENTDATA function returns an XML docu1nent like
the one shown in figure 18-1.
• The x1nl type is i1nplicitly cast to a string when necessary and a string is i1nplicitly
cast to the x1nl type.
EventData1.xml X
1 </TSQLCorrmand >
</EVENT_I NSTANCE >
'V
Description
• To view XML in the XML Editor, ru n a q uery that returns the XML that yo u want
to view and then click on the cell that contains the XML. When yo u do, the XML
will be displayed in the XML Editor, and the XML 1n en u will replace the Query
1nen u.
• To create an XML Sche1n a Definition for an XML docu1n ent, display the XML
docu1n ent in the XML Editor and then select the Create Sche1n a co1n 1n and fro1n the
XML 1n en u.
Figure 18-5 How to use the methods of the xml data type (part 1 of 2)
590 Section 4 Advanced SQL skills
The third example shows how to use the value method to return the value of
the specified element or attribute. To do that, you use the first argument of the
value method to specify the XQuery string for the element or attribute. Then,
you use the second argument to specify the SQL Server data type that you
want to return. In this figure, for example, the varchar data type is used to store
the data for the EventType element and for the ANSI_NULLS attribute of the
SetOptions element. Since the value method returns a single value, this method
requires its XQuery argument to specify the element or attribute number within
square brackets, even if the xml type contains only one attribute or element with
the specified name. As a result, the XQuery path must be enclosed in parentheses
whenever you use the value method.
The fourth example shows how to use the modify method to update the data
that's stored in an xml type. To start, this example declares a variable of the xml
type and uses a SELECT statement to store an XML document in this variable.
Then, it uses a SET statement to replace the value that's stored in the EventType
element of the xml variable with a string value of "TEST". To do that, it uses the
modify method with an XML DML "replace value of' statement. In addition, it
uses the text() function to retrieve the string value that's stored in the EventType
element. Finally, a SELECT statement is used to retrieve the modified value of
the xml variable. Although you don't typically use a SELECT statement like
this, you shouldn't have any trouble understanding how it works.
In addition to the "replace value of' statement, you can use the XML
DML insert and delete statements to insert nodes into and delete nodes from an
xml type. To learn more about these statements, you can begin by looking up
"modify() Method (xml data type)" in the SQL Server documentation. Then, you
can follow the links to learn more about the XML DML statements.
Although you can use the modify method to modify the data that's stored
in an xml data type, you should avoid extensive use of this method whenever
possible. Instead, you should consider storing the data in one or more tables.
Then, you can use the DML statements that are available from SQL to insert,
update, and delete the data in those tables.
Chapter 18 How to work with XML 591
SET @EventData.modify
( 'replace value of (/ EVENT_INSTANCE / EventType / text ()) [l] with "TEST"' ) ;
Description
• X Query is a language that's designed to query an XML docu1n ent.
• XML Data Manipulation Language (XML DM L) is a language that's designed to
insert, update, or delete nodes fro1n an XML docu1n ent.
Figure 18-5 How to use the methods of the xml data type (part 2 of 2)
592 Section 4 Advanced SQL skills
Description
• You can use the value method to parse an xml data type that has been stored in a
database into multiple columns.
A trigger that parses XML data and inserts it into the table
CREATE TRIGGER Database_CreateTable_DropTable2
ON DATABASE
AFTER CREATE_TABLE, DROP_TABLE
AS
DECLARE @EventData xml;
SELECT @EventData = EVENTDATA () ;
INSERT INTO DDLActivityLog2 VALUES
(
@EventData.va1ue ( ' (/ EVENT_INSTANCE / EventType ) [l] ', 'varchar ( 4 0) ' ),
@EventData.va1ue ( ' (/ EVENT_INSTANCE / PostTime ) [1] ', 'varchar ( 4 0) ' ) ,
@EventData.va1ue ( ' (/ EVENT_INSTANCE / LoginName ) [l] ', 'varchar ( 4 0) ' ),
@EventData.va1ue ( ' (/ EVENT_INSTANCE / ObjectName ) [1] ', 'varchar ( 4 0) ')
) ;
Description
• You can use the value 1n ethod to parse an x1n l data type into 1n ultiple colu1n ns
befo re yo u store it in the database.
Figure 18-7 Another example that parses the xml data type
596 Section 4 Advanced SQL skills
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="EVENT_INSTANCE">
<xs:complexType>
<xs:sequence>
<xs:element name="EventType" type="xs:string" />
<xs:element name="PostTime" type="xs:dateTime" />
<xs:element name="SPID" type="xs:unsignedByte" />
<xs:element name="ServerName" type="xs:string" />
<xs:element name="LoginName" type="xs:string" />
<xs:element name="UserName" type="xs:string" />
<xs:element name="DatabaseName" type="xs:string" />
<xs:element name="SchemaName" type="xs:string" />
<xs:element name="ObjectName" type="xs:string" />
<xs:element name="ObjectType" type="xs:string" />
<xs:element name="TSQLCommand">
<xs:complexType>
<xs:sequence>
<xs:element name="SetOptions">
<xs:complexType>
<xs:attribute name="ANSI_NULLS"
type="xs:string" use="required" />
<xs:attribute name="ANSI_NULL_DEFAULT"
type="xs:string" use="required" />
<xs:attribute name="ANSI_PADDING"
type="xs:string" use="required" />
<xs:attribute name="QUOTED_IDENTIFIER"
type="xs:string" use="required" />
<xs:attribute name="ENCRYPTED"
type="xs:string" use="required" />
</xs:complexType>
</xs:element>
<xs:element name="CommandText" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
,
I •
Description
• Before you can use an XML Schema Definition with the xml data type, you must
add the XSD to the database. To do that, you can use the CREATE XML SCHEMA
COLLECTION statement.
Description
• To provide XML validation, you can specify an XSD for the xml data type when you
use it to define a column or a variable. Then, when you attempt to store data in the xml
data type, SQL Server will use the XSD to make sure the data is valid. If the data isn't
valid, SQL Server will display an appropriate error message.
Figure 18-9 How to use an XML schema to validate the xml data type
600 Section 4 Advanced SQL skills
Description
• To view an XML sche1n a that has been added to the database, you can use the
XML_SCHEMA_NAMESPACE function .
• To get infor1nation about XML sche1n as that have been added to the database, you
can query the sys.x1nl_sche1n a_collections catalog view.
• To drop an XML sche1n a fro1n the database, you can use the DROP XML
SCHEMA COLLECTION state1n ent. You ca n't drop an XML sche1n a if it's being
used by another object.
Description
• To specify the name of the root element for the XML document, use the ROOT
keyword.
• To return one XML element for each row, use the RAW keyword.
• To automatically parse the rows of the result set so the elements reflect the structure
of the tables in the database, use the AUTO keyword.
Figure 18-11 How to use the FOR XML clause of the SELECT statement (part 1 of 2)
604 Section 4 Advanced SQL skills
As you saw in the first two examples in figure 18-11, the data for each
column that's returned by a SELECT statement that includes the FOR XML
clause is stored in attributes. However, if you want to store the data for each
column in XML elements instead, you can add the ELEMENTS keyword to the
FOR XML clause. The third example in this figure, for instance, is identical to
the second example except that it includes the ELEMENTS keyword. Although
the XML document that's returned by this example is longer than in the previous
example, it's also easier to read because it uses elements instead of attributes. In
some cases, you may prefer to use this type of XML document.
Most of the time, the skills presented in this figure are all you need to use
the FOR XML clause to create XML documents from the relational data in a
database. However, several other options are available from this clause that give
you even more control over the format of the XML document that's returned by
the SELECT statement. For more information, look up the SELECT statement in
the SQL Server documentation and then click on the "FOR Clause" link.
Chapter 18 How to work with XML 605
Description
• By default, the data that's stored in a database column is stored in an XML
attribute. To store data in XML elements instead, use the ELEMENTS keyword.
• The names that are used for elements and attributes correspond to the names of the
tables and columns that are used in the query. However, you can specify correlation
names for the tables and columns in your query to modify these names whenever
that's necessary.
Figure 18-11 How to use the FOR XML clause of the SELECT statement (part 2 of 2)
606 Section 4 Advanced SQL skills
-- SELECT the data from the table returned by the OPENXML statement
SELECT*
FROM OPENXML (@VendorinvoicesHandle, ' / Vendorinvoices / Vendor/ Invoice' )
WITH
(
VendorName varchar ( S 0) ' •• / VendorName',
InvoiceNumber varchar ( S 0) 'InvoiceNumber',
InvoiceTotal money 'InvoiceTotal'
) ;
Description
• Before you can use the OPENXML state1nent, you 1nust use the
sp_X1nl_PrepareDocu1nent procedure to read the XML docu1nent into 1ne1nory and
return a handle to this docu1nent.
• You can use the OPENXML state1nent to open an x1nl data type as a result set. In
the WITH clause, you can use two dots ( .. ) to navigate back one level in the XML
hierarchy.
• After you use the OPENXML state1nent, you should use the
sp_X1n l_Re1noveDocu1nent procedure to re1nove the XML docu1nent fro1n
1ne1nory.
Perspective
XML is a useful technology for storing and transferring data, and the
features that were introduced with SQL Server 2005 make it easy to work with
XML. Of course, SQL Server is a relational database that is primarily designed
to work with relational data. As a result, you should think twice before using
the xml data type to store XML data in a table.
Instead, whenever possible, you should parse the XML data and store
it in one or more tables. That way, you can still use SQL to easily retrieve
and update the data. However, if the data is structured in a way that makes it
difficult to store in tables, or if you won't need to retrieve or update the data
very often, you can use the skills presented in this chapter to store and work
with that data.
Terms
Extensible Markup Language (XML) XML Schema Definition (XSD)
XML document XML schema
tag untyped XML
element XML Editor
start tag method
end tag XQuery
attribute XML Data Manipulation Language
content (XMLDML)
child element typed XML
parent element XML validation
root element XPath
Chapter 18 How to work with XML 609
Exercises
1. Write a SELECT statement that returns an XML document that contains
all of the invoices in the Invoices table that have more than one line item.
This document should include one element for each of these columns:
lnvoiceNumber, lnvoiceDate, lnvoiceTotal, lnvoiceLineltemDescription, and
lnvoiceLineltemAmount. Then, save the XML document that's returned in a
file named MultipleLineltems.xml. Finally, generate an XML schema for the
file and save it in a file named MultipleLineltems.xsd.
2. Write a script that uses the XML document shown below to update the contact
information in the Vendors table.
<ContactUpdates>
<Contact VendorID= 4 > 11 11
<LastName>McCrystle</LastName>
<FirstName>Timothy</FirstName>
</Contact>
<Contact vendorID= l0 > 11 11
<LastName>Flynn</LastName>
<FirstName>Erin</FirstName>
</Contact>
</ContactUpdates>
To accomplish this, begin by storing this XML document in a variable of the
XML type. Then, you can use two UPDATE statements to update the Vendors
table.
3. Write a script that returns a result set that contains all of the data stored in the
XML document in exercise 2.
4. Write a script that (1) creates a table named Instructions, (2) inserts the
XML document shown below into the table, and (3) selects all records from
this table. The Instructions table should have two columns. The first column
should be an identity column named InstructionsID, and the second column
should be an xml column named Instructions.
<Instructions>
<Step>
<Description>This is the first step.</Description>
<SubStep>This is the first substep.<SubStep>
<SubStep>This is the second substep.<SubStep>
</Step>
<Step>
<Description>This is the second step.</Description>
</Step>
<Step>
<Description>This is the third step.</Description>
</Step>
</Instructions>
19
An introduction to BLOBs
Figure 19-1 describes the pros and cons of three approaches that you can use
for working with large binary values, which are often referred to as binary large
objects (BLOBs).
Pros and cons of using FILESTREAM storage (SQL Server 2008 and later)
Pros
- The BLOB can be larger than 2GB.
- The BLOB access is as fast as file system access.
- The BLOB is backed up with the database.
- Database security can be used to control access to the BLOB.
Description
• With SQL Server 2008 and later, you can use a feature known as FILESTREAM
storage to overcome several limitations for working with binary large objects
(BLOBs) that existed in previous versions of SQL Server.
• To be able to use FILESTREAM storage, the drive that stores the files must be in
NTFS format.
Description
• You can use the varbinary(max) data type for a column that stores binary data.
A .NET application
that uses a varbinary(max) column
Once you understand how to use SQL to work with binary data that's stored
in a varbinary(max) column, you can use a .NET application to write binary data
that's in a file to a column in a database. Then, you can use a .NET application
to present binary data in a way that's meaningful to the user. In this chapter, for
example, you '11 learn how to read binary data for an image from a column in the
database and display it in a picture box control on a Windows form.
This topic presents a simple application that uses C# to work with BLOBs.
All of the principles in this application apply to Visual Basic and the other .NET
languages. The differences mainly have to do with the syntax of each language.
If you prefer to use Visual Basic, you can download the Visual Basic code for
this application from our web site (see appendix A).
If you have some C# programming experience, you shouldn't have much
trouble understanding this code. If you don't have C# experience, that's fine
too. In that case, you can focus on how this code uses the .NET framework to
execute SQL statements against a database. Then, if you want to learn more
about writing C# applications, we recommend our current book on C#. And if
you want to learn more about using C# to work with a database, we recommend
our current book on ADO.NET with C#. For a current list of books, please see
www.murach.com.
Display images
Pacldi.loot
Upload
Note: The image file must be in the C:/Murach/ SQL SeNer 2016/lmages directory
Description
• To view an i1nage, select the ID for the i1nage fro1n the co1nbo box.
• To upload an i1nage, enter a filena1ne and a product ID for the i1nage, and click on
the Upload button.
Figure 19-3 The user interface for the Product Image Manager application
618 Section 4 Advanced SQL skills
// read image bytes from the database and display in picture box
Byte[] imageByteArray = ProductDB.Readimage(imageID);
MemoryStream ms= new MemoryStream(imageByteArray);
imagePictureBox.Image = System.Drawing.Image.FromStream(ms);
ms.Close();
}
catch (Exception ex)
{
MessageBox.Show(this, ex.Message, ''Error'');
}
}
}
catch (Exception ex)
{
MessageBox.Show(this, ex.Message, ''Error'');
}
}
Figure 19-4 The event handlers for the Product Image Manager form
620 Section 4 Advanced SQL skills
namespace MusicStoreimageManager
{
class ProductDB
{
II The directory for the images
static string imagesPath = "C:IMurachlSQL Server 20161Imagesl";
connection.Open();
command.ExecuteNonQuery();
}
catch (Exception e)
{
throw e;
}
finally
{
if (connection!= null)
connection.Close();
}
}
The Readimage method of the Prod uctDB class returns an array of bytes
for the specified image. To start, this method accepts a single parameter
named imageID that's used to specify the image to be read. Then, the body
of this method begins by getting a connection to the database. Next, it creates
a SqlCommand object that contains a SELECT statement that retrieves the
Productimage column for the specified imageID value. This SELECT statement
accepts a single parameter named @ImageID. After creating the SqlCommand
object, this method adds a parameter to that object with the value that was
passed to the method. Finally, this method opens the connection and calls the
ExecuteReader method to execute the SELECT statement that's stored in the
SqlCommand object and return a SqlDataReader object.
Once this method has returned the SqlDataReader object, it reads the
image that's stored within this object. This is easy because the SqlDataReader
object only contains a single row and a single column. In other words the
SqlDataReader object only contains the binary data for the specified image.
To start, the Read method of the SqlDataReader object is called to move the
cursor onto the first and only row in the result set. If the Read method isn't able
to move to this row, an exception is thrown and execution skips into the catch
block. Otherwise, the SqlDataReader object is used to return the first column in
the result set and to convert it to an array of bytes. Finally, this code closes the
SqlDataReader object and returns the array of bytes for the image.
Chapter 19 How to work with BLOBs 623
"FROM Productimages + 11
connection.Open();
SqlDataReader reader= command.ExecuteReader();
return imageByteArray;
}
catch (Exception e)
{
throw e;
}
finally
{
if (connection!= null)
connection.Close();
}
}
connection.Open();
SqlDataReader reader= command.ExecuteReader();
return imageIDList;
}
catch (Exception e)
{
throw e;
}
finally
{
if (connection!= null)
connection.Close();
}
}
OK ![ Cancel
I
I Apply7 L Help '
7. Use the Configuration Manager to stop and then restart the SQL Server service.
8. Close and reopen the Manage1nent Studio.
Description
• By default, FILESTREAM storage is disabled for the server.
Description
• If you want to use the FILESTREAM feature, you must create a database that
includes a file group that provides for FILESTREAM storage.
Description
• To create a table that provides for FILESTREAM storage, you include a colu1nn
definition that contains the FILESTREAM keyword. In addition, you create a
colu1nn with a globally unique identifier (GUID ) that's used to locate the file that
stores the FILESTREAM data.
• A GUID is a value that's unique within the current database and other networked
versions of the database around the globe. To define a colu1nn that contains a
GUID, you specify the uniqueidentifier data type for the colu1nn, and you specify
the ROWGUIDCOL property for the colu1nn.
• You can use the NEWID function to generate a globally unique value.
• You can use the PathNa1ne function to return the path to the binary file strea1n. This
function is case sensitive, so you 1nust use exact capitalization.
won't return a path to the file stream, and the application won't be able to write
data to the file stream.
namespace MusicStoreimageManager
{
class ProductDB
{
II define the directory for the images
static string imagesPath = "C:IMurachlSQL Server 20161Imagesl";
''VALUES (@ProductID, +
11
connection.Open();
command.ExecuteNonQuery();
After executing the query that inserts the row into the database, you must
get a reference to the file stream for the BLOB. To do that, you begin by
defining a SELECT statement that returns two columns. The first column uses
the PathName function to return the path to the file stream. The second column
uses the GET_FILESTREAM_TRANSACTION_CONTEXT function to get the
context for the transaction. Note that the GUID value that was created earlier in
this method is used in the WHERE clause of this SELECT statement to specify
the row that was inserted by the INSERT statement earlier in the same method.
After the SELECT statement is defined, this code executes this statement.
Then, it uses the reader object that's returned to check whether the result set
contains data. If so, the first column is stored in a variable named path, and the
second column is stored in a variable named context. Finally, this code closes the
reader object.
At this point, the Writeimage method has all the data it needs to set up an
output stream to the database. To do that, it creates a FileStream object with
write access.
Now that the Writeimage method has an input stream and an output stream,
it's ready to read data from the input stream (the image file) and write data to
the output stream (the BLOB in the database). To do that, this code defines a
block size of half a megabyte (524,288 bytes), a size that's usually efficient for
working with streams. Then, this code defines a buffer variable that stores this
array of bytes. Finally, it uses a loop to read from the input stream and write to
the output stream.
Note that this allows this class to read half of a megabyte into memory at a
time. For example, let's assume that you have an image file that's 4 megabytes.
In that case, it would take eight trips through the loop to write the file to the
database. On the other hand, the Writeimage method presented earlier in this
chapter reads the entire file into memory before it begins to write the file. As a
result, it can use a lot of memory if you use it with images that are larger than 1
megabyte.
Note also that this method uses a transaction. If the method completes
successfully, the last statement in the try block commits the transaction, and the
image is written to the database. However, if the method encounters an error,
the catch block rolls back the transaction, and the image is not written to the
database.
Chapter 19 How to work with BLOBs 635
targetStream.Close();
sourceStream.Close();
transaction.Commit();
}
catch (Exception e) {
if (transaction!= null)
transaction.Rollback();
throw e;
}
finally {
if (connection!= null)
connection.Close();
}
}
The Readlmage method works much like the Readlmage method presented
earlier in this chapter. However, since this method uses FILESTREAM storage,
it's more complex. To start, this method executes a SELECT statement to get a
path to the file stream and the transaction context. Then, it sets up a file stream
for the BLOB by creating a FileStream object with read access. Since this works
much like the SELECT statement of the Writelmage method that's presented
in part 2 of this figure, you shouldn't have much trouble understanding how it
works.
After setting up the input file stream, this code uses a loop to read the binary
data from the database and stores this data in a List<byte> object named
imageBytes. Then, it converts the List<byte> object to an array of byte values
and returns it.
This loop works similarly to the loop in the Writelmage method that reads
from one stream and writes to another. However, instead of writing to a stream,
this code stores the entire stream in the List<byte> object. The advantage to this
approach is that it allows you to separate the data access layer (the ProductDB
class) from the presentation layer (the form). The disadvantage of this approach
is that the entire image is stored in memory. If this isn't satisfactory for your
application, you can add a PictureBox control as a second argument of the
Readlmage method. Then, this method can stream the data from the BLOB in
the database to the PictureBox control that displays the image.
For this ProductDB class to work with the Product Image Manager
application presented earlier in this chapter, it must include a GetlmageIDList
method. However, the code for this method is the same as the code presented in
part 3 of figure 19-5. To save space, it isn't presented here.
Chapter 19 How to work with BLOBs 637
SqlFileStream sourceStream -
new SqlFileStream(path, context, FileAccess.Read);
Perspective
In this chapter, you learned how to write BLOBs to a database table and
to read BLOBs from a database table. In addition, you learned how to use the
FILESTREAM storage feature that was introduced with SQL Server 2008. At
this point, you have the core concepts and skills for working with BLOBs.
Now, if you want to develop a more sophisticated application for working
with BLOBs, you should be able to do that. For example, you may want to
enhance the application presented in this chapter so it can be used to update
or delete an existing image. Or, you may want to enhance this application so it
works more efficiently.
Terms
binary large object (BLOB)
FILESTREAM storage
globally unique identifier (GUID)
Exercises
1. Modify the first ProductDB class presented in this chapter so the Readimage
method accepts a PictureBox control as a second argument like this:
public static void Readimage(int imageID, PictureBox pictureBox)
Then, modify the Readimage method so it streams data from the database to
the PictureBox control, and modify the code for the form so it works with this
new method. To do this, you can begin by copying code from the form into
the ProductDB class.
2. Modify the second ProductDB class so it works as described in exercise 1.
20
An introduction
to CLR integration
SQL Server 2005 introduced the ability to host the .NET Framework's
Common Language Runtime (CLR). This allows .NET developers to use C#
or Visual Basic to create database objects such as stored procedures, functions,
and triggers. In addition, it allows developers to create new types of database
objects that aren't available from T-SQL such as aggregate functions and
user-defined data types that have properties and methods.
This chapter shows how CLR integration works, when you might want to
use it, and how to enable it. Then, it shows how to work with the SQL DDL
statements that you can use to deploy a CLR object.
However, this chapter doesn't show how to use the Visual Studio IDE
to code, compile, deploy, and debug a CLR object. That's because this type
of work is typically done by a .NET developer who has experience using
the Visual Studio IDE with C# or Visual Basic to work with ADO.NET. In
addition, it requires a non-Express version of Visual Studio that's not available
for free. To learn how to develop CLR objects, you can refer to a previous
edition of this book such as Murach 's SQL Server 2012.
Functions Functions
Triggers Triggers
Aggregate functions
User-defined types
Description
• The Common Language Runtime (CLR) for the .NET Fra1nework executes
co1npiled code that's written in the C#.NET or Visual Basic.NET progra1n1ning
language.
• Co1n piled .NET code is stored in files known as assemblies. Since the CLR
auto1natically 1nanages the 1ne1nory usage and security for the code that it runs,
co1npiled .NET code is known as managed code.
• SQL Server 2005 and later can be configured to host the CLR. This is known as
CLR integration, and it lets you run .NET asse1nblies within a SQL Server instance.
• CLR integration lets you use C# or Visual Basic to create database objects such as
stored procedures, functions, triggers, aggregate functions, and user-defined types.
Description
• CLR integration lets you use C# or Visual Basic to create stored procedures,
functions, and triggers instead of using T-SQL to create these database objects as
described in chapter 15.
• A user-defined aggregate (UDA) is an aggregate function that works si1nilarly to
built-in aggregate functions such as the SUM function described in chapter 5.
• A user-defined type (VDT) is a data type that can include data validation,
properties, and 1nethods.
• If necessary, CLR objects can use the ADO.NET class libraries to retrieve and
1nodify the data that's in the database.
• Most database objects will perfor1n better when they are written in T-SQL instead
of C# or Visual Basic.
Figure 20-2 The five types of CLR objects and when to use them
644 Section 4 Advanced SQL skills
Description: Surface area configuration for features of the Database Engine. Only the
features required by your application should be enabled. Disabling unused
Facet properties::
AdHocRemoteQueriesEnabled False
ClrlntegrationEnabled True V
Description
• To enable CLR integration, start the Manage1nent Studio, right-click on the server
node, and select the Facets co1n1nand to display the View Facets dialog box. Then,
select the Surface Area Configuration option fro1n the Facet drop-down list, and set
the ClrlntegrationEnabled property to True.
Description
• To deploy a CLR object, you start by deploying the assembly that contains the
compiled code for the object using the CREATE ASSEMBLY statement.
• After you deploy the assembly, you can create the object in the database. To create
a stored procedure, for example, you use the CREATE PROCEDURE statement.
• You can use the DROP ASSEMBLY statement to drop an assembly from the
database. But first, you must drop all the CLR objects it contains. You can also use
the ASSEMBLYPROPERTY function to check that an assembly exists before you
drop it.
Figure 20-4 How to use SOL to deploy and drop CLR objects
648 Section 4 Advanced SQL skills
Perspective
This chapter introduces CLR objects. In addition, this chapter shows how
to enable CLR integration on a database server and how to use SQL DDL to
deploy CLR objects. However, since CLR objects are typically developed by
.NET developers, this chapter doesn't present the details that you need to be
able to develop these types of objects. If you want to learn how to do that, we
recommend using a previous edition of this book, such as Murach 's SQL Server
2012.
Terms
Common Language Runtime (CLR)
assembly
managed code
CLR integration
user-defined aggregate (UDA)
user-defined type (UDT)
Exercises
1. Use the Management Studio to enable CLR integration for your instance of
SQL Server.
2. Write a script that deploys the ApExClrObjects assembly to the AP database.
You can find the dll file for this assembly in this directory:
C:\Murach\SQL Server 2016\Exercises\Chapter 20
Description
• For this book, we reco1n1nend that yo u install the Express edition of SQL Server
20 16, but yo u can install the Express with Advanced Services edition if yo u want to
install the advanced features and don ' t 1nind a larger download and install.
Notes
• This book assumes that an instance of SQL Server 2016 Express is installed with a
name of SQLEXPRESS. If it's installed on your system with a different name, you
may have to modify some of the examples to get them to run successfully on your
computer.
• SQL Server 2016 supports Windows 8 and later. Support for Windows 7 has been
dropped.
The Databases directory contains the SQL scripts used to create the three
databases that are used throughout the book. To do that, you can use the
Management Studio to open and execute these scripts as described in the next
figure.
The Scripts directory contains the SQL code that's described throughout
this book. You can use the Management Studio to open these scripts. Then, you
can run them to view the results. Or, you can experiment with these scripts by
modifying them before you run them.
The Exercises directory contains the solutions to the exercises that are
presented at the end of each chapter. You can use these solutions to check that
the solutions you develop are correct. You can also use these solutions to find out
how to solve an exercise if you 're unable to do it on your own. Keep in mind,
though, that you '11 get more out of the exercises if you try to solve them on your
own first.
The Projects directory contains two subdirectories that contain the Visual
Studio projects for chapters 1 and 19. These projects are available in two
versions: a C# version and a Visual Basic version. You can use the Windows
Desktop edition of Visual Studio Express to open these projects.
Appendix A How to set up your computer for this book 655
Description
• All of the files for the databases and code described in this book are contained in a
self-extracting zip file (an exe file) that can be downloaded fro1n www.1nurach.co1n.
The directory that contains the scripts for creating the databases
C: \ Murach\ SQL Server 2016 \ Databases
~ create_aps 1- localhost\ SQLEXPRESS.master (RAV-PC\R (53)) - Microsoft SQL Server Management Studio □ X
File Edit Vi Query Proj ect Debug Tools W, dow Help
100 % • )
Eb
-
Meuage$
,.,
( 1 r ow(s) a ffe c t e d )
( 1 row( s) affecte d )
( 1 r ow(s ) affected )
100% •
Description
• For these scripts to work, the database server 1nust be running. By default, the
database server is auto1natically started when yo u start yo ur syste1n. If it isn ' t
running on yo ur syste1n, yo u can start it as described in chapter 2.
Figure A-4 How to create and restore the databases for this book
658 Appendix A How to set up your computer for this book
Description
• You only need to install Visual Studio for chapter 19 of this book. If you don't
already have Visual Studio installed on your system, you can install Visual Studio
Express for Windows Desktop, which is available for free from Microsoft.
ADO.NET, 38-43
Index with C# code, 44, 45
with Visual Basic code, 42, 43
AFTER trigger, 486-489
Aggregate function, 160-163
-- characters (con1111ent), 32, 33 Aggregate
- operator (subtraction), 97 in view, 396, 397
- wildcard character, 112, 113 query, 160-163
# character (local ten1porary nan1e), 418,419,454, 455 AIX operating systen1, 21
## characters (global ten1porary nan1e), 418, 419, 454,
Alias
455 colun1n, 92, 93
% operator, 97 colun1n and ORDER BY, 118, 119
% wildcard character, 112, 113 table, 128, 129
* operator All colun1ns operator, 90, 91
all colun1ns, 90, 91 ALL keyword, 90, 91
111ultiplication, 97 and subquery, 192, 193
*= operator, 140, 141 in aggregate function, 160-163
.bak file, 60, 61 in SELECT clause, 100, 101
.NET data provider, 40, 41 with union, 150, 151
/ operator, 97 ALL SERVER keyword, 494, 495
/* ... *I characters (block con1111ent), 32, 33 ALTER COLUMN clause, 354, 355
:: scope qualifier, 544, 545 ALTER FUNCTION staten1ent, 335,484, 485
@ character ALTER LOGIN staten1ent, 534, 535
paran1eter nan1e, 456, 457 ALTER PROC staten1ent, 335, 472, 473
variable nan1e, 414, 415 ALTER ROLE staten1ent, 556-589
@@ERROR systen1 function, 434,435 ALTER SCHEMA staten1ent, 538, 539
@@FETCH_STATUS systen1 function, 428,429 ALTER SEQUENCE, 358, 359
@@IDENTITY systen1 function, 434,435 ALTER SERVER ROLE staten1ent, 550-553
@@ROWCOUNT systen1 function, 434,435,504,505 ALTER TABLE staten1ent, 25, 335, 352-355
@@SERVERNAME systen1 function, 434,435 ALTER TRIGGER staten1ent, 335, 496, 497
@@TRANCOUNT systen1 function, 506, 507 ALTER USER staten1ent, 536, 537
[ ] characters ALTER VIEW staten1ent, 335, 398, 399
delinuter, 336, 337 Always Encrypted feature, 576
in col u 11111 nan1e, 92, 93 AI11biguous colun1n nan1e, 126, 127
wildcard, 112, 113 An1erican National Standards Institute (ANSI), 18, 19
"wildcard character, 112, 113 An1erican Standard Code for Inforn1ation Interchange
wildcard character, 112, 113 (ASCII), 244
+ operator Analytic functions, 296-299
addition, 97 Anchor 111en1ber (recursive CTE), 210, 211
concatenation, 94, 95 AND operator, 106, 107
< operator, 104, 105 ANSI, 18, 19
< operator, 104, 105 ANSI/ISO SQL, 18, 19
<> operator, 104, 105, 436, 437 ANSI_NULLS systen1 option, 436, 437
= operator ANSI_PADDING systen1 option, 437
assign colun1n alias, 92, 93 ANSI-standard data type, 240, 241
assign variable value, 415 ANSI-standard SQL, 18, 19
con1parison, 104, 105, 114, 115,436,437 ANY keyword, 194, 195
renan1e colun1n, 92, 93 AP database (script), 360-363
=* operator, 140, 141 API, 6, 7
> operator, 104, 105 Application
> operator, 104, 105 server, 8, 9
INF, 2NF, 3NF, 4NF, 5NF, 6NF, 320,321 web, 8, 9
Application progran1, 38-45
Application progran1111ing interface (API), 6, 7
A
-
ABS function, 268, 269
Application role, 564, 565
Application software, 6, 7
Action query, 30, 31 Approxin1ate nun1eric data type, 242, 243
Ad hoc relationship, 126, 127 Argun1ent, 98, 99
Addition operator, 97 Arithn1etic expression, 96, 97
Arithn1etic operator, 96, 97
662 AS keyword Codd, E.F.
AS keyword C
in CAST function, 252, 253
in FROM clause, 128, 129 -
C# code (with ADO.NET), 44, 45
in SELECT clause, 90-93 CACHE keyword, 356, 357
ASC keyword (ORDER BY), 116, 117 Calculated colun1n, 26, 27, 90, 91-93
ASCII, 244 assigning nan1e, 92, 93
control character, 258, 259 in view, 394-397
function, 258, 259 Call a function, 476, 477
Assen1bly, 640, 641, 646, 647 Call a procedure, 452, 453, 458, 459
ASSEMBLYPROPERTY function, 646, 647 Cartesian product, 148, 149
Associate table, 312, 313 CASCADE clause
Attach database, 58, 59, 338, 339 DENY, 562, 563
Attribute REVOKE, 540,541
SQL, 10, 11,304,305,340,341 CASCADE keyword, 350, 351
XML, 580,581 Cascading deletes and updates, 350, 351, 372, 373, 491
Authentication CASE function, 284, 285
login, 54, 55 Case sensitivity, 104, 105
111ode, 530, 531 CASE software tool, 310,311
AUTHORIZATION clause, 538, 539 Cast as data type, 252, 253
AUTO keyword (FOR XML clause), 602-605 CAST function, 252, 253, 266,267, 278, 279
Autocon1111it 111ode, 504, 505 Catalog (systen1), 404, 405
AVG function, 160-163 Catalog views, 404, 405
database roles, 560, 561
server roles, 554, 555
B XML schen1a inforn1ation, 600, 601
Back end, 6, 7 CATCH block, 430, 431, 462, 463
Back up database, 60, 61 CEILING function, 268, 269
Base table, 26, 27, 388, 389 Cell, 10, 11
Base view, 404, 405 Change script (saving), 382, 383
Batch, 360,361,410,411 char data type, 241, 244, 243
stored procedure, 454, 455 CHAR function, 258, 259
BCNF, 320,321 char varying data type, 241
bcp, 519,520 character data type, 241
BEGIN keyword, 413 character varying data type, 241
BEGIN TRAN staten1ent, 504, 505 CHARINDEX function, 262-267
BEGIN ... END block, 422, 423, 478, 479 check constraint, 346-349, 376, 377
BEGIN ... END staten1ent, 412,413,432,433 CHECK_EXPIRATION option, 532, 533
BETWEEN phrase, 110, 111 CHECK_POLICY option, 532, 533
bigint data type, 242, 243 Child elen1ent (XML), 580,581
Binary data, 612-637 CHOOSE function, 286, 287
Binary file pointer, 612, 613 Client tools, 50, 51
Binary large objects (BLOBs), 612-637 Client, 4, 5
binary varying data type, 241 software, 6, 7
bit data type, 242, 243 Client/server systen1, 4, 5
BLOBs, 612-637 architectures, 7, 8, 9
Block con1111ent, 32, 33 con1pared to file-handling systen1, 6, 7
Book files (downloading), 652, 653 CLR (defined), 640, 641
Books Online, see SQL Server documentation CLR integration, 640-661
Boolean expression, 86, 87 CLR object
Boyce-Codd norn1al forn1, 320, 321 deploy, 646, 647
BREAK staten1ent, 413,426,427 drop, 646, 647
Browser (web), 8, 9 SQL staten1ents for, 646, 647
Bulk copy progran1 (bcp), 519,520 types of, 642, 643
BULK INSERT staten1ent, 519, 520 when to use, 642, 643
Bulk Update (BU) lock, 519,520 CLR stored procedure, 646, 647
Business con1ponent, 8, 9 Clustered index, 318,319,374,375
CLUSTERED keyword, 342, 343
COALESCE function, 288, 289
Coarse-grain lock, 516,517
Codd,E.F., 10, 18, 19
Coding guidelines Data definition language (DDL) 663
Order of precedence
0 data types, 250, 251
Object operators, 96, 97
dependencies, 378, 379 Orphan, 314,315
identification nun1ber, 424, 425 OS/390 operating systen1 20, 21
identifier, 336, 337 OSQL utility, 444,445,
nan1e, 130, 131, 336, 337 Outer join, 28, 29, 140-145
pernussions, 528, 542-543, 562, 563 con1bined with inner join, 146, 147
Object database, 16, 56, 57,334,338,339 exan1ples, 142, 143
Object Explorer (Managen1ent Studio), 56, 57 explicit syntax, 140, 141
OBJECT_ID function, 424,425 111ore than two tables, 144, 145
OFFSET clause, 120, 121 Output paran1eter, 36, 456-459
ON clause OVER clause, 178, 179
MERGE staten1ent, 234, 235
trigger, 486, 487 p
ON DELETE clause, 350, 351
ON phrase, 126, 127 Package (SQL-99 standard), 18, 19
ON PRIMARY clause, 338, 339 Pagelock,516,517
ON UPDATE clause, 350, 351 Paran1eter, 98, 99,450,451, 454-459, 476
One-to-111any relationship, 12, 13,312,313 pass a table, 470, 471
One-to-one relationship, 12, 13,312,313 pass a value, 458, 459
On-line help, see SQL Server documentation stored procedure, 36
Open-source database, 20, 21 Parent elen1ent (XML), 580,581
OPENXML staten1ent, 606, 607 Parent/child relationship, 16, 17
Operating systen1 Parentheses, 96, 97, 106, 107
AIX, 21 Parsing, 266, 267
Linux, 20, 21 Partially-qualified object nan1e, 130, 131
Unix, 20, 21 PARTITION BY clause
Windows, 20, 21 aggregate function, 178, 179
z/OS, 21 analytic function, 296, 297
Operator ranking function, 292, 293
addition, 97 Pass a paran1eter, 458, 459
AND, 106, 107 Password (strong), 532, 533
arithn1etic, 96, 97 PathNan1e function, 630, 631
con1parison, 104, 105 PATINDEX function, 262-265
concatenation, 94, 95 Pattern (string), 112, 113
division, 97 PERCENT keyword, 102, 103
equal, 104, 105 PERCENT_RANK function, 296-299
greater than, 104, 105 PERCENTILE_CONT function, 296-299
greater than or equal to, 104, 105 PERCENTILE_DISC function, 296-299
less than, 104, 105 Pernussion (defined), 528, 529
less than or equal to, 104, 105 Pernussions, 540-549
logical, 106, 107 database, 546,547,574,575
111odulo, 97 object, 542-543
111ultiplication, 97 schen1a, 544, 545
NOT, 104-115 server, 548, 549
not equal, 104, 105 Phanton1 read, 512-515
OR, 106, 107 Position (passing paran1eters by), 458, 459
order of precedence, 96, 97, 106, 107 PostgreSQL database systen1, 20
string, 94, 95 PowerShell (Windows), 444
subtraction, 97 Precedence, 96, 97
UNION, 150,151,396,397 Precision, 242, 243
Operator, see also Keywords Precon1pile, 452, 453
Optional paran1eter, 456-459 Predicate, 86, 87
OR operator, 106, 107 subquery, 184, 185
Oracle, 18-21 Prin1ary key, 10, 11,374,375
ORDER BY clause, 86, 87, 102, 103, 116-121 and referential integrity, 314, 315
by string colun1n, 266, 267 con1posite, 10, 11
in view, 392-395 constraint, 340, 341, 346, 347
of a ranking function, 292-295 how to identify, 312, 313
PRINT statement Role information 671
Roll back a transaction, 502, 503 Second norn1al forn1, 320, 321, 324, 325
ROLLBACK TRAN staten1ent, 504-509 Securables, 528, 529
in trigger, 488, 489 Security, 528-575
ROLLUP operator, 172, 173 Transact-SQL con1pared to Managen1ent Studio, 528,
Root elen1ent (XML), 580,581 529
ROOT keyword (FOR XML clause), 602-605 using view, 390, 391
ROUND function, 268, 269 securityadnun role, 550, 551
Row, 10, 11 SELECT staten1ent, 26, 27, 86-119
Row count, 434, 435 and subquery, 202, 203
Row, lock, 516,517 clause, 86-101
Row versioning, 514,515 in view, 392, 393
ROW _NUMBER function, 292, 293 INTO,216,217,440,441
ROWCOUNT systen1 option, 436, 437 variable assignn1ent, 414,415
ROWGUIDCOL property, 630, 631 Self-join, 134, 135
ROWS clause, 296, 297 SEQUEL, 18, 19
rowversion data type, 241 Sequence, 356-359
RTRIM function, 262-265 SERIALIZABLE keyword, 514,515
Server, 4, 5
application, 8, 9
s
-
Save a change script, 382, 383
connect, 54, 55
database, 50, 51
linked, 130, 131
Save point, 504, 505, 508, 509
login, 54, 55
SAVE TRAN staten1ent, 504, 505
pernussions, 548, 549
Scalar aggregate, 164, 165
software, 6, 7
Scalar function, 160 web, 8, 9
Scalar variable, 414,415 Server authentication, 54, 55
Scalar-valued function (user-defined), 476-479
Server nan1e, 130, 131
Scale, 242, 243 Server pernussion, 528
Scan (table), 318
Server pernlissions (DENY), 562, 563
Schen1a, 392, 393 Server role, 568, 569
default, 56 fixed, 550, 551
lock, 518,519 inforn1ation, 554, 555
nan1e, 130, 131
user-defined, 552, 553
pernussion, 528, 544, 545 Service (web), 8, 9
view, 404, 405 Service Manager, 50, 51
working with, 538, 539
Services (SQL Server), 52, 53
Schen1a (XML), 582, 583
Session setting, 436, 437
Schen1a Modification (Sch-M) lock, 518,519 Set (result), 26, 27
Schen1a pernussions (DENY), 562, 563
SET clause, and UPDATE, 224, 225
Schen1a Stability (Sch-S) lock, 518, 519 SET staten1ent, 413-415
SCHEMABINDING keyword, ANSI_NULLS, 436,437
UDF,478,479
ANSI_PADDING, 437
view, 392-395, 398, 399 DATEFORMAT, 436, 437
Scientific notation, 242 NOCOUNT, 437
Scope qualifier, 544, 545
ROWCOUNT, 436, 437
Scope TRANSACTION ISOLATION LEVEL, 514,515
table objects, 420,421 Shared (S) lock, 518, 519
variable, 414
Shared locks, 518, 519
Script, 360-363, 410-439, 450,451 Shared with Intent Exclusive (SIX) lock, 519, 520
change,382,383
Significant digit, 242, 243
generating, 380-383
Sin1ple table-valued function, 476,477,480, 481
Script to create the AP database, 360-363 Single precision nun1ber, 242, 243
Search
Single quotes
by date value, 280, 281
for string literal, 94, 95
by tin1e value, 282, 283
in colun1n nan1e, 92, 93
for null, 114, 115
within string literal, 94, 95
for real nun1eric value, 270, 271
Single-line con1111ent, 32, 33
Search condition, 86, 87 Sixth norn1al forn1, 320, 321
con1pound, 106, 107, 170, 171
sn1alldatetin1e data type, 246, 247
subquery, 188-199 sn1allint data type, 242, 243
smallmoney data type Statements 673
-
WAITFOR DELAY staten1ent, 522, 523
XML Schen1a Definition (XSD), 582, 583
XML schen1a, 5 82, 5 83, 596-601
XML_SCHEMA_NAMESPACE function, 600, 601
WAN, 4, 5
XPath, 606, 607
Web application, 8, 9 XQuery, 588-591
Web browser, 8, 9 XSD, 582, 583
Web services, 8, 9
Web-based systen1s, 8, 9
WHEN clause (MERGE staten1ent), 234, 235 YZ
WHERE clause, 86 - 88, 104-115
and DELETE, 230, 231 YEAR function, 272, 273, 276, 277
and su bquery, 188-199 z/OS operating systen1 20, 21
and UPDATE, 224, 225
con1pared to HAVING clause, 168, 169
100°/o Guarantee
When you order directly from us, you must be satisfied. Our books must work better than
any other programming books you've ever used... both for training and reference...or you can send
them back within 60 days for a prompt refund. No questions asked !
(\M¼__ ~~
Mike Murach, Publisher Ben Murach,President
1-800-221-5528 facebook.com/murachbooks
(Weekdays, 8 am to 4 pm Pacific Time)
~ ,iii murachbooks@murach.com
linkedin.com/com pany/
mike-murach-&-associates
The software for this book
• SQL Server 2016 Express (a free download)
• SQL Server Management Studio (a free download)
• Visual Studio Express (a free download)
SQL Server 2016 only runs on Windows 8 and later. As a result, if you're using
Windows 7 or earlier, you '11 need to upgrade your operating system before you can
install SQL Server 2016 Express.
For information about downloading and installing these products, please see
appendix A.
www.murach.com