0% found this document useful (0 votes)
7 views40 pages

CH 05

Uploaded by

vuthnarak2005
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views40 pages

CH 05

Uploaded by

vuthnarak2005
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 40

Modifying Data

Modifying Data
Objectives
• Learn to use Transact-SQL INSERT, UPDATE, and DELETE
statements.
• Learn to use bulk copy to insert rows.
• Understand how transaction isolation levels affect performance and
concurrency.
• Learn to avoid locking and blocking problems.
• Use snapshot isolation to improve concurrency.

The files associated with this chapter are located in the following folders:
{Install Folder}\Modifying
{Install Folder}\ModifyingDataLab

Microsoft SQL Server 2005 5-1


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Modifying Data

Modifying Data
The SQL standard draws a distinction between Data Manipulation Language
(DML) and Data Definition Language (DDL). SELECT statements are
considered to be part of DML, even though you might not think of selecting
data as a form of “manipulation.”

When you retrieve data with a SELECT statement, a result set is returned.
However, any further actions you take on that data (besides just looking at it)
involve data manipulation queries that use one of the following three
statements: INSERT, UPDATE, or DELETE. SQL queries that use these
statements are also sometimes known as action queries.

SQL Server was designed to handle data modification extremely efficiently


using Transact-SQL DML statements. Other techniques are often used to
modify data, such as server-side or client-side cursors (also referred to as
recordsets). The problem with using cursors to modify data is that they
sometimes place locks on the data that last longer than the locks necessary to
execute a DML statement.

NOTE ADO.NET, Microsoft’s latest programming interface for data


access, uses no cursors for updating. It performs all updates by
executing DML statements.

You’ll learn how to improve performance and avoid the locking and blocking
issues that can occur during updates later in this chapter. The first sections in
the chapter are devoted to learning how to use Transact-SQL to modify data.

5-2 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Inserting Data

Inserting Data
The INSERT statement adds new rows to a table, either single rows or
multiple rows. The basic syntax of an INSERT statement is:

INSERT [INTO] table_or_view [(col1, col2 ...)]


VALUES(value1, value2 ...)

The Categories table in the Northwind database contains four columns, as


shown in Figure 1: CategoryID, CategoryName, Description, and Picture. The
CategoryID column is an identity column and the primary key. When inserting
data, SQL Server fills in the identity value automatically when it adds a new
row. The CategoryName column is defined as not null, which means that you
must supply a value when adding data. The Description and Picture columns
allow nulls, which means that supplying a value is optional.

Figure 1. The Categories table contains four columns.

Inserting a Single Value

See The simplest INSERT statement adds a single row to a particular table. Use the
ModifyingData.sql following query to add a new category called ‘Vitamins’ to the Categories
table:

INSERT INTO dbo.Categories (CategoryName)


VALUES('Vitamins');

With only one value to add to the Categories table, the syntax of the INSERT
statement reads: INSERT INTO followed by the name of the table the row
should be added to, and then, in parentheses, the list of columns that the data
goes into. For this statement, only one column, CategoryName, receives new
data.

Microsoft SQL Server 2005 5-3


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Modifying Data

After the column list comes the keyword VALUES, which indicates that the
next set of values in parentheses contains the data for the row. Each value must
be of the same data type as the column it goes into, and the columns and values
must be in the same order. Since CategoryName is a nvarchar data type, the
‘Vitamins’ value must be delimited by single quotes, indicating that it is a
string value compatible with the nvarchar data type.

TIP: When working with Unicode data types, such as nvarchar and ntext, it is
safest to preface all literal strings with an uppercase N. This indicates that the
string contains Unicode characters. Without the N prefix, the string is
converted to the default code page of the database, which may not be able to
handle certain characters. Here’s how the INSERT statement above would
look, using this syntax:

INSERT INTO dbo.Categories (CategoryName)


VALUES(N'Vitamins');

The INTO keyword is optional, although INTO is part of the SQL92 standard,
and helps make the SQL statement clearer. The columns list is also optional; if
you leave off the list, you must specify every column in the VALUES list, in
the order that the columns are stored in the table. The following query would
insert the values 1 and Topeka in a table with two columns of int and varchar
data types:

INSERT MyTable VALUES (1, 'Topeka');

WARNING! In SQL Server, the INTO keyword is optional in an INSERT


statement. However, in other databases engines, such as Oracle, the
INTO keyword is required. So it is best to get in the habit of using it.

Also, it is best to use a column list every time you create an INSERT
statement, even if you don’t need one. Explicit code is always easier
to understand, and a column list also protects you against errors that
could occur later if a new column is added to the table.

5-4 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Inserting Data

Rows Affected
When an INSERT statement executes, no result set is returned. As with all
action queries, the only result you get back from SQL Server is a message like:

(1 rows(s) affected)

The message lets you know how many rows were changed by your action
query. This information is also returned to client applications. You can
suppress the return of rows affected by setting NOCOUNT ON:

SET NOCOUNT ON;


INSERT INTO dbo.Categories (CategoryName)
VALUES('Vitamins');

WARNING! Many T-SQL code examples include the SET NOCOUNT ON


command to suppress the extra message. However, use this carefully
if your code will be called from an ADO.NET DataAdapter object.
Suppressing the rows affected message can cause concurrency
exceptions to be raised based on the assumption that the absence of a
message indicates that no rows were updated.

Retrieving Identity Values


There are three ways to retrieve new identity column values. Table 1 describes
the features of each method.

@@IDENTITY SCOPE_IDENTITY IDENT_CURRENT

Returns the last identity Returns the last identity Returns the last identity
value generated in any table value only within the value generated for a
in the current session. current execution scope. specific table in any session
and any scope.
Table 1. The three statements that return identity column values.

@@IDENTITY and IDENT_CURRENT may not return the value you expect
for a single-table insert. They are affected by triggers and other inserts. Use
SCOPE_IDENTITY when you want to retrieve the identity column value for
the table you are performing the insert on. Here is the syntax for the three
methods:

Microsoft SQL Server 2005 5-5


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Modifying Data

SELECT @@IDENTITY AS NewCategoryID


SELECT SCOPE_IDENTITY() AS NewCategoryID
SELECT IDENT_CURRENT('dbo.Categories') AS NewCategoryID

Inserting Multiple Values


The Products table, shown in Figure 2, contains multiple columns of varying
data types. The ProductID column is also an identity column.

Figure 2. The Products table contains many columns.

In the following INSERT statement, multiple columns are listed in the


columns list. Each corresponding value is listed in the VALUES list. Note the
matching of data types; string data is delimited with single quotes, while
numeric and bit values are not.

INSERT INTO dbo.Products


(ProductName, CategoryID, UnitPrice,
QuantityPerUnit, Discontinued)
VALUES
('Pure ''Sunshine'' Orange Juice', 1, 9.99,
6, 0)

5-6 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Inserting Data

Dealing with Delimiters


The ProductName column data demonstrates how to deal with single quotes in
an INSERT statement—use two single quotes together. The description of the
item reads:

Pure 'Sunshine' Orange Juice

Single quotes within the data would confuse SQL Server, since it uses single
quotes to identify where strings begin and end. When you place two single
quotes together, SQL Server recognizes that the quote is actually within the
string. The following example shows two single quotes, not a double quote,
around ‘Sunshine’:

'Pure ''Sunshine'' Orange Juice'

Single quotes also delimit data values in queries.

TIP: Date values also require single quote delimiters. If you use parameterized
queries to perform data modification from .NET code, then you don’t need to
worry about single quotes in your strings. This is only a concern when you
are executing SQL statements with embedded string values.

Inserting Multiple Rows


To add multiple rows, you can use multiple INSERT statements, or you can
replace the value list with a SELECT statement. This example requires
creating a new table named Beverages, which will contain all of the products
in the beverages category. Note that the ProductID in Beverages is not defined
as an identity column. In a real application, you generally do not need to create
a table containing a subset of the rows that appear in another table⎯you can
use a SELECT query instead to get those rows when you need them⎯but this
example illustrates how inserts can be based on selects.

Microsoft SQL Server 2005 5-7


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Modifying Data

CREATE TABLE dbo.Beverages (


ProductID int NOT NULL PRIMARY KEY CLUSTERED,
ProductName nvarchar (40) NOT NULL ,
CategoryID int NULL ,
UnitPrice money NULL ,
QuantityPerUnit nvarchar (20) NULL ,
Discontinued bit NOT NULL DEFAULT (0))

The following query inserts all of the rows in the Products table with a
CategoryID of 1 into the Beverages table.

INSERT INTO dbo.Beverages(


ProductID, ProductName, CategoryID,
UnitPrice, QuantityPerUnit, Discontinued)
SELECT
ProductID, ProductName, CategoryID,
UnitPrice, QuantityPerUnit, Discontinued
FROM dbo.Products
WHERE CategoryID = 1;

Notice that the SELECT statement portion of this query is completely


conventional. If you execute that portion of the query by itself, it returns a
result set, as shown in Figure 3. When you add the INSERT statement, along
with a matching column list, the contents of the result set are loaded into the
table indicated in the INSERT statement.

Figure 3. The result set returned from the SELECT statement in the multi-row
INSERT query.

5-8 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Inserting Data

Creating a New Table Using SELECT


INTO
The SELECT INTO statement creates a new table with the columns necessary
to contain all the values that the SELECT statement returns. The following
query creates a new table called Produce, which contains all of the rows
matching the produce category in the Products table:

SELECT dbo.Products.* INTO dbo.Produce


FROM dbo.Products
WHERE CategoryID = 7;

NOTE When you create a new table with SELECT INTO, the new table
schema will match the original schema, including identity
columns. The Produce table will have a ProductID that is an
identity column. The nullability of columns is also copied from the
source, but indexes, constraints, and triggers are not copied.

Temporary Tables
Although the SELECT INTO syntax allows you to create tables in a database,
you probably won’t want to use this technique very often in applications.
Allowing users to create tables at will introduces problems with backups,
security, and database clutter. But sometimes you’ll want to create temporary,
or temp, tables.

You can create temp tables so that they are accessible only by the connection
that creates them. Once that connection ends, the tables are automatically
destroyed, which eliminates all of the problems with persistent tables. Temp
tables are stored in the tempdb database, and are identified by the first
character defining its name: the pound symbol (#).

NOTE Temp tables created in stored procedures are destroyed when the
stored procedure terminates.

The following SELECT INTO query creates a temporary table named


#Produce:

Microsoft SQL Server 2005 5-9


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Modifying Data

SELECT dbo.Products.* INTO #Produce


FROM dbo.Products
WHERE CategoryID = 7;

Namespace conflicts won’t occur, since every connection can have its own
#Produce in tempdb. Each #Produce table in tempdb has a suffix with an
underscore and the connection information to keep them separate. To select
data from the temp table, use the following query:

SELECT * FROM #Produce;

Another way to create temp tables is to use the standard CREATE TABLE
syntax, as shown in the following DDL statement:

CREATE TABLE #Beverages(


ProductID int NOT NULL,
ProductName nvarchar(40),
SupplierID int NULL,
CategoryID int NULL,
QuantityPerUnit nvarchar(20),
UnitPrice money NULL,
UnitsInStock smallint NULL,
UnitsOnOrder smallint NULL,
ReorderLevel smallint NULL,
Discontinued bit NOT NULL
)

The following query inserts data into the temp table. Note that the data types
you explicitly define in the temp table must match the data types defined in the
table you are selecting data from:

5-10 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Inserting Data

INSERT INTO #Beverages


SELECT
ProductID, ProductName, SupplierID,
CategoryID, QuantityPerUnit, UnitPrice,
UnitsInStock, UnitsOnOrder, ReorderLevel,
Discontinued
FROM dbo.Products
WHERE Products.CategoryID = 1

Uses for Temp Tables


The isolation of temporary tables is one of SQL Server’s greatest strengths.
Many users or applications can create temporary tables of the same name
without a problem. Temporary tables are extremely useful as work tables for
staging complex queries. You can execute a part of the query and store the
results in a temporary table, then use that table to execute the next parts of the
query. In the end, you can drop the temporary table, or it will be dropped
automatically when the connection ends.

You can do virtually everything with a temporary table that you can do with a
standard table: create indexes, create defaults and rules, modify the table, and
use the temporary table anywhere that you use a table. Any objects created for
the temporary table, such as indexes, are automatically dropped when the
temporary table is dropped.

Temporary tables can be used in stored procedures, in which case the table is
handled slightly differently. Temp tables in stored procedures are dropped
when the stored procedure ends, and do not persist for the duration of the
connection.

Global Temp Tables


Temporary tables can be shared across connections by creating a global
temporary table. You must use two pound symbols (##) to identify the global
temporary table. Global temporary tables persist until the connection that
created them ends and no other connection is actively using them. The
following statement creates a global temp table:

Microsoft SQL Server 2005 5-11


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Modifying Data

CREATE TABLE ##Categories


(
CategoryID int NOT NULL PRIMARY KEY CLUSTERED,
CategoryName varchar(255)
)

In practical usage, you will find that global temp tables are rarely called for,
since temp tables are generally used only by the connection that creates them.

Inserting with Output


One of the new features of SQL Server 2005 is the ability to return output from
a data modification query. This is useful when you insert multiple rows in a
table with an identity column and you want to know what the newly inserted
identity values are.

The following example creates a new table named Condiments and uses a table
variable named @NewValues to capture the identity column values when data
is inserted into the table.

CREATE TABLE dbo.Condiments (


ProductID int identity(1,1) NOT NULL PRIMARY KEY
CLUSTERED,
ProductName nvarchar (40) NOT NULL)
--Create table variable
DECLARE @NewValues TABLE(
ProductID int NOT NULL,
ProductName nvarchar(40)
)
--Insert values from Products and capture new identity
values
INSERT INTO dbo.Condiments(ProductName)
OUTPUT inserted.ProductID, inserted.ProductName
INTO @NewValues

5-12 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Inserting Data

SELECT
ProductName
FROM dbo.Products
WHERE CategoryID = 2
--Display the identity values
SELECT ProductID, ProductName FROM @NewValues

The first few rows of the result set are shown in Figure 4.

Figure 4. Displaying the results of INSERT with OUTPUT.

Using Bulk Copy to Insert Data


Bulk copy is the fastest way to add large numbers of rows in SQL Server.
There are several ways to bulk insert data into SQL Server: you can use the
bcp command line utility, a client API, or the Transact-SQL BULK INSERT
statement.

This example uses the BULK INSERT statement to load data from a text file
into SQL Server. The Products.txt file is a tab-delimited text file containing
product information. The data is in the following format. Note that there is no
header row in the text file.

1001 'Chai' 18

1002 'Chang' 19

1003 'Aniseed Syrup' 10

The BULK INSERT syntax allows you to set a variety of options for inserting
the data and is fully documented in SQL Server Books Online. This example
uses a simple format specifying a tab field terminator and a newline row
terminator.

Microsoft SQL Server 2005 5-13


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Modifying Data

The Transact-SQL BULK INSERT statement specifies the location of the table
using the three-part naming syntax. The FROM clause specifies the name and
location of the source file, as shown here.

BULK INSERT Northwind.dbo.NewProducts


FROM 'C:\Data\Products.txt'
WITH
(
FIELDTERMINATOR = '\t',
ROWTERMINATOR = '\n'
)

TIP: SQL Server Integration Services (SSIS) is a new component of SQL Server
2005 that replaces the old Data Transformation Services (DTS). SSIS
provides comprehensive support for importing data from a variety of sources,
as well as support for exporting and transforming data.

5-14 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Updating Data

Updating Data
The Transact-SQL UPDATE statement allows you to modify existing data.
The basic syntax for updating data is:

UPDATE tablename
SET column1 = value1, column2 = value2...

However, if you execute such a statement, the values in all of the rows in the
table are updated. The WHERE clause shown here restricts the number of rows
that the statement affects.

UPDATE table_name
SET [table_name].column_name = expression
WHERE search_condition

Updating a Single Row


To update a single row, specify a WHERE clause in the UPDATE statement to
limit the scope of the revisions. In this case, the CategoryName limits the rows
affected to a single row (unless there are multiple categories named Vitamins,
which is possible in Northwind because there is no unique constraint on
CategoryName).

UPDATE dbo.Categories
SET
Description = 'Pills that are good for you'
WHERE CategoryName = 'Vitamins';

Note the various elements of the UPDATE statement. First, it specifies the
name of the table that contains the data to be modified. The SET clause lists all
changes to be made, specifying the column name and the value to set the
column to. You can change multiple values by listing each field name and the
value to set it to. Use a comma to separate each pair.

Microsoft SQL Server 2005 5-15


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Modifying Data

Updating Multiple Rows and Columns


To update multiple rows, simply make the WHERE clause less restrictive. To
update multiple columns, include value assignments for them. The following
query updates the unit price and reorder level for all products with a
CategoryID of 2.

UPDATE dbo.Products
SET
UnitPrice = UnitPrice * 1.1,
ReorderLevel = ReorderLevel + 5
WHERE CategoryID = 2

This query will update 19 rows of data.

TIP: Always develop your data modification queries as SELECT queries first.
Accidentally changing all the customer addresses to the same value can cause
tremendous problems if you do not have a current backup available. By
testing the WHERE clause of your UPDATE statement, or any other action
query, you’ll be certain that you’re affecting only the rows you want to affect.

Updating from Another Table


You can also use UPDATE in conjunction with another table. In this example,
the UnitPrice in the Beverages table is updated to reflect the price in the
Products table wherever the ProductIDs match:

UPDATE dbo.Beverages
SET
dbo.Beverages.UnitPrice = dbo.Products.UnitPrice
FROM dbo.Beverages JOIN dbo.Products
ON dbo.Beverages.ProductID = dbo.Products.ProductID;

5-16 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Updating Data

Updating with TOP


One of the new Transact-SQL features in SQL Server 2005 is the ability to use
the TOP clause to limit the number of rows modified in an UPDATE
statement. This query updates not more than five rows.

UPDATE TOP (5) dbo.Beverages


SET UnitPrice = UnitPrice * 1.1
WHERE Discontinued = 0
ORDER BY UnitPrice;

Updating Large Value Types with


UPDATE .WRITE
SQL Server 2005 contains the new UPDATE .WRITE Transact-SQL
statement for performing partial updates on columns defined as varchar(max),
nvarchar(max), or varbinary(max). The abbreviated syntax is shown here.

UPDATE

{ <object> }

SET

{ column_name = { .WRITE ( expression , @Offset , @Length


) }

This example uses the Production.Document table in the AdventureWorks


database to demonstrate substitution of the word “critical” for the word
“important” in one row of data with a DocumentID of 7.

First, select the row.

SELECT DocumentSummary
FROM Production.Document
WHERE DocumentID = 7;

Microsoft SQL Server 2005 5-17


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Modifying Data

The first sentence in the results should look like Figure 5.

Figure 5. First sentence in the result set.

To change the word “important” to the word “critical” you need to specify the
offset and the length of the string to be replaced.

UPDATE Production.Document
SET DocumentSummary .WRITE (N'critical',6,9)
WHERE DocumentID = 7;

The results are shown in Figure 6.

TIP: The CHARINDEX and PATINDEX functions are useful for calculating the
offset, or number of characters from the start of the string to the value to be
replaced.

Figure 6. Changing one word in the data.

Execute this statement to restore the original value.

UPDATE Production.Document
SET DocumentSummary .WRITE (N'important',6,8)
WHERE DocumentID = 7 ;

WARNING! In past versions of SQL Server, WRITETEXT was used to replace


sections of long text values. This is still supported in SQL Server
2005, but it has been deprecated and will be removed in a future
version of SQL Server. Therefore, you should always use the new
.WRITE clause of an UPDATE statement rather than using
WRITETEXT.

5-18 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Deleting Data

Deleting Data
The DELETE statement can delete a single row or multiple rows, depending
on the selectivity of your WHERE clause. The syntax of the DELETE
statement is:

DELETE [FROM] table_name


[WHERE search_conditions]

If you omit the optional WHERE clause, then all the rows in the table will be
deleted.

Deleting a Single Row


To delete a single row, use the primary key (or any unique value) in the
WHERE clause. The following query deletes a single row with the Product ID
of 2 from the Beverages table:

DELETE FROM dbo.Beverages


WHERE ProductID = 2;

Deleting Multiple Rows


To delete multiple rows, modify the WHERE clause to be less selective. The
following query deletes all of the rows from the Beverages table with a
UnitPrice of less than 10:

DELETE FROM dbo.Beverages


WHERE UnitPrice < 10;

If you want to remove all of the rows from the Beverages table, simply omit
the WHERE clause:

DELETE FROM dbo.Beverages;

Microsoft SQL Server 2005 5-19


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Modifying Data

The result of this DELETE query is that all rows in the Beverages table are
deleted.

Using TRUNCATE TABLE


If your intention is to delete all of the records in the table, and you are
confident that you won’t need to roll back the operation, then use TRUNCATE
TABLE. This statement executes much faster than an all-row DELETE,
because only the deallocation of pages is logged, and no triggers or rules fire
during the delete. TRUNCATE TABLE does not log the individual row
deletions and therefore uses fewer system and transaction log resources.

TRUNCATE TABLE dbo.Produce

In addition, identity columns are reset to the seed value defined for the column
when you use TRUNCATE. When you use DELETE, the identity seed is not
reset.

5-20 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Understanding Transaction Isolation

Understanding Transaction Isolation


When modifying data in SQL Server it is important to understand how
isolation levels and locking can affect performance and concurrency.

TIP: The term concurrency refers to the ability of multiple users or applications to
access the same data. In relation to updates, concurrency conflicts occur when
multiple users select data and then try to update the data. One problem is that
locks on the data can delay the updates. Another problem is that users may be
allowed to update data that has changed since they last inspected the data.
Applications often prevent this by adding a WHERE clause to the update to
ensure that the update will succeed only if the data in the database still has the
values that were retrieved by that user. As the following section demonstrates,
locks can also affect performance for SELECT queries by other users, which
is another type of concurrency problem.

Isolation Levels Explained


SQL Server has four basic isolation levels and one additional isolation level
that is new to SQL Server 2005, snapshot isolation, which will be discussed
later in this section. The four basic isolation levels are:

• READ COMMITTED: The default isolation level. Every statement


that selects or modifies data executes at this level unless the isolation
level is explicitly changed. Read committed means that data cannot be
read until a row that is being edited has been committed and saved.
• READ UNCOMMITTED: The opposite of READ COMMITTED.
All rows can be read regardless of their state. This situation is
sometimes referred to as “dirty” reads, because rows that have pending
but uncommitted changes are referred to as being dirty.
• REPEATABLE READ: Prevents updates to rows that are being
edited but allows inserts of new rows to the table.
• SERIALIZABLE: Prevents both updates and inserts and is the most
restrictive isolation level.

READ COMMITTED
READ COMMITTED issues shared locks when data is being read. Shared
locks do not prevent other processes from reading the same data. When data is
modified, exclusive locks are issued that remain in effect until the data is
committed or rolled back. It is important to understand that while data is

Microsoft SQL Server 2005 5-21


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Modifying Data

locked for modification, READ COMMITTED blocks that data from being
selected by preventing other processes from obtaining the shared locks.

READ UNCOMMITTED
READ UNCOMMITTED is the least restrictive isolation level. It does not
issue any locks itself or honor any locks placed by other processes. It allows
dirty reads because the underlying data may change while it is being read.

READ UNCOMMITTED is useful when you want to retrieve or summarize a


large amount of data and when the consistency of individual row values is
unimportant. Another case would be if you were querying static data that is
read-only or is rarely modified. Performance is very fast because SQL Server
does not incur the additional overhead of placing shared locks on rows being
read and doesn’t have to check for exclusive locks.

As you’ll learn, the new snapshot isolation level provides a more robust
alternative to using READ UNCOMMITTED.

REPEATABLE READ
REPEATABLE READ prevents other processes from viewing or updating
data until the transaction using REPEATABLE READ completes, but it does
not prevent other processes from inserting new rows. The inserted rows are
known as phantom rows, because they are not detected by a transaction that
was initiated prior to their insertion.

A REPEATABLE READ is the minimum level of isolation required to prevent


lost updates. Lost updates occur when two separate UPDATE processes select
a row and then update it based on the selected data. The second update is lost if
it uses criteria that check whether the data has changed. REPEATABLE
READ ensures that the data cannot change while the lock is held. This is also
called pessimistic locking.

The REPEATABLE READ isolation level dramatically increases the number


of locks. As the number of locks increases, the number of concurrent users
decreases. REPEATABLE READ should be used only when it is highly likely
that two users will attempt to simultaneously update the same rows.

SERIALIZABLE
The SERIALIZABLE isolation level is the most restrictive isolation level of
all. It ensures that if a query is reissued inside the same transaction, existing
rows won’t look any different and new rows won’t suddenly appear. It
employs a range of locks that prevents edits, deletions, or insertions until the
transaction is complete.

SERIALIZABLE lowers multi-user concurrency due to the duration of the


lock and the number of records that are locked, but it ensures that each

5-22 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Understanding Transaction Isolation

operation is implemented successfully. SERIALIZABLE is useful when data


involved in a transaction must stay the same until the transaction is complete.
For example, you may need to produce a closing report that summarizes
transactions for the current date while preventing both inserts and
modifications. Inserts will either be forced to wait or to insert tomorrow’s date.

The new snapshot isolation level also provides a viable alternative to


SERIALIZABLE without reducing concurrency.

Blocking and Deadlocks


SQL Server is very efficient at applying and releasing locks. If you are
modifying data using the default READ COMMITTED isolation level, locks
will be applied and quickly released on each row of data.

Blocking
Blocking occurs when locks are held for too long. When a transaction is
blocked, it just sits there and waits. Over a network, blocked transactions will
either hang or eventually time out with an error message.

You can ameliorate common blocking problems by avoiding user interaction


in the middle of transactions, keeping data modifications short, and avoiding
recursive operations and nested triggers.

Deadlocks
A deadlock occurs when two separate processes are each holding a resource
that the other needs. Each process is waiting to release the resource it is
holding until the other resource becomes available. Unless one of the processes
is forced to yield, they will stay deadlocked forever. Deadlocks are difficult to
simulate in a development environment; they only seem to appear when your
database is running and many users attempt to complete the same operation at
the same time.

SQL Server uses an interval to determine which processes are running and
which are being blocked. If this interval passes twice and a process is still
blocked, SQL Server chooses a deadlock victim. The victim’s transaction is
rolled back, and error code 1205 is returned to the client application. Your
error handling routine in the client application can test for error 1205 and
resubmit or cancel the query. If SQL Server did not select a deadlock victim,
then eventually your server would run out of available processes and crash.

To avoid deadlocks, access objects in the same order every time you access
them, so that if a process is blocked it goes into a wait queue until the process
holding the lock is complete.

Microsoft SQL Server 2005 5-23


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Modifying Data

Try It Out!
Follow these steps to see how the READ COMMITTED isolation level affects
concurrency. This example uses an explicit transaction.

1. Execute the following statement in a query window. Note that you are
beginning a transaction, which locks data until the transaction either
commits or rolls back. This transaction uses the default READ
COMMITTED isolation level.

BEGIN TRANSACTION
UPDATE dbo.Categories
SET CategoryName = 'Supplements'
WHERE CategoryName = 'Vitamins'

2. Open a second query window and execute this SELECT statement:

USE Northwind;
SELECT CategoryName FROM dbo.Categories;

3. You will see that the query is blocked by looking at the status bar at
the bottom of the query window, as shown in Figure 7. This icon will
continue to display indefinitely until the UPDATE statement in the
first window is either committed or rolled back.

Figure 7. This tells you that your query is blocked.

4. Return to the first window and execute the ROLLBACK statement.


This releases the locks on the data and allows the SELECT statement
in the second query window to complete.

5. Start the transaction in the first window again. Switch to the second
query window and execute this statement:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED


SELECT CategoryName FROM dbo.Categories;

5-24 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Understanding Transaction Isolation

6. Executing the query displays Supplements, as shown in Figure 8,


which is data that has not been committed to the database.

Figure 8. Reading uncommitted data.

7. Return to the first query window and roll back the update. Execute the
query in the second window again, and you will see the original value
displayed.

NOTE The READ UNCOMMITTED isolation level will remain in effect


for the connection until it is reset or the connection is closed.

Using Snapshot Isolation


As you’ve seen, concurrency that is based solely on locking can cause
blocking and deadlocking problems. However, reading data using READ
UNCOMMITTED is not a solution for applications that require row-level
accuracy when retrieving data. To solve this problem, SQL Server 2005
introduces a new row versioning mechanism called snapshot isolation, which
is intended to improve performance by avoiding the reader-writer blocking
scenarios in the previous demonstration.

Read operations do not request shared locks on the data, so transactions that
modify data do not block transactions that read data, and transactions that read
data do not block transactions that write data, as they normally would under
the default READ COMMITTED isolation level.

The term “snapshot” reflects the fact that all queries in the transaction see the
same version, or snapshot, of the database, based on the state of the database at
the moment the transaction begins. No locks are acquired on the underlying
data rows or data pages in a snapshot transaction, which permits transactions to
execute without being blocked by a prior uncompleted transaction.

Microsoft SQL Server 2005 5-25


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Modifying Data

NOTE Two write operations will block each other even while running
under row versioning-based isolation levels because two write
operations cannot modify the same data at the same time.

Each transaction is identified by a unique transaction sequence number.


Whenever a transaction modifies a row, an image of the row before
modification is copied into a page in tempdb. If multiple transactions modify a
row, multiple versions of the row are linked in a version chain.

When a user or application retrieves data, it automatically gets the last saved
version of each row.

Snapshot Isolation Caveats


Snapshot isolation is not recommended for every application. There are several
reasons why READ COMMITTED might be a better choice for your
application:

• READ COMMITTED consumes less tempdb space than snapshot


isolation.
• Snapshot isolation does not work with distributed transactions that
span servers.
• Snapshot isolation is vulnerable to update conflicts that are not
applicable to READ COMMITTED. When a transaction running
under snapshot isolation reads data that is then modified by another
transaction, an update by the snapshot transaction to the same data
causes an update conflict and the transaction terminates and rolls back.
This is not an issue with READ COMMITTED.

Enabling Snapshot Isolation


You enable snapshot isolation per database by turning on the
ALLOW_SNAPSHOT_ISOLATION database option.

ALTER DATABASE Northwind


SET ALLOW_SNAPSHOT_ISOLATION ON;

This allows snapshot isolation when it is explicitly invoked, but the default
READ COMMITTED transaction isolation level remains in effect for implicit
transactions that do not specify snapshot isolation.

To replace READ COMMITTED entirely, turn on the


READ_COMMITTED_SNAPSHOT option in addition to the
ALLOW_SNAPSHOT_ISOLATION option. Snapshot isolation will then be
used for all transactions.

5-26 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Understanding Transaction Isolation

ALTER DATABASE Northwind


SET READ_COMMITTED_SNAPSHOT ON;

Try It Out!
Follow these steps to see how snapshot isolation works.

1. Enable snapshot isolation for the Northwind database.

ALTER DATABASE Northwind SET ALLOW_SNAPSHOT_ISOLATION ON;

2. Create a test table and insert one row of data.

--Create a test table.


CREATE TABLE dbo.TestSnapshot
(TestID int primary key, TestValue int);

--Insert one row of data.


INSERT INTO dbo.TestSnapshot VALUES (1,100);

3. Begin a transaction, but do not commit or roll it back.

BEGIN TRANSACTION
UPDATE dbo.TestSnapshot
SET TestValue = 200
WHERE TestID = 1;

4. Open a second query window and execute this statement.

SET TRANSACTION ISOLATION LEVEL SNAPSHOT;


SELECT TestID, TestValue FROM TestSnapshot;

5. Note that the query wasn’t blocked even though the row is in the
middle of an uncommitted transaction. The last saved value (100) is
displayed in the results pane. Recall that if you use READ

Microsoft SQL Server 2005 5-27


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Modifying Data

UNCOMMITTED to avoid the block, you would read the dirty,


unsaved value⎯in this case, 200.

6. Return to the first query window and commit the transaction.

COMMIT TRANSACTION;

7. Go to the second query window and execute the SELECT statement


again. You will now see the updated value because it is the last
committed value.

8. Turn off snapshot isolation for the Northwind database.

ALTER DATABASE Northwind SET ALLOW_SNAPSHOT_ISOLATION OFF;

9. To be able to rerun the examples in this chapter, execute the cleanup


code at the end of the script:

--CLEANUP
USE Northwind;
IF OBJECT_ID('dbo.Beverages') IS NOT NULL DROP TABLE
dbo.Beverages;
IF OBJECT_ID('dbo.Produce') IS NOT NULL DROP TABLE
dbo.Produce;
IF OBJECT_ID('dbo.Condiments') IS NOT NULL DROP TABLE
dbo.Condiments;
IF OBJECT_ID('dbo.NewProducts') IS NOT NULL DROP TABLE
dbo.NewProducts;
IF OBJECT_ID('dbo.TestSnapshot') IS NOT NULL DROP TABLE
dbo.TestSnapshot;
DELETE FROM dbo.Categories WHERE CategoryID > 8;
DELETE FROM dbo.Products WHERE ProductName='Pure
''Sunshine'' Orange Juice';

5-28 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Understanding Transaction Isolation

-- RESET the next IDENTITY value for dbo.Categories


DBCC CHECKIDENT ('dbo.Categories', RESEED, 1)
-- Because the seed is now lower than the max value,
-- the next call resets the seed
-- to the next value after the max.
DBCC CHECKIDENT ('dbo.Categories', RESEED)
-- And for Products
DBCC CHECKIDENT ('dbo.Products', RESEED, 1)
DBCC CHECKIDENT ('dbo.Products', RESEED)

Microsoft SQL Server 2005 5-29


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Modifying Data

Summary
• Executing DML statements is the most efficient way to add, edit, or
delete rows in SQL Server tables.
• Add new rows using the INSERT statement.
• Use SCOPE_IDENTITY to retrieve identity column values.
• Use the single quote delimiter for text and date values.
• Temp tables having names that begin with one pound symbol (#) are
only accessible by the connection that creates them and are destroyed
when the connection is closed.
• Use INSERT with OUTPUT to retrieve identity column values for
multiple rows.
• Use BULK COPY to insert a large number of rows.
• Modify rows using the UPDATE statement.
• Use the TOP clause to limit the number of rows modified in an
UPDATE statement.
• Use UPDATE .WRITE to perform partial updates on columns defined
as varchar(max), nvarchar(max), or varbinary(max).
• Delete rows using the DELETE statement.
• The TRUNCATE TABLE statement is not logged and executes much
faster than a DELETE statement when you want to delete all rows.
• READ COMMITTED is the default isolation level for SQL Server.
• READ UNCOMMITTED is the least restrictive isolation level and
allows dirty reads.
• Blocking occurs when locks are held and a transaction sits and waits.
• A deadlock occurs when each of two processes is waiting for a
resource that is locked by the other process.
• Snapshot isolation can improve performance by avoiding blocking
scenarios so that read operations do not request shared locks and
operations that modify data do not block read operations.

5-30 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Understanding Transaction Isolation

Questions
1. What is the advantage of DML statements over server-side cursors?

2. What keyword is used in an INSERT statement to specify row data?

3. How do you return an identity column value for an inserted row?

4. What clause do you use to limit the number of rows being deleted in a
DELETE statement?

5. What two methods can you use to delete all the data from a table?

6. What is the default isolation level in SQL Server?

Microsoft SQL Server 2005 5-31


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Modifying Data

Answers
1. What is the advantage of DML statements over server-side cursors?
DML statements execute faster and more efficiently.

2. What keyword is used in an INSERT statement to specify row data?


The VALUES keyword

3. How do you return an identity column value for an inserted row?


Use SCOPE_IDENTITY

4. What clause do you use to limit the number of rows being deleted in a
DELETE statement?
The WHERE clause

5. What two methods can you use to delete all the data from a table?
TRUNCATE TABLE and DELETE without a WHERE clause

6. What is the default isolation level in SQL Server?


READ COMMITTED

5-32 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Lab 5:
Modifying Data

Lab 5:
Modifying Data

Microsoft SQL Server 2005 5-33


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Lab 5:
Modifying Data

Lab 5 Overview
In this lab you’ll learn how to add, edit, and delete data from a table using
Insert, Update, and Delete queries.

To complete this lab, you’ll need to work through three exercises:

• Adding a Product
• Editing a Product
• Deleting a Product
Each exercise includes an “Objective” section that describes the purpose of the
exercise. You are encouraged to try to complete the exercise from the
information given in the Objective section. If you require more information to
complete the exercise, the Objective section is followed by detailed step-by-
step instructions.

5-34 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Adding a Product

Adding a Product

Objective
In this exercise, you’ll add a record to the Products table using an Insert query.
A new product named Green Tea Cola needs to be added to the lineup of
products. Table 2 contains the values you’ll be entering for this new product.

Name Value

ProductName Green Tea Cola


CategoryID 1
QuantityPerUnit 12
UnitPrice 3.95
ReorderLevel 5
Discontinued 0
Table 2. Values for the new product.

You will then retrieve the new identity column value for the inserted row so
that it can be used in the subsequent exercises.

Things to Consider
• What are the column names and data types for the Products table?
• Is there an identity column in the table?
• How do you retrieve the new identity value?
• Are there any special characters that must be handled properly?

Step-by-Step Instructions
1. Examine the structure of the Products table in the Object Browser pane.
The ProductID is an identity column and does not need to be specified in
the INSERT list.

2. Build the query:

Microsoft SQL Server 2005 5-35


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Lab 5:
Modifying Data

INSERT INTO dbo.Products(


ProductName, CategoryID, QuantityPerUnit,
UnitPrice, ReorderLevel, Discontinued)
VALUES(
'Green Tea Cola', 1, 12,
3.95, 5, 0)

3. Do not execute the query yet. You will need to retrieve the new identity
column value with the SCOPE_IDENTITY function. Add this statement:

SELECT SCOPE_IDENTITY() AS NewProductID

Execute the statements. The new identity column value will appear in the
results pane, as shown in Figure 9.

Figure 9. Returning the ProductID of the product added to the table.

NOTE Your table may return a different ProductID value than the value
in Figure 9. In the following exercises, it is important that you use
the ProductID that your query returned.

5-36 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Editing a Product

Editing a Product

Objective
In this exercise, you’ll set the price of the product added in the previous
exercise.

Things to Consider
• What kind of action query is used to modify existing data?
• What is the name and data type of the column being modified?
• How will you identify the record to be modified?

Step-by-Step Instructions
1. Determine the data type for the UnitPrice.

2. Use the ProductID of the new product in the WHERE clause of the
UPDATE statement to ensure that only a single row is affected.

3. Execute the following statement:

UPDATE dbo.Products
SET UnitPrice = 4.95
WHERE ProductID = 79;

4. One row should be affected.

5. To verify the results of the UPDATE statement, type the following query
in the Query Analyzer window:

SELECT ProductName, UnitPrice


FROM dbo.Products
WHERE ProductID = 79;

Microsoft SQL Server 2005 5-37


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Lab 5:
Modifying Data
6. The results of the Select query are shown in Figure 10.

Figure 10. Examine the results of the Update query.

5-38 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Deleting a Product

Deleting a Product

Objective
In this exercise, you’ll delete the product that you worked with in the previous
two exercises.

Things to Consider
• Which SQL statement is used to delete records?
• How will you uniquely identify the record to be deleted?

Step-by-Step Instructions
1. To create a DELETE query that does not accidentally delete all of the rows
in a table, start with a SELECT query that has a WHERE clause specifying
the row or rows to be deleted. Use the SELECT query from the previous
exercise, in which you verified that the row was modified:

SELECT ProductName, UnitPrice


FROM dbo.Products
WHERE ProductID = 79;

2. Delete the first line of the query with the SELECT statement.

FROM dbo.Products
WHERE ProductID = 79;

3. Add the DELETE keyword in front of the FROM keyword so that the
query looks like the following:

DELETE FROM dbo.Products


WHERE ProductID = 79;

Microsoft SQL Server 2005 5-39


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.
Lab 5:
Modifying Data
4. Execute the SELECT statement again. Figure 11 shows that no rows are
returned for that product ID.

SELECT ProductName, UnitPrice


FROM dbo.Products
WHERE ProductID = 79;

Figure 11. The SELECT query results after the row is deleted.

5-40 Microsoft SQL Server 2005


Copyright © by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

You might also like