Rdbms With SQL Server 2005 - Done

Download as pdf or txt
Download as pdf or txt
You are on page 1of 144

1

EPITOME

RDBMS with SQL Server 2005


STUDY MATERIAL
2

PREFACE

Dear Students,

Structure Query Language (SQL) is a database computer language designed


for the retrieval and management of data in relational database. SQL have become
ubiquitous as a fundamental tool for managing information, and a course on the
principles and practice of database systems is now an integral part of computer
science curriculum.

This E-Book covers the fundamentals of modern database management


systems, in particular to relational database systems. It is intended as a text for an
introductory database course for graduates, undergraduates, and we have attempted
to present the material in a clear, simple style.

If this E-Book helps anyone to learn and to use the computer effectively, it
will be of great success.

EPITOME EDUCATIONAL SOCIETY


3

CONTENTS
- lntroduction to RDBMS 4
- Approaches to Data Management 5
- lntroduction to DBMS 7
- Database Models 8
- Cood's 12 rulefor RDBMS 13
- Database Design 16
- Structured Query Language (SQL) 44
- SQL Server Data types 44
- Create Table statement 46
- lntegrity Contraints 49
- Altering Table Statements 56
- Sub Queries 64
- Joins 66
- Sorting of Data 77
- Using Transact - SQL 81
- View 87
- Trigger 89
- Stored Procedure 93
- SQL Cursors 97
- Data Permissions 139
SQL Server 2005 4

INTRODUCTION TO RDBMS
SQL Server is a Relational Database Management System (RDBMS) developed and marketed
by Microsoft. This system is a important part of Microsoft's Back Office, an enterprise
suite of client-server applications.

SQL Server runs exclusively under Windows. Microsoft's decision to concentrate on only
their operating system results in benefits as :

 SQL Server works as a natural extension of Windows, because it is closely


integrated with the operating system. The user does not have to learn another
interface to work with SQL Server.
 It has the same easy set-up and maintenance of Windows
 It uses services of Windows to offer new or extended database capabilities,
such as managing logon

However, by focusing on only Microsoft Operating Systems, SQL Server cannot


benefit from advanced operating systems like UNIX.

Almost all relational database originated under the UNIX operating system. The
consequence is that, existing user interface provided by these systems are rather difficult to
use. Microsoft's goal is to make SQL Server the easiest database for implementing and
managing database applications.

The important aspects of SQL Server are :


 SQL Server is easy to use
 SQL Server scales from a laptop to symmetric multiprocessor (SMP)
 SQL Server provides data warehousing features that have been available only
under Oracle and other expensive database

The original SQL Server database system was developed and implemented by
Sybase Inc. Microsoft licensed this DBMS in 1988 for their OS/2 operating system and began
the implementation of it for Windows NT in early 1990's. In 1994, Microsoft ended their
cooperative agreement with Sybase Inc.

EPITOME
SQL Server 2005 5

Approaches to Data Management

• Manual methods of Data Management


• Management of Data and Information
• Convenient and efficient retrieval
• Updating Operations
• Limitation of Manual Data Management
• Physical Volume of Data
• Human Processing of Data
• Technological Advancement in Data Management
• Using Computers to speed up processing of Data
• Advancement of Processing Power
• Using time-sharing for multiple users
• High-speed storage devices
• Centralized to distributed databases
• Centralized to distributed Processing (Client/Server)
Excellent Book keeping strategies existed before the computer age, on the management of
data, including convenient and efficient retrieval and update operations. Due to the limitations
associated with the physical handling of documents and human processing, a look in retrospect
suggests that data and information generated through data were only marginally used in
daily decision making, even in progressive organizations.
The application of computers, speeds up the data processing activities and adds some
flexibility to the management of data and the information generated from it. Widespread and
easy access to time sharing systems, advances in logical and physical access methods,
matched by steep increases in the density and volume of disk storage devices, led gradually
to a reassessment of the role of data in management decision making.
This transition was facilitated by the induction of database technology into the organizations.
The emerging discipline of distributed database management is able to eliminate the
constraints of geographic distribution of decision nodes.
EPITOME
SQL Server 2005 6

Database Management : An Evolutionary Phenomenon

• The evolution of database management was accompanied and promoted by:

• Advances in computing: Hardware, OS and Networking

• Drawbacks of the prevalent approach to Data Management

• Data redundancy

• Risk to data integrity

• Data isolation

• Difficult access to data

• Unsatisfactory security measures

• Poor support of concurrent access of data

Earlier, organizations followed the fragmented approach to data processing by designing


files to specifically suit different application systems. Since the different functional units (de-
partments) in an organization have large amounts of data to share, this approach, inevitably
leads to some major disadvantages as discussed below.

• Data Redundancy- Since the files and application programs are written over a long
period of time, data in the files is likely to get repeated. This may also lead to inconsistency
that is, the various copies of the same data may contain different information. Data
redundancy could also occur due to duplication of data at different locations - the need
for the same data at physically different locations.
• Risk to data integrity- The data values stored, must satisfy certain integrity constraints.
These constraints can be enforced in the system, by adding appropriate code in the
application programs. The problem is compounded when constraints involve several
data items from different files. .
• Data isolation- Since data is scattered in various files, and files may be in different
formats, it is difficult to write new application programs to retrieve the appropriate data.
• Difficult access to data- Whenever there is a new request, that was not anticipated
earlier, there are two possible solutions. Either extract the records manually, or have the
system programmer write the necessary application.

EPITOME
SQL Server 2005 7

• Unsatisfactory security measures- Every user of the system should be allowed to


view only that part of the data that is relevant to his department. Since application programs
are added to the system in an ad hoc manner, it is difficult to enforce such integrity
constraints.
• Concurrent access- Many systems allow multiple users to update the data simultane-
ously to improve the overall performance of the system and obtain a faster response.
But in such an environment interaction of concurrent updates, may result in inconsistent
data. Since the application programs which have not been previously coordinated are
used to access data, supervision is very difficult to provide.

Database management addressed all these problems, though at the price of increased over-
heads and costs.

However, with the advancement of technology and the all-round development made in Hard-
ware, Software, Networking and Operating Systems, the drawbacks of Data Management
have been eliminated to a great extent.

Introduction to DBMS

• A Programmer’s Productivity Tool

• Good User interface

• Powerful Database Structure

• Advancement of Data Manipulations

• Use of 4 GL Tools

• A discipline towards data independence

• Logical Data Independence

• Physical Data Independence

• Data View

• External View

• Conceptual View

• Internal View

EPITOME
SQL Server 2005 8

EXTERNAL VIEW USER LEVEL

Mapping to achieve logical data


independence .
CONCEPTUAL VIEW Administrator level
Mapping to achieve physical data
independence
INTERNAL VIEW Hardware Level

Database Models

• Hierarchical

• Network

• Relational

• Hierarchical Model

This model was introduced in the Information Management System (IMS) developed by IBM
in 1968. This model is like a hierarchical tree structure, used to construct a hierarchy of
records in the form of nodes and branches. The data elements present in the structure have
a Parent-Child relationship. Closely related information in the parent-child structure is stored
together as a logical unit. A parent unit may have many child units, but a child is restricted to
have only one parent.

In order to gain an understanding of the various database models, we take an example of a


sample database consisting of supplier, parts and shipments. A possible hierarchical view for
the supplier-parts database. In this view, data is represented by a simple tree structure, with

EPITOME
SQL Server 2005 9

parts superior to suppliers. The user sees four individual trees, or hierarchical occurrences
one for each part. Each tree consists of one part record occurrence, together with a set of
subordinate supplier record occurrences, one for each supplier of the part. Each supplier
occurrence includes the corresponding shipment quantity that the set of supplier occurrences
for a given part may contain any number of members, including zero.

The record type at the top of the tree - the part record type in our example is usually known
as the “root”. In general, the root may have any number of dependents, and so on, to any
number of levels.

Such a file, however, is a more complex object than the tables. In the first place, it contains
several types of records, not just one; in our example there are two, one for parts, and one
for suppliers. Second, it also contains links, connecting occurrences of these records; in our
example there are links between part occurrences and supplier occurrences, representing
the associated shipments.
The drawbacks of this model are:

1. The hierarchical structure is not flexible enough to represent all the relationship proportions
which occur in the real world.

2. It cannot demonstrate the over all data model for the enterprise because of the non-
availability of actual data at the time of designing the data model.

3. It cannot represent the Many-to-Many relationship

4. The Hierarchical model is used only when the concerned data has a clearly hierarchical
character with a single root, for example the DOS directory structure.

• Network Model

It is an improvement on the hierarchical model. Here multiple parent-child relationships are


used. Rapid and easy access to data is possible in this model due to multiple access paths
to the data elements.

EPITOME
SQL Server 2005 10

A network view for the suppliers-and-parts database. In this view, as in the


hierarchical approach, data is represented by records and links. However, a network
is a more general structure than a hierarchy because a given record occurrence
may have any number of immediate superiors and dependents - we can have
more than one, unlike hierarchical. The network approach thus allows us to model
a many to many correspondence. In addition to the record types representing the
suppliers and parts themselves, we introduce a third type of record which we will
call the connector.

A connector occurrence, represents the association (shipment) between one


supplier and one part, and contains data describing the association. All connector
occurrences for a given supplier or part are placed on a chain starting at and
returning to that supplier or part. Each connector thus has exactly two chains, one
supplier and one part chain. For example Fig. 4.3 shows that supplier S02 supplies
250 of part P02 and 100 of part P01; similarly it shows that part P01 is supplied in
a quantity of 150 by supplier S01 and quantity of 300 by supplier S03. Note that
the correspondence between, say, one supplier and the associated connector
records is one-to-many, which shows that hierarchies may easily be represented
in a network system.

EPITOME
SQL Server 2005 11

Transaction is maintained using pointers and having to trace the pointers is the
drawback of this design.

Relational Model

• Data is organized in terms of rows and columns in a table known as relations


• The position of a row in a table is of no importance

• The intersection of a row and column must give a single value

• All values appearing in the columns are derived from the underlying domain
• Row must be unique
• Column Names must be unique
• All column values are atomic
• In relational database, there are no hard-coded relationships defined between
tables. A relationship can be specifed at any time using any column name.

The publication of the paper “A Relational Model of Data for Large Shared Databases” by
E.F. Codd in June 1970 in the “Communication of ACM”, set a trend for vigorous and extensive
investigation into a theoretical frame work to support further work in the airea of Data Modeling.
The end result is the Relational Database Management Systems (RDBMS).

In RDBMS, the data is organized in tables consisting of rows and columns.

• Supplier

Supplier Supplier Supplier City


Code Name Status Supplier

S01 Ram 15 Calcutta


S02 Shyam 20 Chennai
S03 Amit 25 Hyderabad
S04 Rajesh 15 Mumbai

EPITOME
SQL Server 2005 12

• Part

P Code Part Name Weight City

P01 Screw 8 Calcutta


P02 Nut 16 Chennai
P03 Bolt 20 Hyderabad
P04 Nut 16 Mumbai

• Shipment

SCode PCode Qty


S01 P01 150
S01 P02 200
S02 P03 250
S02 P04 100
S03 P01 300

Consider the tables shown in the sample database. Each supplier status has a unique supplier
code which uniquely identifies the entire row of the table and exactly one name, and city.
Likewise each part has a unique PCode and exactly one name, size and city and at any
given time no more than one shipment exists for a given supplier/part combination.

The term ‘relation’ is used to describe these tables, which is a more precise way of defining
than the traditional data processing term “file” or “table”. Rows of such tables are referred to
as tuples, again a more precise definition than rows or records and columns are referred to
as attributes. A domain is a set of values from which actual values appearing in a given
column are ‘drawn. For example, the values appearing in the part column of both parts and
shipment tables are drawn from the underlying domain of all valid part numbers. This domain
itself may not be explicitly recorded but will be defined in the appropriate schema and will
have a name of its own. We can see that the relations supplier and parts have a domain in
common; so do parts and shipment; so do supplier and shipment. Another important concept
in relational database is that relationships between tables are not hardcoded in the structure
of the data. There are no pointer in the data to relate one table to another. The relationship
between two or more sets of data can be specified at the development time rather than when

EPITOME
SQL Server 2005 13

the tables are first created. This greatly improves the flexibility of the database management
system.

The relational data structure is that association between tuples that are represented solely
by data values in columns drawn from a common domain. The fact that supplier S03 and
PO2 are located in the same city is represented by the appearance of the same value in the
city column for the two tuples.

• Properties of Relational Database

A relational database management system (RDBMS) has the following properties:

• Represents data in the form of tables.

• Does not hard-code relationships between tables.

• Doesn’t require the user to understand its physical implementation

• Provides information about its content and structure in system table

• Supports the concept of NULL values.

The 12 Rules for an RDBMS (Codd’s Rule)

• The information rule


• The guaranteed access rule
• Systematic treatment of null values
• Active online catalog based on the relational model
• The comprehensive data sublanguage rule
• The view updating rule
• High-level insert, update, and delete
• Physical data independence
• Logical data independence
• Integrity independence
• Distribution independence
• The nonsubversion rule

EPITOME
SQL Server 2005 14

• The information rule

All information in the database to be represented in one and only one way, namely by values
in column positions within rows of tables.

• The guaranteed access rule

All data must be accessible with no ambiguity. This rule is essentially a restatement of the
fundamental requirement for primary keys. It says that every individual scalar value in the
database must be logically addressable by specifying the name of the containing table, the
name of the containing column and the primary key value of the containing row.

• Systematic treatment of null values

The DBMS must allow each field to remain null (or empty). Specifically, it must support a
representation of "missing information and inapplicable information" that is systematic, distinct
from all regular values (for example, "distinct from zero or any other number," in the case of
numeric values), and independent of data type. It is also implied that such representations
must be manipulated by the DBMS in a systematic way.

• Active online catalog based on the relational model

The system must support an online, inline, relational catalog that is accessible to authorized
users by means of their regular query language. That is, users must be able to access the
database's structure (catalog) using the same query language that they use to access the
database's data.

• The comprehensive data sublanguage rule

The system must support at least one relational language that


(a) Has a linear syntax
(b) Can be used both interactively and within application programs,
(c) Supports data definition operations (including view definitions), data manipulation
operations (update as well as retrieval), security and integrity constraints, and transaction
management operations (begin, commit, and rollback).

EPITOME
SQL Server 2005 15

• The view updating rule

All views that are theoretically updatable must be updatable by the system.

• High-level insert, update, and delete

The system must support set-at-a-time insert, update, and delete operators.

• Physical data independence

The physical representation of the data must be invisible to the user, so that the user can
manage the data according to need rather than according to the way it is stored

• Logical data independence

If a user's view of the data has been defined, then changing the logical structure of the data
(tables, columns, rows, and so on) must not change the user's view.

• Integrity independence

Integrity constraints must be specified separately from application programs and stored in
the catalog. It must be possible to change such constraints as and when appropriate without
unnecessarily affecting existing applications.

• Distribution independence

The distribution of portions of the database to various locations should be invisible to users
of the database. Existing applications should continue to operate successfully
(a) when a distributed version of the DBMS is first introduced.
(b) when existing distributed data is redistributed around the system.

• The nonsubversion rule

If the system provides a low-level (record-at-a-time) interface, then that interface cannot be
used to subvert the system, for example, bypassing a relational security or integrity constraint.
An RDBMS product has to satisfy at least six of the 12 rules of Codd to be accepted as
a full fledged RDBMS.

EPITOME
SQL Server 2005 16

• Physical Data Independence

Database Design

• Requirement Formulation and Analysis


• Collection and Documentation of Requirement
• Analysis of Requirement
• Conceptual Design
• Data Modeling
• First level E-R Modeling
• Second level Normalization
• E-R Modeling
• Physical Design and Implementation

EPITOME
SQL Server 2005 17

Database design is the process of developing database structures to hold data to cater to
user requirements. The final design must satisfy user needs in terms of completeness, integrity,
performance and other factors. For a large enterprise, the database design will turn out to be
an extremely complex task leaving a lot to the skill and experience of the designer. A number
of tools and techniques, including computer-assisted techniques, are available to facilitate
database design.

• Requirements Formulation and Analysis

The primary input to the database design process is the organization’s statement of require-
ments. Poor definition of these requirements is a major cause of poor database design,
resulting in databases of limited scope and utilities which are unable to adapt to change.
Requirement analysis is the process of identifying and documenting the data that the user
requires in the database to meet present and future information needs. During this phase,
the analyst studies data flows and decision making processes in the organization and works
with the users.

The objective of this phase is to answer the following questions:

• What are user-views of the data (present and future) ?

• What data elements (or attributes) are required in these user-views?

• What are the entities and their primary keys?

• What are the operational requirements regarding Security, Integrity and Response
time?

• Conceptual Design

The major step in conceptual design is to identify the entities and relationships that reflect
the organization’s data, ‘naturally’. The objective of this step is to specify the conceptual
structure of the data and is often referred to as data modeling. The E-R model, with an
emphasis on the topdown approach, will be discussed as an information model to develop a
conceptual structure, later in this chapter.

EPITOME
SQL Server 2005 18

Data Modeling

• Describes relationships between data objects

• First level - Entity-Relationship Diagrams

• Second level - Normalization


The relationships between the collection of data in a system may be graphically represented
using data modeling. If the relationships are complex, data modeling provides a simplified
approach to the structured design of the system. It helps determine the data objects in the
system, the composition of each, and the relationships that exist between them.

Data Modeling is achieved in two levels - the first level builds the conceptual model of the
data, using E-R Modeling. The second level organizes this model better, by removing re-
dundancies, through a process called Normalization. The Normalized model is then converted
into the Physical Database.

Entity Relationship Diagram

Entity Relationship Modeling is a technique for analysis and logical modeling of a system’s
data requirements. It uses three basic concepts, entities, their attributes and the relationships
that exist between the entities. It uses graphical notations for representing these.

• Graphical Notations for E-R Diagram

NAME SYMBOL FUNCTION

Entity Data object in the system Uniquely


identifiable by identifier
Has attributes that describe it

Attribute Describes the entity

Relationship Relates two entities Uniquely

identified by the identifier

EPITOME
SQL Server 2005 19

Entity
An Entity is any object, place, person, concept, activity about which an enterprise records
data. It is an object which can have instances or occurrences. Each instance should be
capable of being uniquely identified. Each entity has certain properties, or Attributes associ-
ated with it and operations applicable to it. An entity is represented by a rectangle in the E-R
Model.
Categories of objects under which an entity is identified:

Category Examples
Physical object Employee, Machine, Book, Client, Student, Item
Abstract object Application, Department
Event Application, Reservation, Invoice, Contract
Location Building, City, State

Entity type and entity instance are two important term related to entities. An entity type is a
set of things which share common properties. For e.g., STUDENT COURSE etc. An entity
type is usually denoted in upper case. An entity instance is a specific individual thing. For
e.g., “Mohit”, “Physics”. An entity instance is usually denoted in lower case.

• Attributes

Attributes are data elements that describe an entity. If the attribute of an entity has more
attributes that describe it, then it is not an attribute of that entity, but another entity. Attributes
can either be listed next to the entities, or placed in circles and attached to the entities.

Similarly, Attributes can also describe properties of Relations.


Example:

Entity Attributes
Customer Name, Address, Status
Book ISBN, Title, Author, Price
Order Order Number, Order Date, Placed by

EPITOME
SQL Server 2005 20

Identifier is one or more attributes of an Entity or Relation, whose value uniquely identifies
the entities or relationships. The identifier attributes are underlined in the diagram.

Example:

PERSON PERSON ID
NAME
DOB

PROJECT PROJECT ID
START_DATE
BUDGET

Relationship

This is an association between entities. It is represented by a diamond in the E-R diagram.


For e.g., there is a relationship between student and course. This relationship represents the
fact that a student enrolls in a course. This relationship could be named as enrolls in. Rela-
tionships can also have properties or Attributes associated with it. The attributes may be
listed next to the relation, as mentioned earlier.

Entity Attributes
Student ID, Name, Address, DOB
Course Course Code, Duration, Start Date, Room No.

A relationship may associate an entity with itself. For example, in a company, one employee
EPITOME
SQL Server 2005 21

may marry another employee. Hence the following relationship can be possible.

Several relationship may exist between the same entities. For example

Dependent Entities
• Depend on the existence of a parent entity

• Also known as weak entities

• Have composite identifiers, one from parent and another of its own

There are two types of entities, dependent and independent. An entity whose existence
depends on the existence of another entity is called a dependent entity. Consider the entity
type OFFERING. A course with same code can be offered in different semesters and different
campuses. The existence of OFFERING depends on the existence of entity type COURSE.
The dependent entity is depicted in the E-R diagram by a rectangular box with a second line
drawn across the top.

Dependent entities have composite identifiers. The identifier consists of the parent entity,
together with another attribute that uniquely identifies the dependent entity with the parent.

EPITOME
Computer Overview 22

Example:

Fig. 4.10

The figure depicts entities PROJECTS and TASKS. A task obviously cannot be present
without the existence of a related Project. The entity Task is thus modeled as a Dependent
Entity of the Project Entity. The dependence is shown by the arrow from PROJ ECTS to
TASKS.

Thus the identifier of TASKS is composed of the attributes, PROJECT-ID (which identifies
the project) and TASK-NO (which identifies the particular task in the project). Every task in a
project may be assigned a Budget, which becomes an attribute of the Task.

An independent entity does not depend on any other entity for existence. For e.g. STUDENT

Subsets and Supersets

• Derived from parent entities called supersets

• Formed when occurrences of the superset are treated in different ways

• Modeled by rectangular boxes, with a second line on the left hand side of the box

• Common attributes among subsets are attributes of the Superset

• Attributes pertaining to each subset, become attributes of that subset

• Identifier of a subset is the identifier of the Superset

A subset is derived from another entity which is called superset. For example, consider the
entity EMPLOYEE. There are two types of employees - salaried employees and wage earning
employees. In this example, EMPLOYEE is the superset, and the SALARIED and WAGE-
EARNING employees are the subset. Subsets have certain attributes of their own, which are
unique to them. They also share some attributes with the other subsets.

EPITOME
SQL Server 2005 23

The common attributes become attributes of the parent entity set, whereas attributes pertaining
to the subset alone are shown as attributes of that subset. For example, “name’, “address”
are common attributes of subset SALARIED and WAGE. So they become attributes of the
parent entity set EMPLOYEE.

WAGE-EARNING employees will have some attributes, like “overtime”, “daily wages” that
do not belong to the subset SALARIED. The subset SALARIED has some attributes like
HRA, BASIC, ALLOWANCE that do not belong to the subset WAGE-EARNING.

A subentity or subset is always dependent on the superentity or superset for its existence.
The attributes of superset apply to all of its subsets. The converse is not true.

Degree of Relationship

• One to One (1:1)

• One to Many (1:N)

• Many to Many (M:N)

The Degree of a Relationship, indicates the link between two entities for a specified occur-
rence of each. The degree of a relationship is also called Cardinality.

• One to One Relationship : (1:1)

EPITOME
SQL Server 2005 24

One Order Requisition raises one purchase order.


One purchase order is raised by one order requisition.

For one occurrence of the first entity, there can be at most one related occurrence of the
second entity, and vice-versa.
• One to Many Relationship: (1:N)

One employee works in at most one department.


One Department can have many employees.

For one occurrence of the first entity there can exist many related occurrences of the
second entity and for every occurrence of the second entity there exists only one associ-
ated occurrence of the first.

• Many to Many Relationship (M:N)

One order may contain many items.


One item can be contained in many orders

For one occurrence of the first entity, there exists many related occurences of the second
EPITOME
SQL Server 2005 25

entity and for every occurrence of the second entity, there may exist many associated occur-
rences of the first.

Normalization

Normalization is a process of eliminating the redundancy of data in a database. A Relational


table in a database is said to be in a normal form if it satisfies certain constraints. The
normalization process involves various levels of normal forms that allow you to separate the
data into multiple related tables. The various normal forms are first normal form (1NF), second
normal form (2NF), third normal form (3NF), fourth normal form (4NF) and fifth normal form
(5NF).

The goals of normalization are:


 Removing the redundant data
 Ensuring that only related data is stored in a table
Therefore, normalization helps you to remove data redundancy and update inconsistencies
when data is inserted, deleted or modified in a database. The benefits of normalization are
as follows:
 It provides better overall database organization and data consistency within a
database.
 It allows you to create tables that can be easily joined with other tables with
related information.
 It helps to reduce redundant data across the tables.
 It prevents data loss by assigning primary and foreign keys in a table.
 It helps to reduce modification anomalies such as deletion, insertion and update
anomalies.
 It defines relation constraints that are a logical consequence of keys.

Normalization Terminology
Normalization terminology consists of various concepts that are frequently used in
normalization, for example primary key and functional dependency.
Primary Key
EPITOME
SQL Server 2005 26

The primary key of a relational table uniquely identifies each row in a table. A pri-
mary key is either a column in a table that is unique such as identification number and
social security number of it is generated by the DBMS such as a Globally Unique Identifier
(GUID). Primary key is a set of single column of multiple columns from a table. For exam-
ple, consider a student records database that contains tables related to student’s informa-
tion. The first table, STUDENTS, contains a record for each student at the university. The
table, STUDENTS, consists of various attributes such as student_id, First_name and
student_stream.

The Table lists the various attributes in the STUDENTS table.


Student_id first_name last_name student_stream
S01 John Wilkins Computers
S01 Chris Burton Electronics
S01 Ken Wilkins Electronics

A unique Student_id number of a student is a primary key in the STUDENTS table. Your
cannot make the first of last name of a student a primary key because more than one
student can have the same first name and can have same stream.

Functional Dependency

A functional dependency is termed as a constraint between two sets of attributes of the


database. Functional dependency is represented by XY between two attributes, X and Y,
in a table. The functional dependency X Y implies that Y is functionally dependent on X.
The Table lists the various attributes in the EMPLOYEE table.

Employee_id Employee_name Employee_dept


K067263 John Sales
K067264 Chris Accounts
K067265 Ken Sales

In the table above , the various attributes of the EMPLOYEE are Employee_id,
Employee_name and Employee_dept. You can state that :
Employee_idemployee_name

EPITOME
SQL Server 2005 27

In the above representation the Employee_name attribute is functionally dependent on the


Employee_id. This implies that the name of an employee can be uniquely identified from the
id of the employee. However, you cannot uniquely identify the employee_id from the
employee_name column because more than one employee can have the same name.
However, each employee has a different value in the Employee_id column.

Functional dependencies are a type of constraints based on keys such as primary key or
foreign key. For a relation table R, a column Y is said to be functionally dependent on a
column X of the same table if each value of the column X is associated with only one value
of the column Y at a given time. All the columns in the relational table R should be functionally
dependent on X if the column X is a primary key.
If the columns X and Y are functionally dependent, the functional dependency can be repre-
sented as:
R.x  R.y
For example, consider the following functional dependency in a table.
Employee_id  Salary, the column Employee_id functionally determines the Salary column
because the salary of each employee is unique and remains same for an employee, each
time the name of the employee appears in the table.
A functional dependency represented by X  Y between two sets of attributes X and Y are
the subsets of R and is termed as trivial functional dependency if Y is a subset of X. For
example, Employee_id Project is a trivial functional dependency.
A functional dependency represented by X  Y between two sets of attributes X and Y are
subsets of r and is termed as non-trivial functional dependency if at least one of the attributes
of Y is not attributes of X. For example, Employee_ id  Salary is a non-trivial functional
dependency.

INFERENCE RULES AND ATTRIBUTE CLOSURE


Inference rules for functional dependencies define the new dependencies, which can exist
between two relations. The inference rules help to deduce these new dependencies from a
given set of functional dependencies, F. The set of dependencies, which cannot be specified,
is called the closure of F and is denoted by F+. Following are the six inference rules of
functional dependencies F:

EPITOME
SQL Server 2005 28

• IR1 (reflexive rule): If X 2 Y, then X  Y: This rule states that if X >=Y and two tuples
t1 and t2 exist in a relation instance r of relation R such that t1 [X] = t2 [X]. Now, t1 [X] =
t2 [X] because X>= Y. This implies that X  Y holds true in relation instance r of
relation R.
• IR2 (augmentation rule): { X  Y } |= XZ  YZ: This rule states that if X  Y holds
true in a relation instance r of R but XZ  YZ does not exist, then tuple t1 and t2 must
exist in relation R.
• IR3 (transitive rule): { X  Y, Y  Z } |= X  Y: This rule states that if both, X  Y
and Y  Z hold true in a relation r, then for any two tuples t1 and t2 in r, you must have
t1 [Y] = t2 [Y].
• IR4 (decomposition or projective rule): This rule states that if X  YZ holds true,
then X  Y and X  Z also hold true.
• IR5 (union or additive rule): This rule states that if X  Yand X  Z hold true, then
in the relation R, X  YZ also holds true.
• IR6 (pseudotransitive rule): This rule states that if X  Y and W Y  Z hold true,
then WX  Y also holds true.

Attribute Closure
To compute the closure J+ of a given set J of functional dependencies, you can apply the
inference rules until they stop producing new functional dependencies. You can test whether
a set of attributes, J is a super key or not, by finding the set of attributes, which are function-
ally determined by J. You can use the following algorithm to
compute the closure J+:
result : = J
while (changes to result) do
for each functional dependency in F do begin
if B c result; then result := result UY end
The above code assumes that J is a set of attributes and you can call the set of attributes
determined by a set F of functional dependencies. The closure of J under F is denoted by J+.

THE FIRST NORMAL FORM


A table is said to be in INF if the data in the table has an identifying key and does not include
repeating groups of data. To reduce data redundancy by using first normal form, you need to:
• Remove the duplicate columns from a table
• Create a separate table for related data and identify the primary key in the table

EPITOME
SQL Server 2005 29

According to the first normal form, a table should be atomic, which implies that no duplicate
data exists within the same row of a table. For example, consider the items table shown in
Table below.

The requirements of the first normal form are:


• Eliminate the multi-valued fields from the table
• Each column in the table must be atomic
• Each column in the table must have a key such as primary or foreign key
• Remove the repeated information from the table
Eliminate the Multi-valued Columns from the Table
The first requirement to apply INF to a table is to ensure that the table does not contain multi-
valued columns. For example, consider a Books table with attributes book_name,
book_author, book_ISBNno, book_price, book_publisher and book_category. Table below
lists the various attributes in the Books table.

Book_author Book_ISBNno Book_price Book_publisher Book_category


John Wilkins 8790478 35 ABC Sales
Chris Burton 8790388 25 PQR Accounts
Ken Wilkins 8790689 77 ABC Sales

In the Table above , since a book can have more than one author and also a book can be
included in different categories, therefore, columns that consist of multi-valued elements
should be removed from the table. Therefore, the Books table should contain book_ISBNno,
book_price and book_publisher columns.
Table below lists the various attributes of the Books table after the multi-valued elements are
removed.
The Books Table after the Multi-valued Elements are Removed
Book_ISBN no Book_price Book_publisher
8790478 35 ABC
8790388 25 PQR
8790689 77 ABC

EPITOME
SQL Server 2005 30

Table below lists the Books category table.

Book_ISBNno Book_category
8790478 Sales
8790388 Accounts
8790689 Sales

Each Column in the Table is Atomic


You need to ensure that each column in a table that is to be normalized is atomic. For
example, the author table can be divided into two columns, the first name and the last name
to make the table atomic.
Table below lists the various attributes in the author table.

Book_ISBNno First_name Last_name


8790478 John Wilkins
8790388 Chris Burton
8790689 Ken Wilkins

Each Column Must Have a Key


You can determine if each column in a table contains a unique value by verifying the keys in
the table. The various keys that can exist in a table are:
• Super key: It refers to one or more than one column that identifies a unique row
within a table.
• Candidate key: It refers to the super key consisting of minimum number of col-
umns required to identify a unique row in a table.
• Primary key: It refers to the candidate key required to uniquely identify a row in a
table.
• Alternate key: It refers to the candidate key, which is not selected as a primary
key.
• Foreign key: It refers to one or more than one column in a table that matches a
candidate key in the same or different table. You can link a row in a table to a row
in another table by using a foreign key.

EPITOME
SQL Server 2005 31

In the Books table, the super keys are Book_author and book_ISBNno. The super keys for
the author table are the combination of first_name and last_name. Similarly, for the catego-
ries table, the super key is category.
The primary key for the Books table is Book_ISBNno and the primary keys for the author
table are first_name and last_name. The primary key for the categories table is CategoryID.
To ensure that each row in the author table is unique, you can add the Author_city and
Author_zipcode columns in the primary key field.
Table below lists the various attributes in the author table.

Book_author Book_ISBNno Author_address Author_phoneno


John Wilkins 8790478 Houston 0098392978
Chris Burton 8790388 New York 008273827
Ken Wilkins 8790689 Denver 002632878

Eliminate the Repeating Values


To make a table compliant with INF, you need to eliminate the repeated values from the
table. For example, in the Books table the publisher column can contain same values for
different books. Therefore, to remove the repeating values you can make a separate table,
publisher, with attributes Publisher_id and Publisher_name. The publisher_id can be identi-
fied as the primary key for the publisher table.
Table below lists the various attributes in the Publisher table.
Publisher_id Publisher_name
P0240 ABC
P0240 LPQR
P0240 ABC

PARTIAL DEPENDENCY
In a table, a primary key consists of one or more than one column to uniquely identify each
row in the table. Partial dependency occurs when a row of a table is uniquely identified by
one column that constitutes a primary key without requiring the entire primary key to uniquely
identify the row. For example, consider a table ‘Stocks’ with attributes cust_id, stock and
stock_price.
EPITOME
SQL Server 2005 32

Table below lists the various attributes in the Stocks table.


Cust_id Stock stock_price
C012 Stkl 15
CO13 Stk2 10
C014 Stk3 20

In Table above, suppose cust_id and stock are identified as the primary key for the Stocks
table. However, the column stock_price is partially dependent on the primary key because
only the stock column determines the stock_price. Also, the values in the stock_price column
do not need the cust_id column to uniquely identify the price of the stocks. Therefore, you
need to make a separate table for the stock_price where the stock column is the primary key.
In the new table, partial dependency is eliminated because the stock_price column is entirely
dependent on the primary key.
Partial dependencies can only occur when more than one field constitutes the primary key. If
there is only one field in the primary identifier, then partial dependencies cannot occur.

THE SECOND NORMAL FORM


A table is in 2NF if the table satisfies all the conditions of the first normal form and does not
consist of any column that depends on only one part of the identified primary key. The 2NF is
based on the concept of full dependency.
To apply 2NF to a table you need to:
• Ensure that the table conforms to 1NF
• Create a separate table for the sets of values which can be applied to multiple records
• Relate the table with a foreign key
For example, consider the following table employee_project.

Emp_id Proj_no Proj_hrs Emp_name Proj_name Proj_loc


H76320 W36 08 Abe Payroll Houston
H76321 W37 02 Xyz Billing Denver

Table above conforms to 1NF since it does not contain repeated values and Emp_id and

EPITOME
SQL Server 2005 33

Proj_id are identified as the primary keys for the table. However, the table is not in 2NF because
all the columns of the table depend on only a part of the primary key, which comprises of
Emp_id and Proj_no, identified for the table. For example, the column Emp_name is dependent
on only the Emp_id and does not depend on the Proj_no part of the primary key. Similarly, the
Proj_name column is dependent on only the Proj_no column and not on the Emp_id primary
key.
Therefore, to apply 2NF to the employee_project table, you need to make a separate table for
columns that depend on only a part of the primary key. The new table should contain columns
that are dependent on the entire primary key identified for the table. The tables formed after
applying 2NF to the employee_project table are emp_proj table and emp table and proj table.
Table below lists the various attributes in the emp_proj table.
Emp_id Proj_no Proj_hrs
H76320 W36 08
H76321 W37 02

Table below lists the various attributes in the emp table.


Emp_id Emp_name
H76320 W36
H76321 W37

Table below lists the various attributes in the proj table.


Proj_no Proj_name Proj_loc
H76320 Payroll system Houston
H76321 Billing system Denver

Similarly, consider an ORDERS table that you need to normalize to 2NF:


Table below lists the various attributes in the ORDERS table.
Order_no Item_no Customer Item Qty Price
H76320 01 ABC Corp IT90 322 36$
H76320 02 ABC Corp IT91 564 45$
H76321 01 XYZ Corp IT92 736 12$
EPITOME
SQL Server 2005 34

In the Table above , Order_no and Item_no are identified as the primary keys for the table.
Also, the table conforms to INF since it does not contain repeated value. However, to apply
2NF to the ORDERS table, you need to create a separate table for the columns that do not
depend on either Order_no or Item_no primary key.
The tables, which are created after 2NF is applied to the ORDERS table, are order_cust
table and orders table.
Table below lists the various attributes in the order_cust table.
Order_no Customer
H76320 ABC Corp
H76321 XYZ Co

In the above order_cust table, the customer column is dependent on the primary key order_no.
Similarly, another table is created in which all the columns, Order_no, Item_no, Item, Qty
and Price are dependent on the primary keys, Order_no and Item _no. Table below lists the
various attributes in the orders table.

Order_no Item_no Item Qty Price


H76320 01 IT90 322 36$
H76320 02 IT91 564 45$
H76321 01 IT92 736 12$
Table lists the various attributes in the emp table.

TRANSITIVE DEPENDENCY
Transitive dependency occurs when a non-key column is uniquely identified by values in
another non-key column of a table. A non-key column of a table refers to the column that is
not identified as a key such as candidate or primary key. For example, consider a SUPPLIER
table with attributes supplier_id, supplier_status and supplier_address. The functional de-
pendencies that exist in the SUPPLIER table helps to understand the concept of transitive
dependency.
Table below lists the various attributes in the SUPPLIER table.

EPITOME
SQL Server 2005 35

Supplier id Supplier_status Supplier_address


SOI 10 Houston
S02 20 Denver
S03 30 Texas

In the above table, the following functional dependencies hold:


supplier_id  supplier_status
supplier_id  supplier_address
supplier_address  supplier_status
In the SUPPLIER table, the non-key column supplier_status is identified by both the primary
key supplier_id and non-key column supplier_address. Therefore, transitive dependency
exists in the above table. To eliminate transitive dependency, you need to apply 3NF to the
table.

THE THIRD NORMAL FORM


A table is said to be in third normal form or 3NF if the table satisfies the requirements of 2NF
and the non-key columns should be only functionally dependent on the primary key. The
third normal form is based on the concept of transitive dependency. A functional dependency,
A—>B, in a relation, R is a transitive dependency if the following conditions are satisfied:
• A column or set of columns, C, exists in the table that is neither the candidate key
of R nor the subset of any key of R.
• The functional dependencies AC and CB hold in the table.
For example, consider a Subject table with attributes such as Subject_no and Chapter_name.
Table below lists the various attributes in the Subject table.
Subject_no Chapter_name Instructor Department
H76320 Data structure ABC Computer
H76320 Communication XYZ Electronics

In the above table, Subject_no is the only candidate key. Therefore, the following functional
dependency exists for the subject table.
Subject_no  Chapter name
Subject_no  Instructor
Instructor  Department
EPITOME
SQL Server 2005 36

From the above functional dependencies, you can say that Subject_no  Department and
therefore the above table is in 2NF. However, the table is not in 3NF since Department is not
directly dependent on Subject_no. In the Subject table, the Department column is determined
by another non-key column, Instructor. Therefore, to apply 3NF to the Subject table, you
need to decompose the table in two tables, subject_inst table and instructor table.
Table below lists the various attributes in the subject_inst table.
Subject_no Subject_name Instructor
H76320 Data structure ABC
H76320 Advanced OS XYZ

Table below lists the various attributes in the instructor table.


Instructor Departm
ABC Computer
XYZ Electronics

BOYCE-CODD NORMAL FORM


Boyce-Codd Normal Form (BCNF) is stricter than the third normal form. In BCNF, the relation,
which is in BCNF is also present in Third Normal Form (3NF), but the relation present in 3NF
form is not necesnants:

Isarily be present in BCNF. In 3NF, if a relation has more than one candidate key then anomalies
can occur. In case of overlapping of candidate keys, 3NF is unable to stop the occurrence of
anomalies. This provides a base for BCNF and is based on the determinant concept. A
determinant is an attribute on which some other attribute is fully functionally dependent. The
following code shows the relation and determinants:
R(a,b,c,d)
a, c  b, d
a, d  b
In the above code the first determinant states that you can change the primary key of relation
R from a,b to a,c. After applying this change, you can still determine the non-key attributes
present in relation R. The second determinant indicates that a,d detetrmine b, but as a,d do
not determine all the non-key attributes of R, it cannot be considered as the primary key of R.
This implies that the first determinant is a candidate key, but the second determinant is not a
candidate key, hence this relation is not in BCNF but is in 3NF.
EPITOME
SQL Server 2005 37

To be in BCNF, every determinant of the relation has to be a candidate key. The definition of
BCNF specifies that a relation schema R is in BCNF if a non-trivial functional dependency
X A holds in R, then X is a super-key of R.

DECOMPOSITION
The relational database design algorithm start with a single universal relation schema, R =
{A1, A2, A3, ...... An}, which includes all the attributes of a database. The database designers
specify the set, F of functional dependencies, which holds true for all the attributes of R. This
set, F of functional dependencies is also provided to the design algorithms. With the help of
functional dependencies, these algorithms decompose the universal relation schema, R into
a set of relation schemas, D = {R1 ........, Rm}, which becomes the relational database schema.
In this case, D is referred a decomposition of R. The properties of decomposition are as
follows:
• Attribute preservation: It involves preserving all the attributes of the relation, which
is being decomposed by the design algorithms. While decomposing a relation, you
need to make sure that each attribute in R exists in at least one relation schema, Ri
while decomposing the relation.
• Lossless-join decomposition: It ensures that the join remains in the same relation,
as it was before the decomposition of the relation. The decomposition of the relation
R into several relations, RI, R2, ..., Rn is called a lossless-join decomposition, if the
relation R is the natural join of the relations RI, R2, ..., Rn. To test whether a given
decomposition is a lossless join for a given set F of functional dependencies, you
need to decompose the relation, R into RI and R2. If the decomposition of the
relation R is lossless join, then one of the following conditions has to be true:
– (Ri intersection RI) -» (R1-R2) and
– {Ri intersection RI) -»(R2 - R1)
• Dependency preservation: It states that if each functional dependency X  Y,
specified in F, either directly appears in one of the relation schemas Ri in the
decomposition D or is inferred from the dependencies that appear in the relation,
R;. The need of dependency preservation arises because each dependency in F
represents a constraint on the database. When a decomposition does not preserve
the dependency, then some dependency can be lost in the decomposition. You
can check for a lost dependency by creating a join of two or more relations in a

EPITOME
SQL Server 2005 38

decomposition to get a relation, which includes all the left and right-hand side attributes of
the lost dependency. Then, check whether or not the dependency is preserved on
the result of join.

MULTI-VALUED DEPENDENCY
An entity in E-R model can have multi-valued attributes. A multi-valued attribute is one that
does not have a single value but a collection of values. If you have to store such an entity in
one relation, you will have to repeat all the information other than the multi- valued attribute
value. In this way, the same instance of the entity will have many tuples. The situation becomes
much inferior if any entity has more than one multi-valued attributes. The multi-valued
dependency gives a solution to the problem of more than one multi-valued attributes. entity
will have many tuples. The situation becomes much inferior if any entity has more than one
multi-valued attributes. The multi-valued dependency gives a solution to the problem of more
than one multi-valued attributes.
MVD: Let R (X, Y, Z) be a relation. The multi-valued dependency XY can hold for relation
R if for the given set of value for attribute X there is a set of zero or more associated values
for the set of attribute Y. The values of Y only depend on X values and these have no
dependence on the set of attributes Z.
Suppose a Students table, which has Studjname, Qualifications and Languages as attributes.
In the relation a student can have more than one qualification (Stud_idQualifications)
and know more than one language (Stud_id Languages). This relation shows duplication
of data and inconsistency. You can decompose the Students relation into two relations having
attributes Stud_id, Qualifications and Stud_id , Languages.
In this example, if there were dependency between Qualifications and Languages attributes
then Student relation would not have MVD and cannot be decomposed into two relations.

THE FOURTH NORMAL FORM


The fourth and fifth normal forms depend on multi-valued facts and composite keys. The
multi-valued facts correspond to many-to-many relationship and many-to-one relationship.
In the fourth and fifth normal forms, you need to minimise the number of columns in a com-
posite key.
In the fourth normal form, you must ensure that a record satisfies the third normal form and
does not contain two or more independent multi-valued facts about an entity. For example,
consider a table, R, with attributes employees, skills and languages. Since in this table, an

EPITOME
SQL Server 2005 39

employee may have various skills and may know various languages, therefore, the table has
two many-to-many relationships. Under the fourth normal form, the two many-to-many
relationships are not represented in a single row and you need to split R into t\v,o tables.
Therefore, the table, R, is split into a table with attributes, employees and skill and another
table with attributes, employees and language. A relation is considered to be as the fourth
normal form if each defined table contains not more than one multi-valued dependency per
key attribute.
For example, consider an Instructor table shown :
MID Database Instructor
1 Access Miller
8 Access Smith

MID Database Instructor


1 Access John
1 DB2 Miller
1 DB2 John
8 Oracle Smith

The redundancy of data is easily perceived. For each MID there are defined multiple on X
value values of Instructors and Database. This is a perfect example of a multi-valued depen-
dency. Table below shows the fourth normal form of instructor table.
MID DATA Table MID Instructor Table
MID Database MID Database
1 Access 1 Miller
8 Access 1 John
1 DB2 8 Smith
8 Oracle

EPITOME
SQL Server 2005 40

JOIN DEPENDENCY AND THE FIFTH NORMAL FORM


The fifth normal form (5NF) is based on join dependency. Join dependency implies that after
a table is decomposed into three or more tables, the tables can be joined to form the original
table. A table is in 5NF if the table cannot have lossless decomposition into smaller tables. A
lossless decomposition implies that after a relational table is decomposed into smaller tables,
the joining of the tables results in exactly the same relation table, which was decomposed. If
an instance is added to a table, which is not in 5NF, it gives spurious results when the tables
are decomposed and then rejoined.
Table below lists the various attributes of Instructor-MID-Location table.
Instructor MID Location
Smith 1 New York
Smith 2 Chicago
Jones 1 Chicago

If you were to add the MID 2 to New York, you would have to add a line to the table for each
instructor located in New York. If Jones were certified for MID 2 and could travel to New York,
you would have to add two lines to reflect this.
Table below shows the instructor-MID-Location table. It is decomposed into the fifth normal
form.
Instructor-Seminar Seminar-Location Instructor-Location
Table Table Table
Instructor MID MID Location Instructor Location
Smith 1 1 New York Smith New York
Smith 2 1 Chicago Smith Chicago
Jones 1 2 Chicago Jones Chicago

CENTRALISED VERSUS DECENTRALISED DATABASE DESIGN


Centralised Database Systems
Centralised database system provides a way to control data of an organization from a
centralised location. In centralised database design, data of the organization is stored at a
single place. The control of the database is not divided among several users at different
locations. All the users who want to use the data access or retrieve data from the centralised
location. The following figure shows the diagram for a centralised database system.

EPITOME
SQL Server 2005 41

Workstation 1 Workstation 2

Centralised
Database

Workstation 4 Workstation 3

There are several advantages of using centralised database system. These advantages are:
• It provides control over the data of the organization.
• It provides easier way to control the information of the organization using well-
known technologies and experts.
• Centralized system contains easier interfaces to interact with its software and hard-
ware.
• Report generation is easier as whole data of the organization is located at a single
place.
Along with the advantages there are certain disadvantages also that are related to the
centralised system. These disadvantages are:
• A huge amount of money is required to establish and maintain a centralized system.
• Speed of accessing the information in the centralized system is slow because only
one system processes all the information of the organization.
• Centralized system provides less security to the information due to the use of one
centralized computer. This means that if the centralized computer fails, the com-
plete system will fail.

Decentralised Systems
In decentralised system, the data of the organization is not stored at a single location. There

EPITOME
SQL Server 2005 42

is no centralised computer to control the data. The control of the data is distributed among
several users and is individually handled by them. Decentralised system also provides an
easy way to access data from the tables. Information in a decentralised system is more
service oriented to an individual user. The following figure shows the diagram for a
decentralised database system.

Database Database

Workstation 1 Workstation 2

ORGANIZATION

Workstation 4 Workstation 3

Database Database

There are several advantages of using a decentralized database system. These advantages
are:
• Initial cost and maintenance cost for starting a decentralized system is less.
• It provides processing and controlling of information on individual computers
of an organization, thus increasing control at the local level.
• It provides an easier way to involve new users in the IT system of the organization.
• The failure of a individual system’does not result in the failure of the entire database
system.
There are certain disadvantages also that are related to the decentralized database system.
These disadvantages are:
• In a decentralized system, it is difficult to control the information of the organization
as the control is distributed among several users.

EPITOME
SQL Server 2005 43

• A decentralized control over the data of the organization results in the lack of
consistency.
• In a decentralized system, technologies used by users are not common, which
results in inefficient information and lack of standardization.
• There is a lot of wastage of money and efforts due to duplication of information.
• Use of decentralized database systems results in redundancy of data as same
data may be stored at different places.
Centralized versus Decentralized Systems
The failure of the centralized system will cause total loss -of the data. In contrast to this, the
failure of a local computer in a decentralized system does not result in the total failure of the
system. The processing units in case of centralized1 systems are expensive whereas the
processing units required for decentralized systems does not cost much as data is stored at
user’s local computer. Data is stored and managed at a single place in case of centralized
system that accounts for the standardization of the stored data whereas in case of decentral-
ized systems different users using different techniques manage data individually. Therefore,
the data in decentralized system lacks uniformity and consistency.
In a centralized database design, the different objects such as tables and views
within the data base are linked together. As a result, data can be exchanged between these
database objects. However, in case of decentralized database design the different Database
objects are not linked. Therefore, exchange of data is not possible in decentralized database
design. In centralized database design, there is no redundancy. In this type of database
design all users use same data. On the other hand, decentralized database design allows
redundancy. The interaction between different objects in a decentralized database design is
more difficult as compared to the database object interaction in centralized database.
In centralized database design, the process of retrieving information is a single step process
in centralized database design whereas in decentralized database design, the process of
retrieving information includes multiple steps. In decentralized database design, ownership
of data can be defined in more efficient manner as compared to the sscentralized database
design. In the centralized database design, the management can obtain all the data related
to decision-making, planning and control but the management could not obtain the data in
decentralized database design. The centralized database design supports data integration
whereas decentralized database design does not allow data integration.

EPITOME
SQL Server 2005 44

THE STRUCTURED QUERY LANGUAGE (SQL)

The Structured Query Language is a standardized set of statements which can be used in all
the RDBMS. The SQL statements can be classified widely in three categories – DDL (Data
Definition Language), DML (Data Manipulation Language) and DCL (Data Control Language).
The DDL contains all the statements which are used to define databases and database
objects for e.g. CREATE DATABASE, CREATE TABLE etc. The DML contains all the state-
ments which are used to manipulate the data stored in the databases for e.g. INSERT,
UPDATE and DELETE etc. The DCL contains all the statements which are used to control
the flow of data among the various users of the databases. All the statements related to the
permissions and security of the database like GRANT, DENY, REVOKE etc. fall under this
category.

SQL Server data types

All the data values of a column in a table must be of the same data type. Transact-SQL uses
different data types, which can be categorized in the following way:

 Numeric data types

 String data types

 Date and time data types

EPITOME
SQL Server 2005 45
Numeric data types

Data type Explanation


INT Represents integer values, which can be stored in 4 bytes.
Represents integer values, which can be stored in 2 bytes
SMALLINT
(32768 to 32767)
TINYINT Represents non-negative integer values, which can be stored
in 1 byte (0 to 255)
DECIMAL(p[, s]) Describes fixed point values. The argument p (precision)
specifies the total number of digits with assumed decimal
points s (scale) digits from the right. DECIMAL values are
stored depending on the values of p in 2 to 17 bytes.
NUMERIC(p[, s]) is the synonym for DECIMAL.
REAL Used for floating point values. The range of positive values is
approximately from 2.23E-308 through 1.79E+308. The range
of negative values is approximately from -2.23E-308 through -
1.79E+308.
FLOAT(p) Represents floating point numbers like REAL. The p defines
the precision with p<25 as single precision (4 bytes) and
p>=25 as double precision (8 bytes)
MONEY Used to represent monetary values. MONEY values
correspond to 8 byte DECIMAL values and are rounded to
four digits after the decimal point.
SMALLMONEY Corresponds to the data type MONEY but is stored in 4 bytes.

String data types


Data type Explanation
CHAR([n]) Represents a fixed length string of n number of characters. The
maximum value of n is 8000. If n is omitted, the length of the string
is assumed to be 1.
VARCHAR([n]) Describes a string with varying length (0<n<=8000). The values for
the VARCHAR data type are stored in the actual length.
NCHAR([n]) The NCHAR data type stores fixed length Unicode character data.
NVARCHAR([n]) The main difference between the CHAR and the NCHAR data types

EPITOME
SQL Server 2005 46

Data type Explanation

is that each NCHAR character is stored in 2 bytes while the CHAR


characters are stored in 1 byte. The maximum number of characters
for NCHAR is 4000.
NVARCHAR([n]) The NVARCHAR data types stores Unicode characters of varying
length. The man difference between the VARCHAR and
NVARCHAR data types is that the VARCHAR characters are stored
in 1 byte while the NVARCHAR characters are stored in 2 bytes.

Date and time data types

Data type Explanation


DATETIME Specifies a date and time with each value being stored as
an integer of 4 bytes. (January 1, 1753 to December 31,
9999)

SMALLDATETIME Specifies a date and time with each value being stored as
an integer of 4 bytes. (January 1, 1950 to June 6, 2079)

Database Objects
Tables
Tables are database objects which are used to store data. A table consists of rows and
columns. The columns are also known as attributes. The rows also known as record are a
group of related attributes. The columns of a table are defined of a certain data type. The
tables are created using the CREATE TABLE statement. The general syntax of the CREATE
TABLE statement is:
CREATE TABLE table_name
(
column_name1 type [IDENTITY (seed, increment) column_constraint,
column_name2 type [IDENTITY (seed, increment) column_constraint,
...
)
Where table_name is the name of the table. A column with the IDENTITY property allows
only integer values, which are usually implicitly assigned by the system. Each value which
should be inserted in the column is calculated by incrementing the last inserted value of the

EPITOME
SQL Server 2005 47

column. Therefore, the definition of a column with the IDENTITY property contains an initial
and an increment. The default value for the initial and the increment are both 1. The following
restrictions apply to the IDENTITY property:
 The column must be numeric. For NUMERIC or DECIMAL data types, the number
to the right of the decimal should be zero.
 There can be at most one column in the table with the IDENTITY property.
 The column with this property does not allow NULL values.
CREATE TABLE AND COLUMN CONSTRAINTS
One of the most important specifications made during creation of the tables are the column
constraints. These constraints also known as the integrity constraints are used to check
the modifications or insertion of data in the tables, thereby maintaining the integrity of the
data in the table. The most important benefits of handling integrity constraints by the RDBMS
are:
 Increased reliability of data.
 Reduced programming time.
 Simple maintenance
There are two groups of integrity constraints handled by an RDBMS:
 Declarative integrity constraints (included in the table definition)
 Procedural integrity constraints (handled by triggers)
There are five declarative integrity constraints:
 Primary key
 Foreign key
 Unique
 Default
 Check
 Not null

The PRIMARY KEY


The primary key constraint is used to specify that the values of this column for each row are
different and they cannot be NULL. Apart from this the primary key enables us to establish
relationship among the tables.

EPITOME
SQL Server 2005 48

CREATE TABLE emp


(
empno INT CONSTRAINT emp_pk PRIMARY KEY,
ename VARCHAR(10),
sal MONEY
)
The above statement creates a table named emp with the empno field as the PRIMARY
KEY. As shown above we can provide a name for the constraint using the CONSTRAINT
clause. Here the integrity constraint is a column-level constraint as it is specified along with
the column definition. The same table can be also created with the following statement,
where the integrity constraint is being defined as column-level constraint and is defined after
the definitions of all the columns of the table.
CREATE TABLE emp
(
empno INT,
ename VARCHAR(10),
sal MONEY,
CONSTRAINT emp_pk PRIMARY KEY(empno)
)
The second form is mainly used while defining multiple columns as primary key as it is done
in the following example:
CREATE TABLE student
(
roll INT,
batch VARCHAR(10),
sname VARCHAR(10),
CONSTRAINT std_pk PRIMARY KEY(roll,batch)
)
There can be only one primary key in a table.

The Foreign Key


The foreign key is a column or group of columns in one table that contains values that match
the primary key values of another table. Each foreign key is defined using the REFERENCES
clause with or without combining with the FOREIGN KEY clause. The table that contains the
foreign key is called the referencing table and the corresponding primary key table is called
the target or referenced table.
EPITOME
SQL Server 2005 49

CREATE TABLE pay


(
empno INT CONSTRAINT pay_fk_emp REFERENCES emp(empno),
hra money,
da MONEY
)
The above example can also be written by defining the empno column as a table level
constraint with the use of the FOREIGN KEY clause.
CREATE TABLE pay
(
empno INT,
hra money,
da MONEY,
CONSTRAINT pay_fk_emp FOREIGN KEY(empno) REFERENCES emp(empno)
)
In the above examples, the pay_fk_emp constraint specifies that the emp table as the
target table and its column empno as the corresponding primary key of the same name in
the referencing table pay. This means that for each value to be inserted in the empno column
of the pay table it will always refer to the empno column of the emp table and the attempted
value will be inserted only if it exists in the empno column of the emp table. The maximum
number of foreign key constraints in a table is 63.

The UNIQUE constraint


The UNIQUE constraint specifies that the values in the column(s) are unique, including the
NULL values. Just as with any other value with a unique constraint, if NULL values are
allowed in a column with a UNIQUE constraint, there can be at the most only one row with
the NULL value. Any attempt to insert an existing value to the column will be rejected by SQL
Server.
CREATE TABLE dept
(
deptno INT,
dname VARCHAR(10) UNIQUE,
location VARCHAR(10)
)
The same can also be achieved as follows:
CREATE TABLE dept
EPITOME
SQL Server 2005 50

(
deptno INT,
dname VARCHAR(10),
location VARCHAR(10),
UNIQUE(dname)
)

The DEFAULT constraint


The DEFAULT constraint is used to specify a default value for the column. This means
whenever a new row is inserted in the table without any value for the column, the DEFAULT
value will be used for that column in the newly inserted row. The value supplied with the
DEFAULT constraint can be a constant, a system function or NULL.

CREATE TABLE student


(
roll INT,
batch VARCHAR(10),
sname VARCHAR(10),
adm_date DATETIME DEFAULT GETDATE()
)

The CHECK constraint


The check constraint is used to impose certain validating criteria to check for the validity of
the values in the columns. The check constraint ensures the insertion of only those values in
the column which satisfies the corresponding condition.
CREATE TABLE student
(
roll INT,
batch VARCHAR(10),
sname VARCHAR(10),
adm_date DATETIME,
gender CHAR CHECK (gender in (‘M’,‘F’))
)
In the above example, the gender column will accept only those values which is either ‘M’ or
‘F’ and will reject all attempts to insert any value other than these.

EPITOME
SQL Server 2005 51

The NOT NULL constraint


The NOT NULL constraint is used to prevent the insertion of null values in the column.
CREATE TABLE student
(
roll INT,
batch VARCHAR(10),
sname VARCHAR(10) NOT NULL,
adm_date DATETIME,
gender CHAR
)
In the above example, the NOT NULL constraint in the sname column will look into it that we
specify a value other than null for the sname column for each row.
Altering table definition
Once the table has been defined we may have the necessity of making a few changes to the
table definition like adding a new column, adding a constraint to a column, deleting a column
etc. This can be done using the ALTER TABLE statement. The general syntax of the ALTER
TABLE statement is:
ALTER TABLE table_name
[WITH CHECK | NOCHECK]
ADD col_name1 type [NULL | IDENTITY] [, col_name2 type [NULL | IDENTITY]...]
DROP COLUMN col_name1 [, col_name2...]
ALTER COLUMN col_name1 type [NULL | IDENTITY] [, col_name2 type [NULL |
IDENTITY]...]
ADD table_constraint
DROP table_constraint
Let us consider the following example:
CREATE TABLE emp
(
empno INT,
ename VARCHAR(10),
)
To add two new columns named gender and deptno
ALTER TABLE emp ADD gender CHAR
ALTER TABLE emp ADD gender Char
The above two statements can also be written as
ALTER TABLE emp ADD deptno INT, gender CHAR
EPITOME
SQL Server 2005 52

To define the deptno column as foreign key to the deptno column of the dept table
ALTER TABLE emp ADD CONSTRAINT emp_fk_dept FOREIGN KEY(deptno)
REFERENCES dept(deptno)
To add a check constraint to the column gender without validating the existing values
ALTER TABLE emp WITH NOCHECK ADD CONSTRAINT check_gender
CHECK(gender IN (‘M’,’F’))
To disable the above constraint
ALTER TABLE emp NOCHECK CONSTRAINT check_gender
To enable an existing constraint
ALTER TABLE emp CHECK CONSTRAINT check_gender
To delete a column with a constraint first we have to drop the constraint and then the table
ALTER TABLE emp DROP check_gender
ALTER TABLE emp DROP COLUMN gender
To add a primary key constraint to a nullable column, first we have to redefine the column as
not null
ALTER TABLE emp ALTER COLUMN empno INT NOT NULL
ALTER TABLE emp ADD CONSTRAINT emp_pf PRIMARY KEY(empno)
To add a column with default values and fill the new column with the default value for the
existing rows. If the values clause is omitted, the existing column contains null in the existing
rows.
ALTER TABLE emp ADD doj DATETIME CONSTRAINT doj_default DEFAULT
GETDATE() WITH VALUES

To disable all foreign key and check constraints


ALTER TABLE emp NOCHECK CONSTRAINT ALL

Deleting Tables
Tables can be deleted using the statement
DROP TABLE table_name1 [, table_name2 …]

All data, indexes, triggers belonging to the removed table are also dropped. In contrast, all
views that are defined using the dropped table are not removed. (NOTE: In case, we want to
delete a table which is being referenced by some other table, we must delete all the referencing
tables before deleting the target table.)

EPITOME
SQL Server 2005 53

Inserting records in a table


The insert statement inserts rows (or parts of them) into a table. It has two different forms:
INSERT INTO table_name [(column-list)]
{DEFAULT VALUES | VALUES (DEFAULT | expression-list)}
And
INSERT INTO table_name [(column-list)] {select_statement | execute_statement}
Using the first form, exactly one row or parts of it is inserted into the table. The DEFAULT
VALUES option inserts the default values for all the columns in the table. The columns,
which do not have any default value, will be filled with NULL. If we want to specify values
other than the default values, we can do so using the VALUES option. We can still use the
DEFAULT option to insert the default values of selected columns. If a certain column is
neither nullable nor has a default value, and if we do not specify any explicit value for the
column, the insert statement fails. We can opt between insert a record with values for all the
columns of the tables or partially for certain columns. Partial insertion can be done by specifying
the names of the required columns following the table name in the INSERT statement. The
second form inserts the resulting set of rows from the SELECT statement or from the stored
procedure, which is executed using the EXECUTE statement.
With both forms, every inserted value must have the compatible data type as the corre-
sponding column of the table. To do so, all character-based values and the date/time data
must be enclosed in single-quotes, while all numeric values need no such enclosing. Let us
consider the following table:
CREATE TABLE emp
(
empno INT IDENTITY(1,1) PRIMARY KEY,
ename VARCHAR(10),
hiredate DATETIME DEFAULT GETDATE(),
gender CHAR CHECK(gender IN (‘m’,’f’)) DEFAULT ‘m’
)

To insert a row with values for all the columns


INSERT INTO emp VALUES(‘Jyoti’, ’05/29/2001', ‘f’)
To insert a row with default values for certain columns
INSERT INTO emp VALUES(‘Kabir’, ’11/24/1999', DEFAULT)

To insert a row with default values for all the columns


INSERT INTO emp DEFAULT VALUES
EPITOME
SQL Server 2005 54

To insert NULL values


INSERT INTO emp VALUES(‘Vikas’, NULL, ‘f’)

To insert a row by specifying values for partial columns


INSERT INTO emp(ename, gender) VALUES(‘Rekha’, ‘f’)
In all the above examples, we can see that we haven’t provided any value for the empno
column. This is because we have defined the column with the IDENTITY property. The value
for a column with the IDENTITY property is automatically supplied with a value by SQL
Server. If we want to provide an explicit value for an IDENTITY column, we have to set the
IDENTITY_INSERT to ON for the desired table. Moreover the name of the IDENTITY column
has to be specified in the column-list in the INSERT statement.

SET IDENTITY_INSERT emp ON


INSERT INTO emp(empno, ename) VALUES(6, ‘Rahul’)

After inserting the required value for the identity column we can reset IDENTITY_INSERT to
OFF for automatic insertion of values. SQL Server will continue providing values for the
identity column from the highest value in that column.

SET IDENTITY_INSERT emp OFF


Viewing records from a table
The SELECT statement enables us to retrieve records from the tables. The set of rows
returned by a SELECT statement is known as result set. The general syntax of select state-
ment is:
SELECT [ ALL | DISTINCT ] * | column_list
[INTO new_table_]
FROM table | view
[WHERE condition]
[GROUP BY expression]
[HAVING condition]
[ORDER BY expression [ASC | DESC]]
A select statement can retrieve either certain columns or certain rows from a table. The first
operation is called projection and the second form is called selection. A select statement can
use the combination of both projection and selection.
Let us consider the following emp table for the illustration of the SELECT statement

EPITOME
SQL Server 2005 55

Field name Data type Description


empno int employee number
ename varchar(10) name of the employee
hiredate datetime date of joining
sal money basic salary of the employee
deptno int department number of the employee

To display the values of all the columns in each row


Select * from emp

To display only selected columns (for e.g. empno, ename and hiredate)
Select empno, ename, hiredate from emp

To display only the distinct department numbers in the table


Select distinct deptno from emp

Conditional retrieval of information


WHERE CLAUSE
The simplest form of the SELECT statement, described in the previous section, is not very
useful for queries. Often, it is necessary to define one or more conditions that limit the se-
lected rows. The WHERE clause specifies a Boolean expression (an expression that returns
a value of true or false) that is tested for each row to be returned. If the expression is true,
then the row is returned; if it is false, it is discarded .
E.g. 1 Get the name and number of all departments located in Guwahati.
SELECT dept_name, dept_no
FROM department
WHERE location=’Guwahati

E.g. 2 Get the last and first names for all employees with employee number  15000.
SELECT emp_lname, emp_fname
FROM employee
WHERE emp_no>=15000
E.g.3 Get the project name for all projects with budget>60000 £. The current rate of ex
change is 0.51 £ per $1.

EPITOME
SQL Server 2005 56

SELECT project_name
FROM project
WHERE budget*0.51>60000
BOOLEAN OPERATORS
WHERE clause conditions can either be simple or contain multiple conditions. Multiple
conditions can be built using the Boolean operators AND, OR, and NOT

E.g.1 Get employee and project numbers of all clerks that work on project p2.
SELECT emp_no, project_no
FROM works_no
WHERE project-no= ‘p2’
AND job= ‘clerk’
E.g.2 Get employee numbers for all employees that work either for project p1 or project p2
for (or both).
SELECT project_no,emp_no
FROM works_on
WHERE project_no=‘p1’
OR project_no=‘p2’

The WHERE clause may include any number of the same or different Boolean
operations. The NOT operation has the highest priority, AND is evaluated next, and the OR
operation has the lowest priority.
E.g.1 SELECT * FROM employee
WHERE emp_no=25348 AND emp_lname= ‘Smith’
OR emp_fname= ‘Matthew’ AND dept_no= ‘d1’

SELECT * FROM employee


WHERE ((emp_no=25348 AND emp_lname= ‘Smith’)
OR emp_fname= ‘Matthew’) AND dept_no= ‘d1’

The first SELECT statement the system evaluates both AND operators first and
then the OR operator is evaluated. In the second SELECT statement all expressions within
parentheses being executed first, in sequence from left to right. As you can see, the first
statement returned one row while the second one returned zero rows.

EPITOME
SQL Server 2005 57

E.g.2 Get employee numbers and first names of all employees who do not belong to the
department d2.
SELECT emp_no, emp_lname
FROM employee
WHERE NOT dept-no= ‘d2’
In this case the NOT operator can be replaced by the comparison operator <>(not equal).
E.g.3 SELECT emp_no,emp_lname
FROM employee
WHERE dept_no <> ‘d2’

IN and BETWEEN Operators


An IN operator allows the specification of two or more expressions, to be used for a query
search.
E.g.1 Get all the columns for employee whose employee numbers equal either 29346 or
28559 or 25348.
SELECT * FORM employee
WHERE emp_no IN (29346,2855,25348)

An IN operator is equivalent to a series of conditions, connected with one or more


OR operators. The IN operator can be used together with the Boolean operator Not.

E.g.2 Get all columns for employees whose employee numbers are neither 10102 nor
9031.
SELECT * FROM employee
WHERE emp_no NOT IN (1012, 9031)

The BETWEEN operator specifies a range, which determines the lower and upper bounds
of qualifying values.

E.g.1 Get the names and budgets for all projects where the budget is in the range between
$95,000 and $ 120,000 inclusive.
SELECT project_name, budget FROM project
WHERE budget BETWEEN 95000 AND 120000

E.g.2 SELECT project_name, budget


FROM project
WHERE budget>=95000 AND budget <=120000
EPITOME
SQL Server 2005 58

Like the BETWEEN operator, the NOT BETWEEN operator can be used to search
for column values that do not fall within the specified range.
E.g.1 Get employee numbers of all analysts who did not enter their project in 1998.
SELECT emp_no FROM works_on
WHERE job= ‘analyst’
AND enter_date NOT BETWEEN ’01/01/1998’ AND ’12/31/1998
Queries Involving Null Values
A NULL in the CREATE TABLE or ALTER TABLE statement specifies that a special value
called NULL is allowed in the column.
All comparisons with NULL values will return false. To retrieve the rows with NULL
values in the column, Transact-SQL includes the operator feature IS [NOT] NULL.

E.g.1 Get employee numbers and corresponding project numbers for employees with un-
known jobs who work on project p2.
SELECT emp_no, project p2
FROM works_on
WHERE project_no= ‘p2’
AND job IS NULL

E.g.2 Shows a syntactically correct, but logically incorrect, usage of NULL


SELECT project_no, job FROM works_on
WHERE JOB<>NULL

LIKE OPERATOR
The LIKE operator compares column values with a specified format. For example, the following
example is used the names of all employees whose last name begins with ‘S’.
SELECT emp_fname, emp_lname FROM Employee
WHERE emp_lname LIKE ‘S%”
‘%’ is a wildcard that represents more than one character. Other wild card operators used
include ‘_’ which represents single character, [] represents any single character in the speci-
fied range, [^] represents any character not within the specified range.
Example: the following query gets all records for the employees whose last name contains
‘h’ as the second character.
SELECT * FROM Employee
WHERE emp_lname LIKE ‘_h%’
Consider another example
EPITOME
SQL Server 2005 59

SELECT title, price FROM books


WHERE title LIKE ‘p[sc]%’
Which erases all records from books table where the title starts with ‘p’ followed by either ‘s’
or ‘c’. The above query can be re written as
SELECT title, price FROM books
WHERE title LIKE ‘p[^c]%’
To get those records where the title starts with ‘p’ but do not contain ‘c’ as the second character.

Grouping Results
The GROUP BY clause organizes the summarized data into groups using the aggregate
functions and HAVING clause. Consider the following example that returns the maximum
price for each type of book from the books table
SELECT type, “Max Price”=MAX(price) FROM books
GROUP BY type
The HAVING keyword can be used to select rows from the intermediate result set. Consider
the following example that displays the type and the average price of those types where the
average price is greater than 20 as
SELECT type, “Average Price”= AVG(price) FROM books
GROUP BY type
HAVING AVG(price) >20
Computing Results: The COMPUTE and COMPUTE BY Clause
The COMPUTE Clause is used to generate summarized reports with the help of Aggregate
functions. For example: the following query will contain the summarized report of the result
set returned by the SELECT statement.
SELECT type, price FROM books
ORDER BY type
COMPUTE AVG(price) BY type
The average price of all types can be obtained by modifying the above query as
SELECT type, price FROM books
ORDER BY type
COMPUTE AVG(price) BY type
COMPUTE AVG(price)
Sub Queries
Sub queries are SELECT Statements that are nested within the WHERE Clause of another
SELECT Statement. The first SELECT statement is called the outer query and the second
SELECT Statement is called the inner query. The inner query will be evaluated first and the
EPITOME
SQL Server 2005 60

outer query will be evaluated on the basis of the results of the inner query. Sub Queries are
of two types:
 Simple
 Co Related
Simple sub queries
In simple subqueries, the inner query will be evaluated only once. A co-related subquery
differs from a simple sub query as it’s value will depend on a variable of the outer query.
Example: Get the name of those employees who work in the department ‘technical’
SELECT emp_fname, emp_lname FROM emp
WHERE dept_no = (SELECT dept_no FROM dept WHERE
dept_name=‘technical’)
Consider another example to get the name of those employees who draw pay higher than
the average pay of the technical dept.
SELECT emp_fname, emp_lname FROM emp
WHERE pay > (SELECT AVG(pay) FROM emp WHERE dept_name= ‘techni-
cal’)
The IN operator is used in a sub query if the inner query returns a set of values and not a
single values. Consider the example where the query gets the records of employees whose
departments are located at ‘Ghy’
SELECT * FROM emp
WHERE dept_no IN (SELECT dept_no FROM dept WHERE city = ‘Ghy’)
SUB-QUERIES (WITH EXITS)
Sub queries, which use with the exit clause, always return data in terms of time or false. It
checks for the existence of data according to the condition specified in the nested query and
passes it to the outer query to produce the result.

E.g. To select the publishers name from publishers table if the city is ‘paris’.
SELECT pub_name FROM publishers
WHERE EXISTS (SELECT * FROM publishers WHERE city=‘paris’)
CO-RELATED SUB-QUERY
A corelated sub query can be defined as a query that depends on the outer query for its
evaluation.

E.g. Find the records from the sales table where the qty is less than the avg qty of sales
for that titles.

EPITOME
SQL Server 2005 61

SELECT sales, title_id FROM sale A1


WHERE qty < (SELECT AVG(qty) FROM sales A2 WHERE
A1.titl_id=A2.title_id)
Implementing Joins
Transact-SQL provides the join operator, which allows retrieval of data from more
than one table. This operator is probably the most important operator for relational database
systems, because it allows data to be spread over many tables and thus achieves a vital
property of database systems – nonredundant data.
The various types of joins are:
 Unrestricted join
 Natural join
 Equi join
 Self join
 Outer join

Unrestricted Join:
A join that includes more than one table without any condition in the WHERE clause is called
an unrestricted join.
CO-RELATED SUB-QUERY
A corelated sub query can be defined as a query that depends on the outer query for its
evaluation.

E.g. Find the records from the sales table where the qty is less than the avg qty of sales
for that titles.
SELECT sales, title_id FROM sale A1
WHERE qty < (SELECT AVG(qty) FROM sales A2 WHERE
A1.titl_id=A2.title_id)
Implementing Joins
Transact-SQL provides the join operator, which allows retrieval of data from more
than one table. This operator is probably the most important operator for relational database
systems, because it allows data to be spread over many tables and thus achieves a vital
property of database systems – nonredundant data.
The various types of joins are:
 Unrestricted join
 Natural join
 Equi join
EPITOME
SQL Server 2005 62

 Self join
 Outer join

Unrestricted Join:
A join that includes more than one table without any condition in the WHERE clause is called
an unrestricted join.

E.g. SELECT title


FORM title, publishers
Where the FROM clause defines the tables from which the data is to be retrieved.
Natural Join:
A join that restricts the redundant column data from the result set is known as a natural join.

E.g. Consider the following example where the title name and the publisher of the book
are selected from the titles and publishers tables are displayed.
SELECT t.title, p.pub_name
FROM titles t, publishers p
WHERE t.pub_di=p.pub_id
Equi Join:
A join that uses an asterisk (*) sign in the SELECT list and displays redundant column data
in the result set is termed as an equi join. An equi join displays redundant column data in the
result set, where two or more tables are compared for equality.

E.g. SELECT *
FROM sales s, titles t, publishers p
will give the output:
13
Here ‘*’ asterisk counts the number of rows in resulting table.
Count ( [ ALL/ DISTINCT] column-name)
It returns the number of values in the expression, either all or distinct.
Further, for example the query:
SELECT COUNT (DISTINCT DEPTNO) FROM EMP;
will give the following output:
Here COUNT (DISTINCT) eliminats duplicate field values before calculating the COUNT.
This is be noted that COUNT, MAX and MIN functions can be used for both numeric and
character fields where as SUM and AVG functions can only be used for numeric fields.
EPITOME
SQL Server 2005 63

WHERE s.title_id=t.title-id AND t.pub_id=p.pub_id


The output produced by the above query results in redundant column data from the three
tables.
Self Join:
A join is said to be a self join when one row in a table correlates with other rows in the same
table. Since the same table is used twice for comparison, an alias name differentiates the
two copies of the table.
E.g.1 Consider the following example where you want to list all those titles of books that
belong to the business category that have the same publisher.
SELECT t1.title_id, t1.pub_id, t2.title_id, t2.pub_id
FROM titles t1, titles t2
WHERE t1.title_id=t2.pub_id AND t1.type= ‘business’
E.g.2 The above query will result in a duplicate result set that can be eliminated by modi-
fying the query in the following way:
SELECT t1.title_id, t1.pub_id, t2.title_id, t2.pub_id
FROM titles t1, titles t2
WHERE t1.pub_id=t2.pub_id AND t1.type= ‘business’ AND
t1.title_id<t2.title_id
Outer Join:
A join can be termed as an outer join when the result set contains all the rows from one table
and the matching rows from another. The syntax is:
SELECT column_name, column-name [,column_name]
FROM table_name, table_name [, table_name]
WHERE table_name.ref_column_name outer_join_operator
table_name.re_column_name
E.g. Consider the following example where all the publishers are displayed irrespective
of whether an author is located in the same city or not.
SELECT pub_name, au-lname, au_fname
FROM publishers p, authors a
WHERE p.city*=a.city
Where *= ensures inclusion of all the rows from the first table and matching rows
from the second table.
An outer join can also be combined with additional conditions.
E.g. Consider the following example where the title id, store id and order date is displayed
where the year in order date is 1994.

EPITOME
SQL Server 2005 64

SELECT s.stor_id, s.ord_date, t.title_id


FROM sales s, titles t
WHERE S.title_id=* t.title_id AND DATENAME(yy, s.ord_date)=’1994’

Mathematical Functions
SQL Server supports various functions that can easily be used to manipulate data.
Mathematical functions are one of them. They are used to resolve some mathematical
problems like to calculate the power of two entities etc. Some mathematical functions are
described below:
(a) ABS (numeric- expn): It will return the absolute value of the column or value passed.
For example the following query:
SELECT ABS (-20)
Will give the output as 20.
(b) ACOS | ASIN | ATAN (float-expn): It will return the only in radians whose cosine,
sine, or tangent is a floating-point value.
(c) ATAN2 (float-expn1,float_expn2): It will return the angle in radians whose tangent is
in between float- expn1 and float- expn2.
(d) COS | SIN | COT | TAN (float-expn): It will return the angle in radians for cosine, sine
or tangent.
(e) CEILING (numeric-expn): It finds the smallest integer, greater than or equal to the
specified value
i.e. numeric expn. The value can be a column name.
For example the following query:
SELECT CEILING (9227.57)
Will give the output as 9228.
(f) DEGREES (numeric-expn): It will convert the numeric-expn from radians to degrees.
(g) EXP (float-expn) It will return the exponential value of specified value i.e. float-exan.
(h) FLOOR (numeric-expn): It finds the largest integer iess than or equal to specied
value i.e.,numeric
_expn.
For example the following query:
SELECT FLOOR (9227.56)
will give the output as 9227.
(i) LOG (float-expn) It will return the natural log value of the specified value in
parenthesis.

EPITOME
SQL Server 2005 65

(j) LOG10 (float-expn) It will return the Base -10 value of the float-expn enclosed in
parenthesis.
(k) PIC : It is a constant function,returns a constant i.e. 3.141592653589793
(l) POWER (num-expn1, num-expn 2) : This function return num-expn1 raised to the
power num-expn
2. Remember that num-expn 2 must be an integer.
For example the following query:
SELECT POWER (2,8)
will give the output as 256.0
(m) RADIANS (num-expn) : It used to convert the specified value from degrees to radians.
(n) RAND ([ Seed ]): It will return random float number between 0 and 1.
(o) ROUND (num-expn, length) : This function is used to round off the specified value to
the given
length. For example the following query:
SELECT ROUND (1234.56,0)
will give the output as 1234, where as
SELECT ROUND (1234.56,1)
will give the output as 1,234.60, and
SELECT ROUND ($1234.56,1)
will give the output as 1,234.60
(p) SIGN (num-expn) : It will return the value in positive, negative as zero.
(q) SQUARE (float-expn): It returns the square of specified value given in parenthesis.
For example the following query:
SELECT SQUARE (15)
will give the output as 225.
(r) SQRT (float-expn) It will return the squarerest of the specified value i.e, float-exan.
For example the following query:
SELECT SQRT (64)
will give the output as 8.

String Functions
String Functions are used to manipulate string in different forms. Some of the string func-
tions are as follows:
(a) Lower (string): This function converts all the characters in the string to lowercase
letters. For example

EPITOME
SQL Server 2005 66

the query:
SELECT LOWER (‘SHALINI’) or Select lower (‘SHALINI’)
will give the output :
SELECT LOWER (JOB) FROM EMP.
will give the output:
LOWER (JOB)
...................
Clerk
Salesman
Manager
Salesman
Manager
Analyst
Salesman
Clerk
Clerk
Analyst
Clerk
(b) UPPER (String) converts all the characters in the string to upper case letters.
For example the query:
SELECT UPPER (JOB) FROM EMP
will give the output
UPPER (JOB)
..............
CLERK
SALESMAN
SALESMAN
MANAGER
SALESMAN
MANAGER
MANAGER
ANALYST
SALESMAN
CLERK
CLERK ANALYST CLERK

EPITOME
SQL Server 2005 67

(c) SOUNDEX (String): This function returns a phonetic representation of each word
and allows you to compare word that are spelt differently but sounds alike. For example the
query,
SELECT ENAME FROM EMP WHERE SOUNDEX (ENAME)
=SOUNDEX (‘RAJ’)
will give the following output:
ENAME
RAJAN
(d) SUBSTRING (String M, N): This function returns a sub-string, N characters long
from the string, starting from position M.If the number of characters, N, is not specified, the
string is extracted
from position M to end. Note the blank spaces are also counted.
For example the query:
SELECT SUBSTRING (“ I WILL KILL YOU”, 8,4)
will give the following output;
kill
(e) ‘expn’ + ‘expn’: This function is used to concatenates two or more character strings.
For example the query:
SELECT ‘ HELLO’ + ‘SHALINI’
will give the output as-HELLO SHALINI.
(f) ASCII (Char-expn): This function returns the ASCII code value of the leftmost char-
acter.
For example the query:
SELECT ASCII (‘HELLO’)
will give the output as 72.
(g) CHAR (integer-expn): This function returns the character equivalent of the ASCII
code value.
(h) CHARINDEX (Pattern, expn) : This string function return the starting position of the
specified pattern.
(i) DIFFERENCE (Char-expn 1, Char-expn 2): It Compares two strings and evaluates
their similarity.
It returns a value from 0 to 4 being the best match.
(j) LEFT (Char-expn, int-expn): It returns a character string staring from the left and
preceding integer expn characters.
For example the following query:

EPITOME
SQL Server 2005 68

SELECT LEFT (‘SQL SERVER’3)


will give the output as SQL
(k) LTRIM (Char-expn) : It returns the string without leading blanks.
For example the query:
SELECT LTRIM (“SQL SERVER”)
will give the output as SQL SERVER.
(l) NCHAR (int-expn): It returns the Unicode character corresponding to the int-expn.
(m) PATINDEX (“ % Pattern %” expn) : It returns the starting position of the first occur-
rence in expression.
(n) QUOTENAME (‘string’, ‘quote-char’) : It returns a Unicode string (nvarchar (129)
with valid SQL
Server delimiters.
(o) REPLACE (‘STRING1’, ‘STRING2’, ‘STRING3’): It replaces all occurrence of string
2, with string 3 in string 1.
For example the following query:
SELECT REPLACE (‘HELLO’, HOW ARE YOU’, ;HELLO’, ‘HI’) will give the output
as HI, HOW ARE YOU ?
(p) REPLICATE (Char-expn, int-expn): This function is used when we required to re-
peat a single character expn the specified number of times.
For example the following query:
SELECT REPLICATE (‘HA!, 3)
will return the output as HA! HA! HA!
(q) REVERSE (Char-expn) : This function is used when we want to reverse the expn.
For example the following query:
SELECT REVERSE (‘REVERSE IT’)
will give the output as TI ESREVER
(r) RIGHT (Char-expn, int-expn): It returns a character string starting integer-expn
character from right.
For example the following query:
SELECT RIGHT (‘SQL SERVER’,3)
will generate the output as VER
(s) RTRIM (Char-expn) : It removes the trailing spaces from the Char-expn.
For example the following query:

EPITOME
SQL Server 2005 69

SELECT RTRIM (‘SQL SERVER’)


will generate the output as SQL SERVER.
(t) STUFF (Char-expn1, start, len, Char-expn2): It is used to insert a string in place of
other. It deletes length (len) character from Char-expn1 at start position and inserts Char-
expn2 at start.
For example the following query:
SELECT STUFF (‘HELLO, HOW ARE YOU?’, 1,5, ‘H1’)
will give the output as HI, HOW ARE YOU?

Date Function
Date functions used to do the manipulation on system date or on the date type datafields.
The datetime values can be manipulated using the Date functions. They can be used in the
column-list WHERE clause, or Where ever an expression can be used. The syntax of date
function is as follows:
SELECT date-func (parameters)
The parameters passed in date-func must enclose date time values, between single or double
quotation marks. Some function take a parameter called date part. The following are the
dateparts, their values and abbreviations.
date part Abbreviation Values
day dd 1-31
day of year dy 1-366
hour hh 0-23
millisecond ms 0-999
minute mi 0-59
month mm 1-12
quarter qq 1-12
second ss 1-4
week wk 0-59
weekly dw 1-7( sun-sat)
year yy 1759-9999

Some of the Date functions are as follows :-


(a) DATE ADD (date part,num, date) : This function is used to add num, datepart to the

EPITOME
SQL Server 2005 70

date. It means that any datepart like dd, mm, yy, mi etc. Can be changed in the date by
adding the number i nit.
For example the following query
SELECT DATE ADD (mm, 6, ‘1/1/07’)
will generate the output as Jul 1, 2007 10.50 PM.
Another example as follows:
SELECT DATE ADD (mm, 5, ‘1/1/07’)
will generate the output as Jul 1, 2006 10.50 PM.
Note that the function is taking the date in dd/mm/yy mi: ss AM/PM format
(b) ATE DIFF (datepart, datel, date 2) : It returns the number of dateparts i.e, days.
Months, year etc.,
in between two dates.
For example the following query
SELECT DATEDIFF (mm, ‘1/1/07’, ‘12/31/08)
will return the result as 23.
(c) DATE NAME(date part, date):It returns the ASC11 Code/value for a specified datepart
for
the date listed.
(d) DATE PART (datepart, date): It returns the integer value for a specified datepart for
the date listed.
(e) DAY (date) : It is used to get the integer value of the day.
(f) MONTH (date) : It returns an integer value representing the year.
(g) YEAR (date) : It returns an integer value representing the year.
(h) GET DATE () : It returns the current date and time in internal format.
Eliminating Duplicate Information
Preventing the Selection of Duplicate Rows
Unless you indicate otherwise, SQL Server displays the result of query without eliminating
duplicate entries.
For instance, the following query:
SELECT DEPTNO
FROM EMP
Produces the following result.

EPITOME
SQL Server 2005 71

DEPTNO
20
30
30
20
30
30
10
20
10
30
20
30
20
10
To eliminate duplicate values in the result, include the DISTINCT qualifier in the SELECT
command as follows:
SELECT DISTINCT DEPTNO
FROM EMP
This time the result will not contain duplicate values.
DEPTNO
20
30
10
Multiple columns may be specified after the DISTINCT qualifier and the DISTINCT
affects all selected column.
To display distinct values of DEPTNO, JOB
FROM EMP
The result is given below:

DEPTNO JOB
10 CLERK
10 MANAGER
10 PRESIDENT
20 ANALYST

EPITOME
SQL Server 2005 72

20 CLERK
20 MANAGER
30 CLERK
30 MANAGER
30 SALESMAN

Sorting of Data
Sorting Data Using the ORDER BY Clause
In general, the rows displayed from a query do not have any specific order either ascending
or descending. But that can be control for the selected rows by adding the clause ORDER
BY to the SELECT command, So,the ORDER BY clause is used to sort the rows on a
particular field. If used, ORDER BY clause must always be the last clause in SELECT
statement.
To sort by ENAME, the basic syntax for using the ORDER BY clause is as follows:
SELECT Column-list
FROM table-list
[ORDER BY Column-name [column-list-number [ASC DESC]
You can have any number of column in your ORDER by list as they are no wider than 900
bytes. You can also specify column names or use the ordinal number of the columns in the
column-list.
(In the table EMP) the query:
The result is below.

ENAME JOB SAL DEPTNO


AMAN CLERK 1,100.00 20
ANIL SALESMAN 1,600.00 30
KIRON MANAGER 2,975.00 20
MINU MANAGER 2,450.00 10
NILU ANALYST 3,000.00 20
PRASHANT MANAGER 2,850.00 30
RAJAN SALESMAN 125.00 30
RAKESH SALESMAN 1,250.00 30
RAMESH SALESMAN 1,500.00 30
SUDHA CLERK 950.00 30
SUNIL ANALYST 3,000.00 20

EPITOME
SQL Server 2005 73

VIBHOR CLERK 800.00 20


VINOD CLERK 1,300.00 10

The default sort order is ASC, which defines the following sort order.
 Numeric values lowest first
 Date values earliest first
 Character values alphabetically (a to z)

To reverse the order, the command word DESC is specified after the column name in the
ORDER BY clause.
SELECT ENAME, JOB, SAL, DEPTNO
FROM EMP
ORDER BY ENAME
To reverse the order of the DOJ column, so that the latest dates are displayed first, enter.
SELECT ENAME, JOB
DOJ FROM EMP
ORDER BY DOJ DESC
ENAME JOB DOJ
SUDHA CLERK 23-Jul-84
PRASHANT MANAGER 11-Jun-84
RAMESH SALESMAN 4-Jun-84
AMAN CLERK 4-Jun-84
MINU MANAGER 14-May-84
RAKESH SALESMAN 26-Mar-84
SUNIL ANALYST 5 Mar-84
RAJAN SALESMAN 5 Dec-83
NILU ANALYST 5 Dec -83
VINOD CLERK 21-Nov-83
KIRON MANAGER 31-Oct-83
ANIL SALESMAN 15 -Aug -83
VIBHOR CLERK 13- Jun-83

It is possible to ORDER BY more than one column. The limit is the number of columns on the
table. In the ORDER BY clause, specify the columns to order by column.
To order by two columns and display in reverse order of salary, enter.
SELECT DEPTNO, ENAME, JOB, SAL
EPITOME
SQL Server 2005 74

FROM EMP
ORDER BY DEPTNO, SAL DESC
The result is shown below:
DEPTNO ENAME JOB SAL
10 MINU MANAGER 2,450.00
10 VINOD CLERK 1,300.00
20 SUNIL ANALYST 3,000.00
20 NILU ANALYST 3,000.00
20 KIRON MANAGER 2,975.00
20 AMON CLERK 1,100.00
20 VIBHOR CLERK 800.00
30 RAJAN SALESMAN 1,25.00
30 PRASHANT MANAGER 2,850.00
30 ANIL SALESMAN 1,600.00
30 RAMESH SALESMAN 1,500.00
30 RAKESH SALESMAN 1,250.00
30 SUDHA CLERK 950.00

Note : all examples are taking from EMP table only.


You can use column names and ordinal numbers together in the ORDER BY clause, It also
be specified, whethar. You want the results sorted in ascending (ASC) OR descending (DESC)
order.
For example the following query :
SELECT EMPID, MGR
FROM EMP
ORDER BY 1,2
Here the EMP table will be displaying with two columns sorted on first and second column of
the EMP table.
you sort results based on a column with NULL values and ASC order is used, the containing
NULLS are displayed first.
When you use ORDER BY clause, the sort order of the SQL SERVER can make a differ-
ence in the result sets. The default sort order for SQL server is dictionary order and case
insensitive. A case-sensitive sort order can affect the ordering of the result sets because a
capital ‘A’ considered the same as a lower case a.

Aggregate Function
EPITOME
SQL Server 2005 75

SQL Server aggregate functions produce a single value for the entire gruop of table entries.
Aggregate functions are normally used with the GROUP by clause and in the entries. Aggre-
gate functions are normaly used with the GROUP by clause and in the HAVING clause or
the column-list. This information might seem to little overwhelming at first, but with me.
Aggregate or column functions can also be used with the SELECT command. These func-
tions are SUM, AVG, MAX, MIN and COUNT etc.

Sum
Sum ([ALL DISTINCT] column-name)
Sum function is used to calculate the addition of all the selected values of a given column.
It returns the total of the values in the numeric expression, eithor all or distinct.
For example the query:
SELECT SUM (SAL) FROM EMP
will give the following output:
23000.00
AVG ([ ALL/ DISTINCT] column-name)
This function is used to calculates the average of all selected values. It returns the average
of the values in the numeric expn, either all or distinct.
For example the query:
SELECT AVG (SAL) FROM EMP
will give the following output:
17694.32

MAX (column-name)
This function is used to calculate the largest of all selected values of a given column or given
expression.
For example the query,
SELECT MAX (SAL) FROM EMP
will give the output as shown below:
3000.00
MIN (column-name)
This function is used to calculate the smallest of all selected values of a given column or
given expression.
For example the query:
SELECT MIN (SAL) FROM EMP;
will give the output as shown below
EPITOME
SQL Server 2005 76

800
Count (*)
This function is used to count the number of rows in the output table.
For example the query :
SELECT COUNT (*) FROM EMP
will give the output:
13
Here ‘*’ asterisk counts the number of rows in resulting table.
Count ( [ ALL/ DISTINCT] column-name)
It returns the number of values in the expression, either all or distinct.
Further, for example the query:
SELECT COUNT (DISTINCT DEPTNO) FROM EMP;
will give the following output:
Here COUNT (DISTINCT) eliminats duplicate field values before calculating the COUNT.
This is be noted that COUNT, MAX and MIN functions can be used for both numeric and
character fields where as SUM and AVG functions can only be used for numeric fields.
Using Transact-SQL

Introduction

You are already familiar with commands used to modify the database like INSERT, UP-
DATE and DELETE. we rarely, if ever, give our database users DELETE permissions It’s
far too easy for accidents to happen with of power. Instead of this, create stored procedures
that do a delete and ensure that data integrity is maintained.
This Unit focuses on the programming features of the Transact-SQL language. You start off
by learning about control-of-flow language elements, if-else blocks and while statements.

Control-of-Flow Language Elements


When a batch of statements is submitted to SQL Server for execution, the normal flow is for
the commands to be executed in the order they are given. The T-SQL language supports
serval commands that allow to change the sequence of command execution. They are most
useful in transactions, triggers, functions, and stored procedures.

Begin.......... End Block


Several control-flow commands require a single as part of their syntax. Whereever a single

EPITOME
SQL Server 2005 77

statement is expected, you can use just a single statement. To execute multiple statements
together; you must enclose them between the keywords BEGIN and END. This construct is
used in some of the following examples.

Print Statement
Till now, you use only SELECT statement to return any information from SQL server to your
client program. SQL Server also provides a PRINT Statement.
SYNTAX : PRINT. { ‘ANY ASCII TEXT’/ @local-variable/@@global-variable}.
You can print an ASCII string (string constant) or type character. For example.
PRINT “ Hello”
PRINT @@ version
To print something more complex, you must build the string in a character variable and then
print that variable.

Example
Use pubs
DECLARE @msg varchar (50),
@numWA tinyint
SELECT @numWA = COUNT (*) FROM stores
WHERE state = ‘WA’
SELECT @msg = ‘ There are’ + Convert (varchar (3), @numWA)
+’ stores in washington’
PRINT @msg
(1 row (s) affected)
(1 row (s) affected)

here are 2 srores in washington.

If...... Else Block


An IF....ELSE block allows the conditional execution of a statement. The word IF is followed
by an expression that be either true or false. If the expression is true, the next statement is
executed. The optional EISE keyword introduces on alternative statement that’s executed
when the expression following IF is false.

Syntax

EPITOME
SQL Server 2005 78

IF Boolean-expression
{Sq1-statement/statement-block}
ELSE [ Boolean-expression]
{ Sql-statement/statement-block}

Example
The statement call given below calls precedure usp Weekly Report if today is Friday; other-
wise, no action is taken:
IF (datename (dw, getdate ( )) = ‘ Friday’)
BEGIN
PRINT ‘Weekly report’
EXEC usp weekly Report
END
ELSE
BEGIN
PRINT ‘Daily report’
EXEC usp Daily Report
END
The Boolean expression that follows the IF can include a SELECT statement. If that SE-
LECT statement returns a single value, it can then be compared with another value to pro-
duce a Boolean expression.
Example
IF (SELECT avg (price) FROM titles) > S15
PRINT ‘ Hold a big sale’
ELSE
PRINT ‘Time to raise prices’
If more that one value are returned by the SELECT statement following IF, then a special
form of IF-IF
EXISTS is used.
Syntax
IF EXISTS(SELECT statement)
{sql-statement/statement-block}
[ ELSE
{ sql-Statement /Statement-block}]
IF EXISTS returns true if the SELECT statement returns any rows at all and returns false if
the
EPITOME
SQL Server 2005 79

SELECT
statement returns no rows.
Example
The following example returns all the information about any book published by the publisher
with ID 8453.
IF EXISTS (SELECT * FROM titles WHERE
pub-id = ‘8453’)
BEGIN
PRINT ‘The books are as follows :’
SELECT * FROM titles WHERE
pub-id = ‘8453’
END
ELSE
PRINT ‘No book is found for that publisher’

Case Expressions
The CASE expression allows T-SQL expressions to be simplified for conditional values. It
allows statement to return different values depending on the value of a controlling value or
condition.
Syntax
CASE expression
WHEN expression 1 THEN expression 1
[ WHEN expression 2 THEN expression 2]
[.....] ]
[ELSE expression N]
END
A searched expression can also used.

Syntax
CASE
WHEN boolean=expression 1 THEN expression 1
[WHEN boolean=expression 2 THEN expression 2]
[........] ]
[ ELSE expression N]
END
A simple CASE expression compares an initial expression with each expression in the list
EPITOME
SQL Server 2005 80

and returns the associated result expression. If none of the expression match, the result
expression after the word ELSE is returned.
Example
SELECT title-id type = CASE type
WHEN ‘business’ THEN ‘Business Book’
WHEN ‘psychology’ THEN ‘psychology Book’
WHEN ‘mod-cook’ THEN ‘ Modern Cooking book’
WHEN ‘popular-camp’ THEN ‘popular computing book’
WHEN ‘undecided’ THEN ‘No’ type determined yet’
FROM titles
Sometimes a CASE expression has the following form:
CASE
WHEN expr IS NOT THEN expr 1
[ [ WHEN expr 2 IS NOT THEN expr 2]
[......]]
[ELSE expr N]
END

Using the While Command


The T-SQL language also supports a WHILE construct that allows repetitive execution until
some condition is met.
In certain situations, you need to repeat actions. You can them inside a transaction, within a
stored procedure, or within a SQL function. WHILE statements can be useful when you
navigate through a cursor.s
A WHILE construct repeats as long as a specified condition remains true. If the condition
includes a SELECT statement, the entire SELECT must be in parentheses.
Example
WHILE (SELECT AVG (price) FROM titles) <$20
BEGIN
UPDATE titles SET price = price * 1.1
PRINT ‘all prices have been increased by 10%
END
The above example repeatedly checks the average price of all books. As long as the aver-
age is less than $ 20, the price of every book is updated. The repetition stops when the
average price is greater than or equal to $ 20.
The above default can be unbounded as
EPITOME
SQL Server 2005 81

SP_UNBINDEFAULT ‘emp.joindate’
SQL Programing:
BATCH: A batch is a set of SQL statement that are sent together to the SQL server for
execution
BLOCK OF STATEMENTS:
A block allows the building of units with one or more SQL statements. Every block begins
with the BEGIN statement and ends with an END statement.
BEGIN
Statement – 1
Statement – 2
…………………
…………………
END

IF STATEMENT
This statement is used to execute block of the condition following the keyword ‘IF’ evaluates
to true.
E.g.
IF (SELECT sum (price) FROM titles where type= ‘business’)<60
BEGIN
PRINT ‘The sum of these business books are less then 60’
SELECT title FROM titles
WHERE type= ‘business’
END

WHILE STATEMENT
This statement executes a block while the Boolean expression following it evaluates to true.
E.g.
WHILE (SELECT AVG(price) FROM titles)<60
BEGIN
SELECT title FROM titles
IF (SELECT MAX(price) FROM titles)>30
BREAK
ELSE
CONTINUE

EPITOME
SQL Server 2005 82

END
Working with Views
Creating views
Views are database objects resembling a virtual table which are derived from one or more
base tables. Views do not contain any records. The records retrieved through the views are
actually retrieved from the underlying base table(s). The only information concerning the
views that is physically stored is the name of the view and the way in which the rows are to be
retrieved from the base tables. All the DML operations (INSERT, UPDATE, DELETE etc) that
are performed in the tables can be performed in the views as well. The changes being made
through the views are actually reflected in the base tables. The general syntax of creating
views is:
CREATE VIEW view_name
[WITH ENCRYPTION]
AS
select_statement
[WITH CHECK OPTION]
Where view_name is the name of the view to be created. The select_statement is the
SELECT statement which is used to retrieve the result-set of the view from the underlying
tables. The WITH ENCRYPTION option encrypts the select statement in the system table
syscomments. This option can be used to enhance the security of the SQL Server system.
Purpose of views
Views are used for the following purposes:
 To restrict the use of particular columns and/or rows of a table. Therefore, views can
be used for controlling access to a particular part of one or more tables.
 To hide the details of complicated queries. If database applications need queries
that involve complicated join operations, the creation of corresponding views can
simplify the use of such queries.
 To restrict insertion and updation of values of certain ranges (with the use of WITH
CHECK OPTION).
DML statements and views
The following example creates a view named dept10 consisting the empno, ename, hiredate
and deptno columns of all records of the employees of department no. 10.
CREATE VIEW dept10
AS
select empno,ename,hiredate,deptno from emp where deptno=10

After the above view is being created, it can be used to retrieve the information from the

EPITOME
SQL Server 2005 83

underlying tables using the SELECT statement.


SELECT * from dept10
Similarly, the above view can also be used to perform INSERT, UPDATE and DELETE op-
erations as it is done for the tables. Any change made through the view will actually change
the data stored in the base table.
INSERT INTO dept10 VALUES(5,’Urvashi’,getdate(),10)
UPDATE dept10 SET ename=’Jyoti’, hiredate=’12/22/2001’ WHERE empno=5
DELETE FROM dept10 WHERE empno=4
The present form of the above view is now flexible enough to accept or update records of
employees who are not from department no 10. This means a user can use the above view
to insert a record with department number other than 10 and can update them as well. This
might cause some conflict in the security mechanism. In order to prevent any such situation,
the view can be created with the WITH CHECK OPTION clause. The with check option
clause prevents a user to use the view for manipulating the records which are beyond the
scope of the view. So the correct definition of the above view in this case, will be:
CREATE VIEW dept10
AS select empno,ename,hiredate,deptno from emp where deptno=10
WITH CHECK OPTION
The modification of columns with a view is not possible in the following situations:
 If the view is created on multiple base tables
 If a column of the view is derived from an aggregate function
 If the SELECT statement in the view contains GROUP BY clause or the DISTINCT
clause
 If a column of the view is derived from a constant or an expression
Altering and removing views
Views once created can be modified using the ALTER VIEW statement. The ALTER VIEW
statement is actually used to modify the definition of the view query. We can use the ALTER
VIEW statement to avoid reassigning existing privileges for the view. The syntax of the alter
view statement is:
ALTER VIEW view_name
AS
select_statement
Views can be permanently deleted from the database using the drop view statement. The
syntax is:
DROP VIEW view_name

EPITOME
SQL Server 2005 84

TRIGGER
A trigger is composed of two parts:
 A SQL command to activate the trigger. The INSERT, DELETE, and UPDATE commands
can activate a trigger. The same trigger can be invoked when more than one action occurs.
 An action executed by the trigger. The trigger executes the PL\SQL block.
Limitations of Triggers
 A trigger can execute the commands contained in its body or activate stored procedures
and other triggers in order to execute certain tasks.
 Any SET command can be specified inside a trigger. It remains active during the execution
of the trigger.
 You cannot create a trigger for a view. However, when the view is used, the triggers of the
base table normally are activated.
 When a trigger is executed, the results are returned to the application that called it. To
avoid returning the results, do not use the SELECT command that returns results or execute
the attribution of contents to the variables.
 The Transact-SQL commands listed below cannot be used inside a trigger:
ALTER DATABASE ALTER PROCEDURE ALTER TABLE
ALTER TRIGGER ALTER VIEW CREATE DATABASE
CREATE DEFAULT CREATE INDEX CREATE PROCEDURE
CREATE RULE CREATE TABLE CREATE TRIGGER
Creating a Trigger
The syntax to create a trigger is:
CREATE TRIGGER trigger_name ON table_name FOR [INSERT | DELETE |
UPDATE]
AS commands
e.g.
CREATE TRIGGER newprod on test1 FOR INSERT
as
print “A new product was inserted”
To test the functioning of this trigger using the Query Analyzer.
INSERT test1 values ( 1, “prod01”, 10 )
Now let’s create a trigger that is activated when the UPDATE command is executed. The
code for the trigger is the following:
CREATE TRIGGER upprod ON test1 FOR UPDATE
AS
Print ‘A product was updated’
EPITOME
SQL Server 2005 85

Now execute the following code in the Query Analyzer to increase by 20 percent the value of
the Cost field of the codprod 2 record:
Update test1 Set cost=cost * .2 Where codprod=“2”
Select * from test1
And see the sesult:
codprod nameprod cost
———— —————- ———-
1 prod01 10
2 prod02 24
The Inserted Deleted Tables
When a trigger is executed, the SQL Server 7 creates two temporary tables that only
exist when the trigger is activated. One is called Inserted and the other is Deleted. When an
INSERT or UPDATE command is executed, the records that are created or changed are
copied to the Inserted table. When a DELETE command is executed, the deleted lines are
copied to the Deleted table.
These tables are useful when you want to have the lines added, deleted, or altered
during the process of executing the trigger. They are particularly useful for copying lines from
one table to another. To check the existence of this table we will change the updprod trigger
as
Create trigger updprod on test1 For UPDATE
As
Print ’A Product was updated’
SELECT * FROM INSERTED
The following code updates the record with prod02 and shows the result through the selection
of the altered record in Test1. The trigger shows the message “A product was updated” and
the contents of the Inserted table.
Update test1 Set cost=cost*1.2 Where codprod=’2’
Select * form test1
Eg. 1. Consider the Use of Triggers in the case of the following Tables :

ITEM TRANSAC
cItem_code cTransaction_code
vItem_name dTran_Date
iQOH cItem_Code
mPrice iQty
mTotalAmt

EPITOME
SQL Server 2005 86

Eg. 2. Trigger to avoid insert of duplicate value of item_code on


Item table (check primary key)
create trigger insert_icode
onitem
for insert
as
if (select count ( * ) from item m, inserted i
where m. cItem_code=i.cItem_code)>0
begin
rollback tran
print ''Duplicate Item Code ....already exist''
end
else
begin
print ''Row inserted''
end
Eg. 3. Trigger to avoid insert of duplicate value of transaction_code on
Transac table (check primary key)

create trigger insert_tcode


on transac
for insert
as
if (select count ( * ) from transac t, inserted i
where t.c Transaction_code=i.c Transaction_code)>0
begin
rollback tran
print ''Duplicate Transaction Code .... already exist''
end
else
begin
print ''Row inserted''
end

EPITOME
SQL Server 2005 87

Changing a Trigger
A trigger can be changed directly with the ALTER TRIGGER command, as shown below.
Another option is to eliminate the trigger and create it again. This operation can also be
performed in the Trigger Properties dialog box. The syntax is:
ALTER TRIGGER trigger_name
Deleting a Trigger
In order to delete a trigger, first expand the Databases folder, expand the database in which
the table containing the trigger belongs, and then click Tables. In the details pane, right-click
the table in which the trigger exists. Point to Task, and then click Manage Triggers. In the
Name list, select the name of the trigger to delete, and select Delete. You can also use the
SQL DROP TRIGGER statement:
DROP TRIGGER trigger_name
Managing Database Transactions
Transactional control is the ability to manage various transactions that may occur within a
relational database management system as INSERT, UPDATE or DELETION of data. When
a transaction completes successfully, the target table is not changed immediately. Certain
control commands are used to finalize the transaction by either saving the changes made by
the transaction or by reversing the same. There are three commands used to control trans-
actions:
a. COMMIT
b. ROLLBACK
c. SAVE
The COMMIT Command
This command is used to save the changes made to the database tables since the last
commit or rollback statement. For example, consider the statement:
DELETE Products
WHERE cost<14
Which deletes say eight rows from the table.
A COMMIT statement is issued to save the changes to the database, completing the
transaction
COMMIT
The ROLLBACK Command
This command is used to undo transactions that has not yet been saved to the database. For
example, consider the statement.
Update Products
Set Price=34.45
EPITOME
SQL Server 2005 88

Where ProductID='11234'
A select statement will show the new values in the table if you execute the statement
Select * from Products
A rollback statement will undo the change made to the table
ROLLBACK
To verify that the changes have not occoured to the database, use the select statement
again. you will find that the original values are returned.
The Save command
A transaction can be rollback to the savepoint. consider the following example that sets a
savepoint and rollback atransaction upto the point.
Save s1
Delete Products where ProductID='11234'
Save s2
Delete Products where ProductID='11256'
Rollback s2
The Changes made by the 2nd Delete statement will be undone.
Stored Procedures
Stored procedures are precompiled transact-SQL (T-SQL) statements stored in a SQL Server
database. Because stored procedures are precompiled, they usually provide the best perfor-
mance of any type of query. Many system stored procedures defined with an sp_gather
information from system tables and are especially useful for administration. You can create
your own user-defined stored procedures as well. Stored procedures are fast running sets
of T-SQL commands stored in a Server database.

Working with Stored Procedures


When a stored procedure is run for the first time, all the following steps are run. The query
plan of the stored procedure in them is placed into memory.
1. The procedure is passed into component pieces.
2. The components that reference other objects in the database are checked for their
existence. This process is known as resolving.
3. The name of the procedure is stored in the sysobjects table, and the code to create the
stored procedure is saved in syscomments.
4. Blueprint for how to run the query is created during compilation. The blueprint is often
called a normalized plan or a query tree. The query tree is saved in the sysprocedures
table.
5. When the stored procedure is first executed, the query tree is read and fully optimized
EPITOME
SQL Server 2005 89

into a procedure plan and then run. This saves the time of reparsing, resolving and compiling
a query tree every time the stored procedure is run.
Another benefit of a stored procedure is that after it’s executed, the procedure plan is stored
in the procedure cache. This means that the next time you use that stored procedure in the
same session, it will be read directly from the cache and run.

Creating Stored Procedures


To create a stored procedure, the CREATE PROCEDURE statement is used. Stored
procedures are created in the current database unless a temporary stored procedure is
created in tempdh. You must have the create procedure statement permission to create a
stored procedure.

The rules for creating a stored procedure are as follows :


* The name must follow the rules for identifiers.
* Referenced objects must exist when your stored procedure runs.
* Objects with the same name in a single stored procedure can’t be created and then
drop or re-create.
* Upto 1024 parameters can be allowed.
* Temporary tables can be referenced within the stored procedure. Local temporary tables
disappear when procedure ends.
* Stored procedure can’t have the following T=SQL create statements in them: CREATE
DEFAULT, CREATE PROCEDURE, CREATE RULE, CREATE TRIGGER, and CREATE
VIEW
* Procedures can be nested within procedures (upto 32 levels deep).
* If a * is used in the stored procedure SELECT statement and the underlying table has
new columns added to it, the new columns don’t show up underlying table has new
column added to it, the columns don’t show up when the procedure is run. ALTER
statement must be used and the stored procedure must be recompiled.

Syntax
CREATE PROC [EDURE] procedure-name [ ; number]
[{ @parameter data-type} [VARYING] [= default] [OUTPUT]] [, .....n]
[WITH { RECOMPILE | ENCRYPTION | RECOMPILE, ENCRYPTION}]
[ FOR REPLICATION]
As sql-statement [........ n]

EPITOME
SQL Server 2005 90

Example
CREATE PROCEDURE pAuthors
AS SELECT au-fname, au-lname
FROM authors
ORDER BY au-lname DESC

This command did not return data, and it did not return any rows.

Use this procedure by executing it from the Query Analyzer Window :

EXEC pAuthors
au-fname au-lname
Yokomoto Akiko
Stringer Dirk
[...] [...]
Blotchet-Halls Reginald
Bennet Abraham
(23 row (s) affected)
The result is a two-column table with the last and first names shown in descending order.
COMPONENTS OF A STORED PROCEDURE
Parameters:
Parameters are used to establish connection between a stored procedure and the outside
world. When a program executes a stored procedure, it can pass values to it in the form of
input parameters and receive values from it in the form of output parameters.
Parameters must have a unique name and always start with a ‘@’ symbol followed by the
data type definition. All the parameters created are considered input by default. Output
parameter can be created by using the keyword OUTPUT with the parameter.
Return Codes:
Stored procedures can return an integer type of value called return code to indicate whether
the execution of the procedure was successful. For example:
Value Meaning
0 Procedure executed successfully
1 Input Parameter not specified
2 Invalid parameter contents

EPITOME
SQL Server 2005 91

The Create Procedure Statement


The syntax for creating a stored procedure is:
CREATE PROCEDURE procedure_name [INPUT | OUTPUT PARAMETERS]
AS
BEGIN
Sql statements
RETURN
END
The stored procedure can be executed using the command:
EXEC[UTE] procedure_name
Eg: the following procedure inserts values into a table emp

CREATE PROCEDURE insert1 @emp_no char(4), @emp_name varchar(20),


@dept char(4)
AS
BEGIN
INSERT INTO emp VALUES (@emp_no,@emp_name,@dept)
END
The procedure can be executed as :
EXEC insert1 ‘e001’, ‘Vikash’, ‘d001’
Changing a Stored Procedure - The Alter Procedure Statement
Consider we have a procedure find_author as follows
CREATE PROCEDURE find_author
AS
SELECT au_lname,au_fname, state from authors
END
The procedure can be changed to display the name of the authors after accepting the state
as a parameter as
ALTER PROCEDURE find_author @st varchar(10)
AS
SELECT au_lname,au_fname, state from authors
WHERE state=@st
END
A standard value can also be used in a stored procedure if no parameter is supplied during
execution as:

EPITOME
SQL Server 2005 92

ALTER PROCEDURE find_author @st varchar(10)=’UT”


AS
SELECT au_lname,au_fname, state from authors
WHERE state=@st
END
Deleting a Stored Procedure
A stored procedure can be deleted by using the DROP PROCEDURE command as:
DROP PROCEDURE find_author
Recompiling a Stored Procedure
The stored procedure is recompiled each time it is executed. Use the WITH
RECOMPILE option when stored procedures take parameters whose values differ widely
between executions of the stored procedure, resulting in different execution plans to be
created each time. Ideally, you should not use this option because by using this option,
you lose most of the advantages you get by substituting SQL queries with the stored
procedures. However, you can use this option during early development stages of the
project where database structure is still evolving and stored procedures should be
recompiled as a result of these changes.

Example : For using With Recompile in creating STORE PROCEDURE


CREATE PROCEDURE find_author WITH RECOMPILE
AS
SELECT au_lname,au_fname, state from authors
End

Except the above method, you also can using with Recompile when you Execute the
Store procedure.

Example: For using With Recompile


EXEC find_author WITH RECOMPILE

SQL Cursors
Cursors are a way of taking a set of data and being able to interact with a single record at a
time. It doesn’t happen nearly as often as one tends to think, but there are indeed times
where you just can’t obtain the results you want to by modifying or even selecting the data in
an entire set. The set is generated by something all of the rows have in common (as defined

EPITOME
SQL Server 2005 93

by a SELECT statement), but then you need to deal with those rows on a one-by-one basis.
The result set you place in a cursor has several distinct features that set it apart from a
normal SELECT statement:
 You declare the cursor separately from actually executing it.
 The cursor and, therefore, its result set are named at declaration-you then refer to it
by name.
 The result set in a cursor, once opened, stays open until you close it.
 Cursors have a special set of commands used to navigate recordset.
While SQL Server has its own engine to deal with cursors, there are actually a few different
object libraries that can also create in SQL Server:
 SQL Native Client (used by ADO.NET)
 OLE DB (used by ADO)
 ODBC ( used by RDO, DAO, and in some cases, OLE DB/ADO)
 DB-Lib (used by VB-SQL)
These are the libraries that client applications will typically use to access individual records.
Each provide its own syntax for navigating the recordset and otherwise managing the cursor.
Each, however, shares in the same set of basic concepts, so, once you have got one object
model down for cursors, you’re most of the way there for all of them.
Every data access API out there (ADO. NET,ADO, ODBC,OLE DB etc.) returns
data to a client application or component in a cursor-it’s simply the only way that non-SQL
programming languages can currently deal with things. This is the source of a big difference
between this kind of cursor and SQL Server cursors. With SQL Server cursors, you usually
have a choice to perform things as a set operation, which is what SQL Server was designed
to do. With the API-based cursors, all you have is cursors, so you don’t have the same
cursors versus no cursor debate that you have in your server-side activities.
The client-side part of your data handling is going to be done using cursors-that’s a given, so
don’t worry about it. Instead, worry about making the server side of your data access as
efficient as possible- that means not using cursors on the server side if you can possibly help
it.
The Lifespan of a Cursor
Cursors have lots of little pieces to them, but I think that it’s best if we get right into looking
first at the most basic form of cursor and then build up from there.
Before we get into the actual syntax though, we need to understand that using a cursor
requires more than one statement-indeed, it takes several. The main parts include:
 The Declaration
 Opening
EPITOME
SQL Server 2005 94

 Utilizing/Navigating
 Closing
 Deallocating
That being said, the syntax for declaring a cursor looks this :
DECLARE< CURSOR name> CURSOR
FOR < select statement>
Keep in mind that this is the super-simple rendition-create a cursor using defaults wherever
possible. we’ll look at more advanced cursors a little later in the chapter.

The cursor name is just like any other variable name, and, other than not requiring the “ @”
prefix, they must obey the rules for SQL Server naming. The SELECT statement can be any
valid SELECT statement that returns a result set. Note that some result sets will not, how-
ever, be updatable. (For example, if you use a GROUP BY, then what part of the group is
updated? The same holds true for calculated field for much the same reason.)

We’ll go ahead and start building a reasonably simple example. For now, we’re not really
going to use it for much, but we’ll see later that it will be the beginning of a rather handy tool
for administering your indexes :
DECLARE @SchemaName varchar (255)
DECLARE @TableName varchar (255)
DECLARE @ IndexName varchar (255)
DECLARE @ Fragmentation float
DECLARE TableCursor CURSOR FOR
SELECT SCHEMA_NAME (CAST (OBJECTPROPERTYEX (i.object -id,
‘SchemaId’ ) AS int) ),
OBJECT-NAME (i.object-id),
i. name,
ps.avg-fragmentation-in-percent
FROM sys.dm-db-index-physical-stats (DB-ID), NULL, NULL, NULL, NULL)
AS ps
JOIN sys. indexes AS i
ON ps. object-id = i. object-id
AND ps. index-id = i. index-id
WHERE avg-fragmentation-in-percent > 30
Note that this is just the beginning of what you will be building. One of the first things you
should notice about cursors is that they require a lot more code than the usual SELECT statement.
EPITOME
SQL Server 2005 95

We’ve just declared a cursor called TableCursor that is based on a SELECT statement that
will select all of the tables in our database. We also declare a holding variable that will
contain the values of our current row while we are working with the cursor.
Just declaring the cursor isn’t enough though-we need to actually open it:
OPEN TableCursor
This actually executes the query that was the subject of the FOR clause, but we still don’t
have anything in place we can work with it. For that, we need to do a couple of things:
Grab-or FETCH-our first record
Loop through, as necessary, FETCHing the remaining records
We issue our first FETCH-this is the command that says to retrieve a particular record. we
must also say into which variables we want to place the values :
FETCH NEXT FROM TableCursor INTO @TableName, @IndexName,
@Fragmentation
Now that we have a first record, we’re ready to move onto performing actions against the
cursor set:
WHILE @@FETCH-STATUE =0
BEGIN
PRINT @SchemaName + ‘.’ + @TableName + ‘.’ +@IndexName + ‘is’
+ CAST @Fragmentation AS varchar) + ‘% Fragmented’
FETCH NEXT FROM TableCursor INTO @SchemaName, @TableName,
@IndexName,
@Fragmentation
END
Every time we fetch a row, @@FETCH-STATUS is updated to tell us how our fetch went.
The possible values are:
0 Fetch succeeded-Everything’s fine.
-1 Fetch failed-Record missing (you’re not at the end, but a record has been deleted
since you opened the cursor).
-2 Fetch failed-This time it’s because you’re beyond the last (or before the first) record
in the cursor.
Once we exit this loop, we are, for our purposes here, done with the cursor, so we’ll close it:
CLOSE TableCursor
Closing the cursor, does not, however, free up the memory associated with that cursor. It
does free up the locks associated with it. In order to be sure that you’ve totally freed up the
resources used by the cursor, you must deallocate it:

EPITOME
SQL Server 2005 96

DEALLOCATE TableCursor
So, let’s bring it all together just for clarity :
DECLARE @SchemaName varchar (255)
DECLARE @TableName varchar (255)
DECLARE @IndexName varchar (255)
DECLARE @Fragmentation float
DECLARE TableCursor CURSOR FOR
SELECT SCHEMA-NAME (CAST (OBJECTPROPERTYEX (i. object-id, ‘SchemaId’) AS
int),
OBJECT-NAME (i. object-id)
i. name
ps.avg-fragmentation-in-percent
From sys.dm-db-index-physical-stats (DB-ID), NULL, NULL, NULL) AS ps JOIN sys.
indexes AS i
ON ps. object-id = i. object-id
AND ps.index-id = i index-id
WHERE avg-fragmentation-inpercent > 30
OPEN TableCursor
FETCH NEXT FROM TableCursor INTO @SchemaName, @TableName,
@IndexName,
@Fragmentation

WHILE @@ FETCH-STATUS =0
BEGIN
PRINT @SchemaName + ‘.’ @TableName + ‘.’ + @IndexName + ‘is’ +
CAST @Fragmentation AS varchar) + ‘% Fragmentented’
FETCH NEXT FROM TableCursor INTO @SchemaName, @TableName,
@IndexName,
@ Fragmentation
END
CLOSE TableCursor
DEALLOCATE TableCursor

We now have something that runs, but as we’ve created it at the moment, it’s really nothing
more than if we had just run the SELECT statement by itself (technically, this isn’t true since
we can’t “PRINT” a SELECT statement, but you could do what amounts to the same thing).
EPITOME
SQL Server 2005 97

What’s different is that, if we so chose, we could have done nearly anything to the individual
rows. Let’s go ahead and illustrate this by completing our little utility.

In days of old, there was no single statement that will rebuild all the indexes in an entire
database (fortunately, we now have an option in DBCC INDEXDEFRAG to do an entire
database). Keeping your indexes defragmented was, however, a core part of administering
your system. The cursor example we’re using here is something of a descendent of what
was the common way of getting this kind of index defragmentation done. In this newer ver-
sion, however, we’re making use of specific fragmentation information, and we’re making it
possible to allow for the use of ALTER INDEX (which allows for more options in how exactly
to do our defragmentation) instead of DBCC INDEXDEFRAG.

Okay, so we have a few different methods for rebuilding or reorganizing indexes without
entirely dropping and recreating them. ALTER INDEX is the most flexible in terms letting you
select different underlying methods of defragmenting (online or offline, complete rebuild or
just a recorganization of what’s there, etc.), so we’re going to leverage this way of doing
things. The simple version of the syntax for ALTER INDEX looks like this:
ALTER INDEX <index name> / ALL
ON <object>
{ [ REBUILD] / [REORGANIZE ]}
Again, this is the hyper-simple version of ALTER INDEX.
The problem with trying to use this statement to rebuild all the indexes on all of your tables is
that it is designed to work on one table at a time. You can use ALL option instead of the index
name if you want to build all the indexes for a table, but you can’t leave off the table name to
build all the indexes for all the tables.Indeed, even if we had used a tool like DBCC
INDEXDEFRAG-which can do an entire database, but just doesn’t have as many options-it
would still be an all-or-nothing thing. That is, we can’t tell to do just the tables above a certain
level of fragmentation, or to exclude particular tables that we may want to have fragmentation
in.

Remember that there are occasionally times when fragmentation is a good thing. In particular,
it can be helpful on where we are doing a large number of random inserts as reduces the
number of page splits.

Our cursor can get us around this just dynamically building the DBCC command:
DECLARE @SchemaName varchar (255)
EPITOME
SQL Server 2005 98

DECLARE @TableName varchar (255)


DECLARE @IndexName varchar (255)
DECLARE @Fragmentation float
DECLARE @Command varchar (255)
DECLARE TableCursor CURSOR FOR
SELECT SCHEMA-NAME (CAST (OBJECTPROPERTYEX (i. object-id,
‘SchemaId’) AS int),
OBJECT-NAME (i. object-id)
i.name
ps.avg-fragmentation-in-percent
From sys.dm-db-index-physical-stats (DB-ID(), NULL, NULL, NULL, NULL
) AS ps
JOIN sys. indexes AS i
ON ps.object-id = i.object-id
AND ps.index-id = i.index-id
WHERE avg_fragmentation_in_percent > 30
OPEN TableCursor
FETCH NEXT FROM TableCursor INTO @SchemaName, @TableName,
@IndexName,
@Fragmentation

WHILE @@ FETCH_STATUS = 0
BEGIN
PRINT ‘Reindexing’ + ISNULL ( @SchemaName, ‘dbo’) + ‘. ’ +
@TableName + ‘. ’ + @ IndexName
SET @Command = ‘ALTER INDEX [‘ + @IndexName + ’] ON [ ‘ +
ISNULL ( @SchemaName, ‘dbo’) + ‘. ’ + @TableName + ’]
REBUILD'
EXEC ( @Command)
FETCH NEXT FROM TableCursor
INTO @SchemaName, @TableName, @IndexName,
@Fragmentation
END
CLOSE TableCursor
DEALLOCATE TableCursor

EPITOME
SQL Server 2005 99

We have now done what would be impossible using only set based commands. The ALTER
INDEX command is expecting a single argument-providing that a recordset won’t work. We
get around the problem by combining the notion of a set operation (the SELECT that forms
the basis for the cursor) with single-data-point operations (the data in the cursor).
In order to mix these set based and individual data point operations, we had to walk through
a series of steps.
First, we declared the cursor and any necessary holding variables.We then “opened” the
cursor-- it was not until this point that the data was actually retrieved from the database.
Next, we utilized the cursor by navigating through it. In this case, we only navigated forward,
but, as we shall see, we could have created a cursor that could scroll forward and backward.
Moving on, we closed the cursor (if the cursor had still had any open locks, they were re-
leased at this point), but memory continues to be allocated for the cursor. Finally, we
deallocated the cursor. At this point, all resources in use by the cursor are freed for use by
other objects in the system.

So just that quick, we have our first cursor. Still, this is really only the beginning. There is
much more to cursors than meets the eye in this particular example. Next, we’ll go on and
take a closer look at some of the powerful features that give cursors additional flexibility.

Types of Cursors and Extended Declaration Syntax

Cursors come in a variety of different flavors . The default cursor is forward-only (you can
only move forward through the records, not backward) and read-only, but cursors can also
be scrollable and updatable. They can also have a varying level of sensitivity to changes that
are made to the underlying data by other processes.

The forward-only, read-only cursor is the default type of cursor in not only the native
SQL Server cursor engine, but is also default from pretty much all the cursor models. It is
extremely low in overhead, by comparison, to the other cursor choices, and is usually re-
ferred to as being a “firehose” cursor because of the sheer with which you can enumerate
the data. Like a firehose, it knows how to dump its contents in just one direction. Firehose
cursors simply blow away the other cursor-based options in most cases, but don’t mistake
this as a performance choice over set operations-even a firehose cursor is slow by compari-
son to most equivalent set operations.
Let’s start out by taking a look at a more extended syntax for cursors, and then we’ll look at
all of the options individually:
EPITOME
SQL Server 2005 100

DECLARE < cursor name> CURSOR


[ LOCAL /G LOBAL]
[FORWARD_ONLY/ SCROLL]
[STATIC| KEYSET | DYNAMIC | FAST_FORWARD]
[READ_ONLY | SCROLL_LOCKS | OPTIMISTIC]
[ TYPE_WARNING]
FOR < SELECT statement>
[FOR UPDATE [OF < column name > [,.....n] ] ]

At first glance, it really looks like a handful, and indeed are a good many things to think about
when declaring cursors . The bright side is that several of these options imply one another,
so once you`ve made one choice the others often start to fall into place quickly.
Let`s go ahead and apply the specific syntax in a step manner that attaches each part to the
important concepts that go with it.

Scope
The LOCAL versus GLOBAL option determines the scope of the cursor, that is what
connections and processes can “see” the cursor. Most items have scope will default to the
more conservative approach, that is, the mininum scope (which would be LOCAL in this
case). SQL Server cursors are something of an exception to this-the default is actually
GLOBAL.
We are already dealing with something of an exception in that the default scope is set to
what we`re calling global rather than the more conservative option of local. The exception
doesn’t stop there though. In SQL Server, the notion of something being global versus local
usually indicates that it can be seen by all connections rather than just the current connection.
For the purposes of our cursor declaration, however, it refers to whether all processes (batches,
triggers, spocs) in the current connection can see it versus just the current process.

Now let`s think about what this means, and test it a bit.
The ramifications to the global default fall, as you might expect, on both the pro and the con
side of the things. Being global, it means that you can create a cursor within one sproc and
refer to it from within a separate sproc-you don’t necessarily have to pass references to it.
The downside of this though is that, if you try to create another cursor with the same name,
you’re going to get an error.
Let`s test this out with a brief sample. what we`re going to do here create a sproc that will
create a cursor for us :
EPITOME
SQL Server 2005 101

USE AdventureWords
GO

CREATE PROCEDURE spCursorScope


AS

DECLARE @Counter int,


@Order ID int,
@Customer ID int

DECLARE CursorTest CURSOR


GLOBAL
FOR
SELECT SalesOrderID, CustomerID
FROM Sales.SalesOrderHeader

SELECT @Counter = 1
OPEN CursorTest
FETCH NEXT FROM CursorTest INTO @OrderID, @CustomerID
PRINT ‘Row’ + CAST ( @Counter AS varchar) + ‘ has a SalesOrderID of ‘ +
CONVERT (varchar, @OrderID) + ’ and a CustomerID of ‘ + CAST
(@CustomerID AS varchar)

WHILE (@Counter < =5) AND (@@FETCH_STATUS=0)


BEGIN
SELECT @Counter= @Counter + 1
FETCH NEXT FROM CursorTest INTO @OrderID, @CustomerID
PRINT ‘ Row ’ + CAST (@Counter AS varchar) + ‘has a SalesOrderID of ’ +
CONVERT (varchar, @OrderID) + ‘ and a CustomerID of ’ +
CAST (@ Customer ID AS varchar)
END
Notice several things in this sproc. First, we`ve declared holding variables to do a few
things for us. The first, @Counter, will just keep tabs on things so we only have to
move through a few records rather than moving through the entire recordset. The
second and third, @ OrderID and @CustomerID, respectively, will hold the values
retrieved from the query as we go row by row through the result set.
EPITOME
SQL Server 2005 102

Next, we declare the actual cursor. By default, if we had left off the GLOBAL, keyword,
then we would have still received a cursor that was global in scope.

You do not have to live by this default. You can use sp_dboption or ALTER DATABASE to set
the “ default to local cursor” option to True (set it back to False if you want to go back to
global).

We then go ahead and open the cursor and step through serveral records. Notice, however,
that we do not close or deallocate the cursor-we just leave it open and available as we exit
the sproc.

When we look declaring our cursor for output, we will see a much more explicit and better
choice for situations where we want to allow outside interaction with our cursors.
Now that we`ve enumerated several records and proven that our sproc is operating, we will
then exit the sproc (remember, we haven’t closed or deallocated the cursor). We’ll then refer
to the cursor from outside the sproc:

EXEC spCursorScope

DECLARE @Counter int,


@OrderID int,
@CustomerID int
SET @Counter =6

WHILE ( @Counter <=10) AND ( @@ FETCH_STATUS=0 )


BEGIN
PRINT ‘Row ’ + CAST ( @Counter AS varchar) + ‘ has a SalesOrderID of ’ +
CAST ( @OrderID AS varchar) + ‘ and a CustomerID of ’ +
CAST ( @CustomerID AS varchar)
SELECT @Counter= @Counter +1
FETCH NEXT FROM CursorTest INTO @OrderID, @CustomerID
END

CLOSE CursorTest

EPITOME
SQL Server 2005 103

DEALLOCATE CursorTest
First, we execute the sproc. As we`ve already seen, sproc builds the cursor and then enu-
merates several rows. It exits, leaving the cursor open.

Next, we declare the very same variables that were declared in the sproc. Why do we have
to declare them again, but not the cursor? Because it is only the cursor that is global by
default. That is, our variables went away as soon as the sproc went out of scope-we can’t
refer to them anymore, or we’ll get a variable undefined error. We must redeclare them.
The next code structure looks almost identical to one in our sproc-we`re again looping through
to enumerate several records.
Finally, once we`ve proven our point that the cursor is still alive outside the realm of the
sproc, we`re ready to close and deallocate the cursor. It is not untill we close the cursor that
we free up the memory or tempdb space from the result set used in the cursor, and it is not
until we deallocate that the memory taken up by the cursor variable and its query definition is
freed.
Now, go ahead and create the sproc in the system and execute the script. You should wind
up with a result that looks like this:
Row 1 has a SalesOrderID of 43659 and a CustomerID of 676
Row 2 has a SalesOrderID of 43660 and a CustomerID of 117
Row 3 has a SalesOrderID of 43661 and a CustomerID of 442
Row 4 has a SalesOrderID of 43662 and a CustomerID of 227
Row 5 has a SalesOrderID of 43663 and a CustomerID of 510
Row 6 has a SalesOrderID of 43664 and a CustomerID of 397

Row 7 has a SalesOrderID of 43665 and a CustomerID of 146


Row 8 has a SalesOrderID of 43666 and a CustomerID of 511
Row 9 has a SalesOrderID of 43667 and a CustomerID of 646
Row 10 has a SalesOrderID of 43668 and a CustomerID of 514

So, you can see that the cursor stayed open, and our loop outside the sproc was able to pick
up right where the code inside the sproc had left off.

Now let`s see what happens if we alter our sproc to have local scope:
USE AdventureWorks
GO

EPITOME
SQL Server 2005 104

ALTER PROCEDURE spCursorScope


AS
DECLARE @Counter int,
@OrderID int,
@CustomerID int
DECLARE CursorTest CURSOR
LOCAL
FOR
SELECT SalesOrderID, CustomersID
FROM Sales.SalesOrderHeader

SELECT @Counter =1
OPEN CursorTest
FETCH NEXT FROM CursorTest INTO @OrderID, @CustomerID
PRINT ‘ Row ’ + CAST @Counter AS varchar) + ‘ has a SalesOrderID of ’ +
CAST (@OrderID AS varchar) + ’ and a CustomerID of ’ + CAST (@CustomerID
AS varchar)

WHILE ( @Counter <=5) AND ( @@FETCH_STATUS=0 )


BEGIN
SELECT @Counter = @Counter +1
FETCH NEXT FROM CursorTest INTO @OrderID, @CustomerID
PRINT ‘ Row ’ + CAST ( @Counter AS varchar ) + ‘ has a SalesOrderID
of ’ +
CAST ( @OrderID AS varchar) + ’ and a CustomerID of ’ +
CAST ( @CustomerID AS
varchar)
END

Row 1 has a SalesOrderID of 43659 and a CustomerID of 676


Row 2 has a SalesOrderID of 43660 and a CustomerID of 117
Row 3 has a SalesOrderID of 43661 and a CustomerID of 442
Row 4 has a SalesOrderID of 43662 and a CustomerID of 227

EPITOME
SQL Server 2005 105
Row 5 has a SalesOrderID of 43663 and a CustomerID of 510
Row 6 has a SalesOrderID of 43664 and a CustomerID of 397

Msg 16916, Level 16, State 1, Line 13


A Cursor with the name ‘CursorTest’ does not exist.
Msg 16916, Level 16, State 1, Line 17
A Cursor with the name ‘CursorTest’ does not exist.
Msg 16916, Level 16, State 1, Line 18
A Cursor with the name ‘CursorTest’ does not exist.
Things ran just as they did before until we got out of the sproc. This time the cursor was no
longer in scope as we came out of the sproc, so we were unable to refer to it, and our script
ran into several errors.

The big thing that you should have gotten out of this section is that you need to think about
the scope of your cursors. They do not behave quite the way that other items for which you
use the DECLARE statement do.

Scrollability
Scrollability applies to pretty much any cursor model you might face. The notion is
actually fairly simple. Can we navigate in relatively any direction, or are we limited to only
moving forward? The default is no-we can only move forward.

FORWARD_ONLY
A forward-only cursor is exactly what it sounds like. Since it is default method, it
probably doesn’t surprise you to hear that it is the only type of cursor that we`ve been using
up to this point. When you are using a forward-only cursor, the only navigation option that is
valid is FETCH NEXT. You need to be sure that you`re done with each record before you
move onto the next because, once it`s gone, there`s no getting back to the previous record
unless you close and reopen the cursor

SCROLLABLE
Again, this is just as it sounds. You “scroll” the cursor backward and forward as
necessary. If you`re using one of the APIs (ODBC, OLE DB, DB-Lib), then, depending on
what object model you`re dealing with, you can often navigate right to a specific record.
Indeed, with ADO and ADO. NET you can even easily resort the data and add additional

EPITOME
SQL Server 2005 106
filters.

The cornerstone of scrolling is the FETCH keyword. You can use FETCH to move forward
and backward through the cursor, as well as move to specific positions. The main arguments
to FETCH are:

NEXT- Move to the next record

PRIOR- Move to the previous record.

FIRST-Move to the first record.

LAST-Move to the last record.

Let`s do a brief example to get across the concept of a scrollable cursor. We`ll actually just
use a slight variation of the sproc we created a little earlier.

USE AdventureWorks
GO

CREATE PROCEDURE spCursorScope


AS

DECLARE @Counter int,


@OrderID int,
@CustomerID int
DECLARE CursorTest CURSOR
LOCAL
SCROLL
FOR
SELECT SalesOrderID, CustomersID
FROM Sales.SalesOrderHeader

SELECT @Counter =1
OPEN CursorTest
EPITOME
SQL Server 2005 107

FETCH NEXT FROM CursorTest INTO @OrderID, @CustomerID


PRINT ‘ Row ’ + CAST ( @Counter AS varchar) + ‘ has a SalesOrderID of ’ +
CAST ( @OrderID AS varchar) + ’ and a CustomerID of ’ + CAST (
@CustomerID AS
varchar)

WHILE ( @Counter<=5) AND ( @@FETCH_STATUS=0 )


BEGIN
SELECT @Counter = @counter +1
FETCH NEXT FROM CurserTest INTO @OrderID,@CustomerID
PRINT ‘ Row ’ + CAST(@Counter AS varchar) + ‘ has a SalesOrderID
of ‘ +
CAST( @OrderID AS varchar) + ‘ and a CustomerID of ‘ +
CAST(@CustomerID
AS varchar)
END

WHILE ( @ Counter < =1 ) AND (@@FETCH_STATUS = 0)


BEGIN
SELECT @Counter = @Counter - 1
FETCH PRIOR FROM CursorTest INTO @OrderID, @CustomerID
PRINT ‘ Row ’ + CONVERT ( varchar, @Counter) + ‘ has an
SalesOrderID of ’ +
CAST (@OrderID AS varchar) + ‘ and a CustomerID of ’ + CAST (
@CustomerID AS
varchar)
END

CLOSE CursorTest
DEALLOCATE CursorTest

The big differences are :


The cursor is declared with the SCROLL option
We added a new navigation keyword ---------- PRIOR---------in the place of NEXT.
EPITOME
SQL Server 2005 108

We went ahead and closed and deallocated the cursor in the sproc rather than
using
an outside procedure.
The interesting part comes in the results.
EXEC spCursorScro11
And you`ll see how the order values scroll forward and back:

Row 1 has a SalesOrderID of 43659 and a CustomerID of 676


Row 2 has a SalesOrderID of 43660 and a CustomerID of 117
Row 3 has a SalesOrderID of 43661 and a CustomerID of 442
Row 4 has a SalesOrderID of 43662 and a CustomerID of 227
Row 5 has a SalesOrderID of 43663 and a CustomerID of 510
Row 6 has a SalesOrderID of 43664 and a CustomerID of 397
Row 5 has a SalesOrderID of 43663 and a CustomerID of 510
Row 4 has a SalesOrderID of 43662 and a CustomerID of 227
Row 3 has a SalesOrderID of 43661 and a CustomerID of 442
Row 2 has a SalesOrderID of 43660 and a CustomerID of 117
Row 1 has a SalesOrderID of 43659 and a CustomerID of 676

As you can see, we were able to successfully navigate not only forward, as we did before,
but also backward.

A forward-only cursor is far and away the more efficient choice of the two options. Think
about the overhead for a moment--if it is read-only, then SQL Server really needs to keep
track of the next record only- a linked list. In a situation where you may reposition the cursor
in other ways, extra information must be stored in order to reasonably seek out the re-
quested row. How exactly this is implemented depends on the specific cursor options you
choose.

Some types of cursors imply scrollability; others do not. Some types of cursors are sensitive
to changes in the data, and some are not.

Cursor Types
The various APIs generally break cursors into types :
Static
Keyset driven
EPITOME
SQL Server 2005 109

Dynamic
Forward-only
How exactly these four types are implemented (and what, they`re called) will something vary
slightly among the various APIs and object models, but their general nature is usually pretty
much the same.

What makes the various cursor types different is their ability to be scrollable and their sensi-
tivity to changes in the database over the life of the cursor.

Whether a cursor is sensitive or not defines whether if notices changes in the database or
not after the cursor is opened. It also defines just what it does about it once the change is
detected. Let`s look at this in its most extreme versions-static versus dynamic cursor, how-
ever, is effectively aware of every change (inserted records, deletions, updates, you name it)
to the database as long as the cursor remains open. We`ll explore the sensitivity issue as
we look at each of the cursor types.

Static Cursors
A static cursor is one that represents a “ snapshot” in time. Indeed, at least one of
the data access object models refers to it as a snapshot recordset rather than a static one.

When a static cursor is created, the entire recordset is created in what amounts to a tempo-
rary table in tempdb. After the time that it`s created,a static cursor changes for no one .
Some of the different object models will let you update information in a static cursor, some
won`t, but the bottom line is always the same: you cannot write updates to the database via
a static cursor.

Static cursor is kept by SQL Server in a private table in tempdb. If that`s how SQL Server is
going to be storing it anyway, why not just use a temporary table yourself? There are times
when that won`t give you what you need (record rather than set operations). However, If you
are just after the concept of a snapshot in time, rather than record-based operations , build
your own temp table using SELECT INTO and save yourself (and SQL Server) a lot of
overhead.

If you`re working in a client-server arrangement, static cursors are often better dealt with on
the client side. By moving the entire operation to the client, you can cut the number of net-
work
EPITOME
SQL Server 2005 110

roundtrips to the server substantially. Since you know that your cursor isn`t going to be
affected by changes to the database, there`s no reason to make contact with the server
again regarding the cursor after it is created.
Let us take this example:

USE AdventureWorks
/* Build the table that we`ll be playing with this time*/
SELECT SalesOrderID, CustomerID
INTO CursorTable
FROM Sales.SalesOrderHeader
WHERE SalesOrderID BETWEEN 43661 AND 43665

DECLARE CursorTest CURSOR


GLOBAL
SCROLL
STATIC
FOR
SELECT SalesOrderID, CustomerID
FROM CursorTable

DECLARE @SalesOrderID int


DECLARE @CustomerID varchar (5)

OPEN CursorTest
FETCH NEXT CursorTest INTO @SalesOrderID, @CustomerID
- - Now loop through them all
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT CAST (@SalesOrderID AS varchar) + ‘ ’ + @CustomerID
FETCH NEXT FROM CursorTest INTO @SalesOrderID, @CustomerID
END

UPDATE CursorTable
SET CustomerID = -111
WHERE SalesOrderID = 43663
EPITOME
SQL Server 2005 111

SELECT SalesOrderID, CustomerID


FROM CursorTable

FETCH FIRST FROM CursorTest INTO @SalesOrderID, @CustomerID

WHILE @FETCH_STATUS = 0
BEGIN
PRINT CONVERT ( varchar (5) @SalesOrderID ) + ‘ ’ + @CustomerID
FETCH NEXT FROM CursorTest INTO @SalesOrderID, @CustomerID
END

CLOSE CursorTest

DEALLOCATE CursorTest

DROP TABLE CursorTable

Let`s take a look at what this gets us:


(5 row (s) affected)
43661 442
43662 227
43663 510
43664 397
43665 146

(1 row (s) affected)


SalesOrderID CustomerID
43661 442
43662 227
43663 -111
43664 397
43665 146

(5 row (s) affected)

EPITOME
SQL Server 2005 112

43661 442
43662 227
43663 510
43664 397
43665 146

There are several things to notice about what happened during the run on this script.
First, even though we had a result set open against the table, we were still able to
perform the update. In this case, it`s because we have a static cursor-once it was created, it
was disconnected from the actual records and no longer maintains any locks.
Second, although we can clearly see that our update did indeed take place in the
actual table, it did not affect the data in our cursor. Again, this is because, once created, our
cursor took on something of a life of its own-it is no longer associated with the original data
in any way.
Under the heading of “ one more thing,” you could also notice that we made use of
a new argument to the FETCH keyword-this time we went back to the top of our result set by
using FETCH FIRST.

Keyset-Driven Cursors
We`re talking about maintaining a set of data that uniquely identifies the entire row
in the database.
Keyset-driven cursors have the following high points:
They require a unique index to exist on the table question.
Only the keyset is stored in tempdh-not the entire dataset.
They are sensitive to changes to the rows that are already part of the keyset, including
the possibility that they have been deleted.
They are, however, not sensitive to new rows that are added after the cursor is
created.
Keyset cursors can be used as the basis for a cursor that is going to perform updates
to the data.
Given that it has a name of “keyset” and that I`ve already said that the keyset uniquely
identifies each row, it probably doesn’t shock you in any way that you must have a unique
index of some kind (usually a primary key, but it could also be any index that is explicitly
defined as unique) to create the keyset from.

The keys are all stored in a private table in tempdb. SQL Server uses this key as a method
EPITOME
SQL Server 2005 113

to find its way back to the data as you ask for a specific row in the cursor. The point to take
note of here is that the actual data is being fetched, based on the key, at the time that you
issue the FETCH. The great part about this is that the data for that particular row is up to date
as of when the specific row is fetched. The downside (or upside depending on what you`re
using the cursor for) is that keyset that is already created to do the lookup. This means that
once the keyset is created, that is all the rows that will be included in your cursor. Any rows
that were added after the cursor was created--even if they meet the conditions of the WHERE
clause in the SELECT statement-will not be seen by the cursor. The rows that are already
part of the cursor can, depending on the cursor options you chose, be updated by a cursor
operation.

Let`s modify our earlier script to illustrate the sensitivity issue when we are making use of
keyset-driven cursors:

USE AdventureWorks
/* Build the table that we`ll be playing with this time*/
SELECT SalesOrderID, CustomerID
INTO CursorTable
FROM Sales.SalesOrderHeader
WHERE SalesOrderID BETWEEN 43661 AND 43665

ALTER TABLE CursorTable


ADD CONSTRAINT PKCursor
PRIMARY KEY (SalesOrderID)

/* The IDENTITY property was automatically brought over when


** we did our SELECT INTO, but I want to use my own SalesOrderID
** value, so I’m going to turn IDENTITY_INSERT on so that I
** can override the identily value.
*/
SET IDENTITY_INSERT CursorTable ON

DECLARE CursorTest CURSOR


GLOBAL
SCROLL
KEYSET
EPITOME
SQL Server 2005 114

FOR
SELECT SalesOrderID, CustomerID
FROM CursorTable
DECLARE @SalesOrderID int
DECLARE @CustomerID varchar (5)

OPEN CursorTest
FETCH NEXT FROM CursorTest INTO @SalesOrderID, @CustomerID

WHILE @@FETCH_STATUS = 0
BEGIN
PRINT CAST (@SalesOrderID AS varchar) + ‘ ’ + @CustomerID
FETCH NEXT FROM CursorTest INTO @SalesOrderID, @CustomerID
END
UPDATE CursorTable
SET CustomerID = -111
WHERE SalesOrderID = 43663
DELETE CursorTable
WHERE SalesOrderID = 43664

INSERT INTO CursorTable ( SalesOrderID, CustormerID ) VALUES ( -99999, -99999 )

SELECT SalesOrderID, CustomerID FROM CursorTable


FETCH FIRST FROM CursorTest INTO @SalesOrderID, @CustomerID

/*And loop through again.


** This time, notice that we changed what we`re testing for.
** Since we have the possibility of rows being missing (deleted)
** before we get to the end of the actual cursor, we need to do
** a little bit more refined testing of the status of the cursor.
*/

WHILE @@FETCH_STATUS! = -1
BEGIN
IF @@FETCH_STATUS = -2
BEGIN
EPITOME
SQL Server 2005 115

PRINT ' MISSING! It probably was deleted. '


END
ELSE
BEGIN
PRINT CAST ( @SalesOrderID AS varchar) + ‘ ‘ + CAST (
@CustomerID AS
varchar)
END
FETCH NEXT FROM CursorTest INTO @SalesOrderID, @CustomerID
END
CLOSE CursorTest

DEALLOCATE CursorTest

DROP TABLE CursorTable


The changes aren`t really all that remarkable. We`ve gone ahead and added the required
unique index . I happened to choose to do it as a primary key since that`s what matches up
best with the table we got this information out of, but it also could have been a unique index
without the primary key. We also added something to insert a row of data so we can clearly
see that the keyset doesn`t see the row in question.

Perhaps the most important thing that we`ve changed is the condition for the WHILE loop on
the final run through the cursor. Technically speaking, we should have made this change to
both loops, but there is zero risk of a deleted record the first time around in this example, and
I wanted the difference to be visible right within the same script.

The change was made to deal with something new we`ve added--the possibility that we
might get to a record only to find that it`s now missing. More than likely, someone has deleted
it.

Let`s take a look then at the results we get after running this:

(5 row (s) affected)


43661 442

EPITOME
SQL Server 2005 116

43662 227
43663 510
43664 397
43665 146

(1 row (s) affected)

(1 row (s) affected)

(1 row (s) affected)


SalesOrderID CustomerID
..................... ......................
-99999 -99999
43661 442
43662 227
43663 -111
43665 146

(5 row (s) affected)

43661 442
43662 227
43663 -111
MISSING! It probably was deleted.

43665 146
Okay, let`s walk through the highlights here.

Everything starts out pretty much as it did before. We see the same five rows in the result set
as we did last time. We then see an extra couple of “affected by” messages-these are for the
INSERT, UPDATE, and DELETE statement that we added. Next comes the second result
set. It`s at this point that things get a bit more interesting.

EPITOME
SQL Server 2005 117

In this we`re result set, we see the actual results of our UPDATE, INSERT and DELETE
statements. Just as we think we`re done, SalesOrderID 43664 has been deleted, and a new
order with the SalesOrderID of -99999 has been inserted. That’s what’s in the table, but
things don’t appear quite as cozy in the cursor.

The next (and final) result set tells the tale on some differences in the way that things are
presented in the cursor versus actually re-running the query. As it happens, we have exactly
five rows-- just like we started out with and just like our SELECT statement showed are in the
actual table. But that’s entirely coincidental.

In reality, there are a couple of key differences between what the cursor is showing and what
the table is showing. The first presents itself rather boldly-our result set actually knows that a
record is missing. The cursor continues to show the key position in the keyset, but, when it
went to do the lookup test on the data, the data wasn’t there anymore. Our
@@FETCH_STATUS was set to-2, and we were able to test for it and report it. The SELECT
statement showed us what data was actually there without any remembrance of the record
ever having been there . The INSERT, on the other hand, is an entirely unknown quantity to
the cursor. The record wasn`t there when the cursor was created, so the cursor has no
knowledge of its existence--it doesn`t show up in our result set.

Keyset cursors can be very handy for dealing with situations where you need some sensitiv-
ity to changes in the data, but don`t need to know about every insert right up to the minute.
They can, depending on the nature of the result set you`re after and the keyset, also provide
some substantial savings in the amount of data that has to be duplicated and stored into
tempdb-this can have some favorable performance impacts for your overall server.

Dynamic Cursors
Dynamic cursors fall just short of dynamic in the sense that they won`t proactively
tell you about changes to the underlying data. What gets them close enough to be called
dynamic is that they are sensitive towards all changes to the underlying data.

In order to understand some of the impacts that a dynamic cursor can have, you just need to
realize a bit about how they work. You see, with a dynamic cursor, your cursor is essentially

EPITOME
SQL Server 2005 118

rebuilt every single time you issue a FETCH . The SELECT statement that forms the basis of
your query, complete with its associated WHERE clause is effectively re-run.

The dynamic cursor can actually be slightly faster in terms of raw speed because it uses the
tempdh for keyset cursors. While a lot more work has to be done with each FETCH in order
to deal with a dynamic cursor, the data for requery will often be completely in cache (depend-
ing on the sizing and loading of your system) This means the dynamic cursor gets to work
largely from RAM. The keyset cursor, on the other hand is stored in tempdb, which is on disk
(that is, much, much slower) for most system.

As your table size gets larger, there is more diverse traffic hitting your server, the memory
allocated to SQL Server gets smaller, and the more that keyset-driven cursors are going to
have something of an advantage over dynamic cursors.

Let`s go ahead and re-run our last script with only modificaton--the change from KEYSET to
DYNAMIC:

USE AdventureWorks
/* Build the table that we`ll be playing with this time*/

SELECT SalesOrderID, CustomerID


INTO CursorTable
FROM Sales.SalesOrderHeader
WHERE SalesOrderID BETWEEN 43661 AND 43665
ALTER TABLE CursorTable
ADD CONSTRAINT PKCursor
PRIMARY KEY (SalesOrderID)

/* The IDENTITY property was automatically brought over when


** We did our SELECT INTO, but I want to use my own SalesOrderID
** value, so I’m going to turn IDENTITY_INSERT on so that I
** can override the identily value.
*/
SET IDENTITY_INSERT CursorTable ON

EPITOME
SQL Server 2005 119

DECLARE CursorTest CURSOR


GLOBAL
SCROLL
DYNAMIC
FOR
SELECT SalesOrderID, CustomerID
FROM CursorTable

DECLARE @SalesOrderID int


DECLARE @CustomerID varchar (5)

OPEN CursorTest
FETCH NEXT CursorTest INTO @SalesOrderID, @CustomerID

WHILE @@FETCH_STATUS = 0
BEGIN
PRINT CAST (@SalesOrderID AS varchar) + ‘ ’ + @CustomerID
FETCH NEXT FROM CursorTest INTO @SalesOrderID, @CustomerID
END

UPDATE CursorTable
SET CustomerID = -111
WHERE SalesOrderID = 43663

DELETE CursorTable
WHERE SalesOrderID = 43664

INSERT INTO CursorTale


(SalesOrderID, CustormerID)
VALUES
(-99999, -99999)

SELECT SalesOrderID, CustomerID


FROM CursorTable

FETCH FIRST FROM CursorTest INTO @SalesOrderID, @CustomerID

EPITOME
SQL Server 2005 120
/*And loop through again.
** This time, notice that we changed what we`re testing for.
** Since we have the possibility of rows being missing (deleted)
** before we get to the end of the actual cursor, we need to do
** a little bit more refined testing of the status of the cursor.
*/

WHILE @@FETCH_STATUS ! = -1
BEGIN
IF @@FETCH_STATUS = -2
BEGIN
PRINT ‘ MISSING! It probably was deleted.'
END
ELSE
BEGIN
PRINT CAST ( @SalesOrderID AS varchar) + ‘ ’ + CAST(@CustomerID
AS varchar)
END
FETCH NEXT FROM CursorTest INTO @SalesOrderID, @CustomerID
END

CLOSE CursorTest

DEALLOCATE CursorTest

DROP TABLE CursorTable

And the result s:

(5 row (s) affected)


43661 442
43662 227
43663 510
43664 397
43665 146

(1 row (s) affected)


EPITOME
SQL Server 2005 121

(1 row (s) affected)

(1 row (s) affected)


SalesOrderID CustomerID
..................... ....................
-99999 -99999
43661 442
43662 227
43663 -111
43665 146

(5 row (s) affected)

-99999 *
43661 442
43662 227
43663 -111
43665 146

The first two recordsets look exactly as thay did last time. Change comes when we get to the
third (and final) result set:
-There is no indication of a failed fetch, even though we deleted a record (no notification).
-The updated record shows the update (just as it did with a keyset).
-The inserted record now shows up in the cursor set.
Dynamic cursors are the most sensitive of all cursors. They are affected by everything you
do to the underlying data. The downside is that they can provide some extra concurrency
problems, and they can pound the system when dealing with larger data sets.

FAST_FORWARD Cursorsrs
Fast is the operative word on this one. This one is the epitome of term “firehose
cursor” that is often used around forward only cursors. With FAST_FORWARD cursors, you
open the cursor, and do nothing else but deal with the data, move forward, and deallocate it.

Now, it`s safe to say that calling this a cursor “type” is something of a misnomer. This kind of
cursor has several different circumstances where it is automatically converted to other cursor

EPITOME
SQL Server 2005 122

types, but I think of them as being most like a keyset-driven cursor in the sense that
membership is fixed-once the members of the cursor are established, no new records are
added. Deleted rows show up as a missing record (@@FETCH_STATUS of -2).

There are a number of circumstances where FAST_FORWARD cursor is implicitly converted


to another cursor type. Below is a table that outlines these conversions:

Condition Converted to

The underlying query requires that a temporary table be built Static


The underlying query is distributed in nature Keyset
The cursor is declared as FOR UPDATE Dynamic
A condition exists that would convert to keyset driven but at
least one underlying table does not have a unique index Static

It`s worth noting that all FAST_FORWARD cursors are read-only in nature. You can explicity
set the cursor to have the FOR UPDATE option, but, as suggested in the preceding implicit
conversion table, the cursor will be implicitly converted to dynamic.

What exactly does a FAST_FORWARD cursor have that any of the other cursors wouldn`t
have if they were declared as being FORWARD_ONLY? Well, a FAST_FORWARD cursor
will implement at least one of two tricks to help things along:
The first is pre-fetch data. That is, at the same time that you open the cursor, it
automatically fetches the first now-this means that you save a roundtrip to the server if you
are operating in a client-server environment using ODBC. Unfortunately, this is available
only under ODBC.
The second is the one that is a sure thing-auto-closing of the cursor. Since you are
running a cursor that is forward-only, SQL Server can assume that you want the cursor
closed once you reach the end of the recordset. Again, this saves a roundtrip and squeezes
out a tiny bit of additional performance.

Choosing a cursor type is one of the most critical decisions when structuring a cursor. Choices
that have little apparent difference in the actual output of the cursor task can have major
differences in performance. Other affects can be seen in sensitivity to changes, concurrency
issues, and updatability.

EPITOME
SQL Server 2005 123

Concurrency Options
We got our first taste of concurrency issues under the topic transactions and locks. We deal
with concurrency issues whenever there are issues surrounding two or more processes
trying to get to the same data at essentially the same time. When dealing with cursors,
however, the issue becomes just slightly stickier.

The problem is multi-fold:


The operation tends to last longer (more time to have a concurrency problem).
Each row is read at the time of the fetch, but someone may try to edit it before you
get a chance to do your update.
You may scroll forward and backward through the result set for what could be an
essentially unlimited amout of time.

As with all concurrency issues, this tends to be more of a problem in a transaction environ
ment than when running in a single statement situation. The longer the transaction, the more
likely you are to have concurrency problems.

SQL Server gives us three different options for dealing with this issue:
READ_ONLY
SCROLL_LOCKS (equates to Pessimistic in most terminologies)
OPTIMISTIC

READ_ONLY
In a read-only situation, you don`t have to worry about whether your cursor is going to try and
obtain any kind of update or exclusive lock. You also don`t have to worry about whether
anyone has edited the data while you`re been busy making changes of your own. Both of
these make life considerably easier.

READ_ONLY is just what it sounds like. When you choose this option, you cannot update
any of the data, but you also skip most (but not all) of the notion of concurrency entirely.

SCROLL_LOCKS
Scroll locks equate to what is more typically referred to as pessimistic locking in the various
APIs and object models. In its simplest form, it means that, as long as you are editing this
record, no one else is allowed to edit it. The specifics of implementation of duration of this
vary depending on:

EPITOME
SQL Server 2005 124

Whether you`re in a transaction or not


What transaction isolation level you`ve set

With update locks, we prevented other users from updating the data. This lock was held for
the duration of the transaction. If it was a single statement transaction, then the lock was not
released until every row affected by the update was complete.

Scroll locks work identically to update locks with only one significant exception-the duration
the lock is held. With scroll locks, there is much more of a variance depending on whether
the cursor is participating in a multi-statement transaction or not. Assuming for the moment
that you do not have a transaction wrapped around the cursor, then the lock is held only on
the current record in the cursor-that is, from the time the record is first fetched until the next
record (or end of the result set) is fetched. Once you move on to the next record, the lock is
removed from the prior record.

Let`s take a look at this through an example:

USE AdventureWorks
/* Build the table that we`ll be playing with this time*/
SELECT SalesOrderID, CustomerID
INTO CursorTable
FROM Sales.SalesOrderHeader
WHERE SalesOrderID BETWEEN 43661 AND 43665

ALTER TABLE CursorTable


ADD CONSTRAINT PKCursor
PRIMARY KEY (SalesOrderID)

/* The IDENTITY property was automatically brought over when


** We did our SELECT INTO, but I want to use my own SalesOrderID
** value, so I’m going to turn IDENTITY_INSERT on so that I
** can override the identily value.
*/
SET IDENTITY_INSERT CursorTable ON

EPITOME
SQL Server 2005 125

DECLARE CursorTest CURSOR


GLOBAL - - So we can manipulate it outside the batch
SCROLL - - So we can scroll back and see the changes
DYNAMIC - - This is what we`re testing this time
SCROLL_LOCKS
FOR
SELECT SalesOrderID, CustomerID
FROM CursorTable

DECLARE @SalesOrderID int

DECLARE @CustomerID varchar (5)

OPEN CursorTest
FETCH NEXT FROM CursorTest INTO @SalesOrderID, @CustomerID

What we`ve done is toss out most of the things that were happening, and we`ve refocused
ourselves back on the cursor. Perhaps the biggest think to notice though is a couple of key
things that we have deliberately omitted even though they are things that would normally
cause problems if we try to operate without them:

 We do not have a CLOSE on our cursor, nor do deallocate it at this point.


 We don`t even scroll any further than getting the first row fetched.

The reason we`ve left the cursor open is to create a situation where the state of the cursor
being open lasts long enough to play around with the locks somewhat. In addition, we fetch
only the first row because we want to make sure that there is an active row.

What you want to do is execute the preceding and then open a completely separate connec-
tion window with AdventureWorks active. Then run a simple test in the new connection
window:

SELECT * FROM CursorTable

EPITOME
SQL Server 2005 126

SalesOrderID CustomerID
------------------- ---------------------
43661 442
43662 227
43663 510
43664 397
43665 146

(5 row (s) affected)

Based on what we know about locks you would probably expect the preceding SELECT
statement to be blocked by the locks on the current record. Not so scroll locks. The lock is
only on the record that is currently in the cursor, and perhaps more importantly, the lock only
prevents updates to the record. Any SELECT statements can see the contents of the cursor
without any problems.

CLOSE CursorTest

DEALLOCATE CursorTest

DROP TABLE CursorTable

Don`t forget to run the preceding clean up code !!! If you forget, than you`ll have an open
transaction sitting in your system until you terminate the connection. SQL Server should
clean up any open transaction (by rolling them back) when the connection is broken.

OPTIMISTIC
Optimistic locking creates situation where no scroll locks of any kind are set on the cursor.
The assumption is that, if you do an update, you want people to still be able to get at your
data. You`re being optimistic because you are essentially guessing that no one will edit your
data between when you fetched it into the cursor and when you applied your update.

The optimism is not necessarily misplaced. If you have a lot a records and not that many
user, then the chances of two people trying to edit the same record at the same time are very
small. Still, if you get this optimistic, then you need to also be prepared for the possibility that
you will be wrong--that is, that someone has altered the data in between when you per

EPITOME
SQL Server 2005 127

formed the fetch and when you went to actually update the database.

If you happen to run into problem, SQL Server will issue an error with a value in @@ERROR
of 16394. When this happens, you need to completely re-fetch the data from the cursor and
either rollback the transaction or try the update again.

Detecting Conversion of Cursor Types: TYPE_WARNING


This one is really pretty simple. If you add this option to your cursor, then you will be notified
if an implicit conversion is made on your cursor. Without this statement, the conversion just
happens with no notification. If the conversion wasn`t an anticipated behavior, then there`s a
good chance that you`re going to see the most dreaded of all computer terms - unpredict-
able result.

This is perhaps best understood with an example, so let`s go back and run a variation again
of the cursor that we`ve been using.
In this instance, we`re going to take out the piece of code that creates a key for the table.
Remember that without a unique on a table, a keyset will be implicitly converted to a static
cursor:

USE AdventureWorks
/* Build the table that we`ll be playing with this time*/
SELECT OrderID, CustomerID
INTO CursorTable
FROM Orders
WHERE OrderID BETWEEN 10701 AND 10705

DECLARE CursorTest CURSOR


GLOBAL
SCROLL
KEYSET
TYPE_WARNING
FOR
SELECT OrderID, CustomerID
FROM CursorTable

EPITOME
SQL Server 2005 128

DECLARE @OrderID int


DECLARE @CustomerID varchar (5)

OPEN CursorTest
FETCH NEXT CursorTest INTO @SalesOrderID, @CustomerID

WHILE @@FETCH_STATUS = 0
BEGIN
PRINT CONVERT ( varchar (5), @OrderID) + ‘ ’ + @CustomerID
FETCH NEXT FROM CursorTest INTO @OrderID, @CustomerID
END

CLOSE CursorTest

DEALLOCATE CursorTest

DROP TABLE CursorTable

The major changes are the removal of blocks of code that don`t need for this illustration
along with the addition of the TYPE_WARNING option in the cursor declaration.

Now we come up with some interesting results:

(5 row (s) affected)


The created cursor is not of the requested type.
43661 442
43662 227
43663 510
43664 397
43665 146

Everything ran okay-we just saw a statement that was meant solely as a warning. The re-
sults may not be what you expected given that the cursor was converted.

The downside here is that you get a message sent out. but no error. Programmatically speak-
ing, there is essentially no way to tell that you received this message--which makes this
EPITOME
SQL Server 2005 129

option fairly useless in a production environment . Still, it can often be quite handy when
you`re trying to debug a cursor to determine why it isn`t behaving in the expected fashion.

FOR < SELECT>


This section of the cursor declaration is at the very heart of the matter. This is a section that
is required under even the most basic of cursor syntax, and that`s because it`s the one and
only clause that determines what data should be placed in the cursor.

Almost any SELECT statement is valid--even those including an ORDER BY clause. As long
as your SELECT statement provides a single result set, you should be fine. Example of
options that would create problems would be any of the summary options such as a CUBE
or ROLLUP.

FOR UPDATE
By default, any cursor that is updatable at all is completely updatable-that is, if one column
can be edited then any of them can.

The FOR UPDATE <Column list > option allows you to specify that only certain columns
are to be editable within this cursor. If you include this option, then only the columns in your
column list will be allowed to be updatable. Any columns not explicity mentioned will be
considered to be read-only.

Navigating the Cursor :

The FETCH Statement


FETCH actually has many more options than what we`ve seen so far. Up to this point, we`ve
seen three different options for FETCH (NEXT, PREVIOUS, and FIRST).
Let`s look at each of the cursor navigation commands and see what they do for us:

FETCH Option Description

NEXT This moves you forward exactly one row in the result set and is the
backbone options. Ninety percent or more of your cursors won`t
need any more than this. keep this in mind deciding to declare as
FORWARD_ONLY or not. When you try to do a FETCH NEXT and
it results in moving beyond the last record. you will have a
EPITOME
SQL Server 2005 130

@@FETCH_STATUS of -1

PRIOR As you have probably surmised, this one is the functional opposite
of NEXT. This moves backward exactly one row. If you performed a
FETCH PRIOR when you were at the first row in the result set,
thenyou will get a @@FETCH_STATUS of -1 just as if you had
moved beyond the end of the file.

FIRST Like most cursor options, this one says what it is pretty clearly. If
you perform a FETCH FIRST, then you will be at the first record in
the recordset. The only time this option should generate a
@@FETCH_STATUS of -1 is if the result set is empty.

LAST The functional opposite of FIRST, FETCH LAST moves you to the
last record in the result set. Again, the only way you`ll get a -1
for@@FETCH_STATUS on this one is if you have an empty result
set.

ABSOLUTE With this one, you supply an integer value that indicates how many
rows you want from the beginning of the cursor. If the value supplied
is negative, then it is that many rows from the end of the cursor.
Note that this option is not supported with dynamic cursors. This
equates roughly to navigating to a specific “ absolute position” in a
few of the client access object models.

RELATIVE This is about navigating by moving a specified number of rows


forward or backward relative to the current row.

We’ve already gotten a fair look at a few of these in our previous cursors. The other naviga-
tional choices work pretty much the same.

Altering Data within Your Cursor


Up until now, we`ve kind of glossed over the notion of changing data directly in the cursor.
Now it’s time to take a look at updating and deleting records within a cursor.

EPITOME
SQL Server 2005 131

Since we`re dealing with a specific row rather than set data, we need some special syntax to
tell SQL Server that we want to update. Happily, this syntax is actually quite easy given that
you already know how to perform an UPDATE or DELETE.
Essentially, we’re going to update or delete data in table that is underlying our cursor. Doing
this is as simple as running the same UPDATE and DELETE statements that we’re now
used to, but qualifying them with a WHERE clause that matches our cursor row. We just add
one of syntax to our DELETE or UPDATE statement:

WHERE CURRENT OF< cursor name>

USE AdventureWorks
/* Build the table that we`ll be playing with this time*/
SELECT SalesOrderID, CustomerID
INTO CursorTable
FROM Sales.SalesOrderHeader
WHERE SalesOrderID BETWEEN 43661 AND 43665

ALTER TABLE CursorTable


ADD CONSTRAINT PKCursor
PRIMARY KEY (SalesOrderID)

/* The IDENTITY property was automatically brought over when


** We did our SELECT INTO, but I want to use my own SalesOrderID
** value, so I’m going to turn IDENTITY_INSERT on so that I
** can override the identity value.
*/
SET IDENTITY_INSERT CursorTable ON

DECLARE CursorTest CURSOR


SCROLL
KEYSET
FOR
SELECT SalesOrderID, CustomerID
FROM CursorTable

DECLARE @SalesOrderID int


EPITOME
SQL Server 2005 132

DECLARE @CustomerID varchar (5)

OPEN CursorTest
FETCH NEXT CursorTest INTO @SalesOrderID, @CustomerID

WHILE @@FETCH_STATUS = 0
BEGIN
IF ( @SalesOrderID % 2 = 0)
BEGIN
UPDATE CursorTable
SET CustomerID = -99999
WHERE CURRENT OF CursorTest
END
ELSE
BEGIN
DELETE CursorTable
WHERE CURRENT OF CursorTest
END
FETCH NEXT FROM CursorTest INTO @SalesOrderID, @CustomerID
END

WHILE @@FETCH_STATUS ! = -1
BEGIN
IF @@FETCH_STATUS = -2
BEGIN
PRINT ’ MISSING! It probably was deleted.'
END
ELSE
BEGIN
PRINT CAST @SalesOrderID AS varchar) + ‘ ’ + CAST
(@CustomerID
AS varchar)
END
FETCH NEXT FROM CursorTEST INTO @SalesOrderID, @CustomerID
END

EPITOME
SQL Server 2005 133

CLOSE CursorTest

DEALLOCATE CursorTest

DROP TABLE CursorTable

Again, we have treating this one as an entirely new cursor. We’ve done enough deletions,
additions, and updates that we suspect you’ll find it easier to just key things in a second
time rather than having to look through row by row to see what you might have missed.

We are also again using the modulus operator (%) . Remember that it gives us nothing but
the remainder. Therefore, if the remainder of any number divided by 2 is zero, then we know
the number was an even number.
The results are shown below:

(5 row (s) affected)

(1 row (s) affected)

(1 row (s) affected)

(1 row (s) affected)

(1 row (s) affected)

(1 row (s) affected)


MISSING! It probably was deleted.
43662 *
MISSING! It probably was deleted.
43664 *
MISSING! It probably was deleted.

You can see the multiple “ 1 row affected” that is the returned message for any row that was
affected by the UPDATE and DELETE statements. When we get down to the last result set
enumeration, you can quickly tell that we deleted all the odd numbers (which is what we told
our code to do), and that we updated the even numbered rows with a new CustomerID.
EPITOME
SQL Server 2005 134

DATA PERMISSIONS
Introduction
When you are working with database, you must have permission to perform any action. SQL
SERVER is an inherently secure system. If you want to perform any action, you must have
been given permission to do so. By designing and implementing a good security plan for
SQL Server, you can eliminate many problems before they happen rather than spend your
time trying to figure out how your data (or SQL Server) became damaged. What data modi-
fications can be made as well as what data a user is allowed to see can be successfully
restricted. Whether a user can back up a database, back up the transaction log for a data-
base, or create and manipulate objects in a database can also be restricted.
Another benefit of enabling multiple logins, users, and permissions is that you can track what
individual users are allowed to do and audit their activity.

Implementing Database Permissions


All permissions in SQL Server are given to database users. While examining permissions,
always look at a database user’s permissions, not the permissions for a login. Thus, we can
say that permissions are database specific.
For example, SAM has all permissions to the sales database. (He is a regional sales execu-
tive). SAM might have SELECT permissions on tables in the purchasing department data-
base. (He can see items on order, but only the purchasing department can buy new items.)
Finally, SAM might have no permissions in the accounting department database. (Only the
accountants have permissions in the accounting department database).
In the above example, SAM must connect to SQL Server with a SQL Server Authentication
mode login or use his Windows account credentials. He has a separate user account within
each database (or he can use his Windows user account or group membership) to gain
access. He might also use guest permissions, for example, in the accounting department
database (if a guest username exists). Keep in mind that each user in each database has
separate permissions.The supermission database system table tracks security within a da-
tabase. That’s why security is database specific.
Types of Permissions
Three terms are used in SQL SERVER 2000 to indicate the action taking place in reference
to permissions: GRANT, DENY and REVOKE statements.
Some kind of permission is granted to the user to let him perform an action. To prevent a
user from performing an action, deny the user the right to perform an action. Revoke the
permission to remove a previously granted permission.

Two types of permissions can be granted:


Statement level and object level. Statement level permissions enable a user to run a particu-
lar Transact-SQL command, whereas object-level permissions allow a user to perform some
operations: SELECT data (read), INSERT data, UPDATE data or DELETE data.

EPITOME
SQL Server 2005 135

Permissions Precedence
It is critical to understand how permissions are applied than understanding when a particular
permission is in effect. All permissions in SQL Server are cumulative, except DENY, which
overrides other permissions.
If a user has the SELECT permission from a membership in ROLED and the INSERT per-
mission from another membership in Rule 2; he effectively have the SELECT and INSERT
permissions. If the user then to be denied SELECT permissions within either of these roles
or within any individual account, then he would no longer have the SELECT permission.
DENY always overrides any other permission.

Special Permissions
SQL Server 2000 supports several different levels of permissions. Most of these permis-
sions are database specific. However, fixed Server roles are tied to logins, not database
users. Each role implies a specific set of permissions. Also sysadmin role membership im-
plies its own particular set of permissions.
There are fixed database roles within each database, each of which is associated with a
particular set of permissions. Each database also has a special user known as dbo (the
database owner). Special permissions are inherent for anyone who’s in this conceptual role
as well.

Fixed Server Role Permissions


Each role has implicit permissions associated with it. You can view them by running the
system stored procedure sp_srvrolepermission:
sp_srvrolepermission [ [@srvrolename =] . ‘role’]
Here, role is the name of the fixed server role for which you want to see the permissions.

Example
If you run
EXEC sp_srvrolepermission ‘db creator’
The output is as follows:

Server Role Permission


.................................................
dbcreator Add member to dbcreator
dbcreator ALTER DATABASE
dbcreator CREATE DATABASE
dbcreator DROP DATABASE
dbcreator EXTEND DATABASE
dbcreator RESTORE DATABASE
dbcreator RESTORE LOG
dbcreator sp_renamedb
EPITOME
SQL Server 2005 136

(8 row(s) affected)

Sysadmin
Members of the sysadmin server role are granted an extremely powerful set of permissions
and should be considered carefully. The sa login is always a member of this role and can’t be
removed from the sysadmin role. Members of the sysadmin fixed server role are always
considered to be the database owner of every database they use. Members of the sysadmin
role can’t be prevented from accessing any database on SQL Server.
A list of right is provided by the user interface for sysadmin members; however, it’s a little
misleading because a sysadmin role member can do anything.

Serveradmin
Server administrators who won’t otherwise be administering databases or other objects are
best suited to be members of the serveradmin role. Members of this role can perform the
following operations:
• Add another login to the serveradmin fixed server role.
• Run the DBCC FREE PROCCACHE command.
• Run the sp_configure system stored procedure to change system options.
• Run the RECONFIGURE command to install changes made with sp_configure.
• Run the SHUTDOWN command to shut down SQL Server.
• Run the sp_falltext_service system stored procedure to configure the full text service of
SQL Server 2000.

Setupadmin
Members of setupadmin role are administrators who are configuring remote servers. Members
of this role can perform the following operations:
• Add another login to the setupadmin fixed server role.
• Add, drop, or configure linked servers.
• Mark a stored procedure as startup

Securityadmin
Members of securityadmin role can perform any operation related to serverwide security in
SQL server. Members of this role can perform the following operations:
• Add members to the securityadmin fixed server role.
• Grant, revoke, or deny the CREATE DATABASE statement permission
• Read the SQL Server error log by using the sp_readerrorlog system stored procedure
• Run security_related system stored procedures.

Processadmin
Members of the processadmin role can control processes running on the database server.
This role typically involves “killing” runaway queries, and help desk personnel might need
this right. Members of this role can perform the following operations:
EPITOME
SQL Server 2005 137

• Add members to the processadmin fixed server role


• Run the KILL command to end a SQL Server Process

dbcreator
Members of the dbcreator fixed server role, which most likely includes senior database
administrators, can perform operations relating to creating and modifying databases. Members
of this role can perform the following operations:
• Add members to the dbcreator fixed database role
• Run the sp_renamedb system stored procedure
• Run the CREATE DATABASE, ALTER DATABASE, and DROP DATABASE commands
• Restore a database or transaction log

Õiskadmin
Members of the diskadmin fixed server role can manage files. This role is mostly for backward
compatibility with SQL Server 6.5. Members of the diskadmin fixed serve role can perform
the following operations:
• Add members to the diskadmin fixed server role
• Run the following DISK commands (used for backward compatibility): DISK INIT, DISK
REINIT, DISK REFIT, DISK MIRROR, and DISK REMIRROR.
• Run the sp_disk default and sp_dropdevice system stored procedures
• Run the sp_addump device system stored procedure to add backup devices.

Fixed Database Roles


Members of fixed database roles are given specific permissions within each database. Unlike
fixed server roles, however, they are specific to each database. You can view list of nine
fixed database roles by running the SD_dbfixedrolepermission system stored procedure:

Syntax
sp_dbfixedrolepermission [ [Srolename =] ‘role’]
Here, role is the name of the fixed database role for which you want to see permissions.
The results of running this system stored procedure are discussed below:
db-owner
Members of the db_owner fixed database role are the “owners” of a database. They can do
almost everything the actual database owner can do. They can perform the following opera-
tions within their databases:
• Add members to, or remove members from, any fixed database role except for db-owner.
• Run any data definition language (DDL) statement, including TRUNCATE TABLE.
• Run the BACKUP DATABASE and BACKUP LOG statements.
• Run the RESTORE DATABASE and RESTORE LOG statements.
• Issue a CHECKPOINT in a database.
• Run the following Database Consistency Checker (DBCC) Commands: DBCC
CHECKALLOC, DBCC CHECKFILE GROUP, DBCC CHECKDB, DBCC CHECKIDENT,
DBCC CLEANTABLE,

EPITOME
SQL Server 2005 138

DBCC DBREINDEX, DBCC PROCCACHE, DBCC SHOW _STATISTICS, DBCC,


SHOW CONTIG, DBCC SHRINKDATABASE, DBCC SHRINKFILE, and DBCC
UPDATEUSAGE.
• Grant, revoke, or deny the SELECT, INSERT, UPDATE, DELETE, REFERENCES, or EX-
ECUTE permissions on every object.
• Add users, group, roles, or aliases to a database by using the following system stored
procedures: sp_addalies, sp_addapprole, sp_addgroup, sp_addrole, sp_addrolemember,
sp_adduser, sp_approlepassword, sp_change_users_login, sp_changegroup, sp_dropalias,
sp_dropapprole, sp_dropgroup, sp_droprole, sp_droprolemember, sp_dropuser,
sp_grantdbaccess, and sp_revokedbaccess.
• Rename stored procedures by using the sp_recompile system stored procedures.
• Rename any object by using the sp_rename system stored procedure.
• Modify some table_specific options by using the sp_tableoption system stored procedure.
• Change the owner of any object by using the sp_changeobjectowner system stored proce-
dure.
• Configure full_text services within the database by using the following system stored pro-
cedure: sp_fulltext._catalog, sp_full text_column, sp_fulltext_database, and sp_full text_table.
db_accessadmin
Members of the db_accessadmin fixed database role manage which logins can access a
database. As with the securityadmin role, your help desk staff might be the best candidates
for membership in this role. Members can perform the following operation:
• Run the following system stored procedure:
sp_addalias, sp_adduser, sp_dropalias, sp_dropuser, p_grantdbaccess, and
sp_revokedbaccess
db_securityadmin
Members of the db_securityadmin fixed database role can administer security within a data-
base, and they can perform the following operations:
• Run the GRANT, REVOKE or DENY Statements
• Run the following system stored procedure:
p_addapprole, sp_addgroup, sp_addrole, sp_addrolemember
p_approlepassword, sp_changegroup, sp_changeobjectowner,
p_dropapprols, sp_dropgroup, sp_droprole, and sp_droprole members.
db_ddladmin
Member of the db_ddladmin fixed database rate can perform the following operations:
• Run any DDL command except GRANT, REVOKE, and DENY.
• Grant the REFERENCES permission on any table.
• Recompile stored procedure by using the sp_recompile system stored procedure.
• Rename any object by using the sp_rename system stored procedure.
• Modify some table-specific option by using the sp_tableoption system stored procedure.
• Change the owner of any object by using the sp_changeobjectowner system stored proce-
dure.
• Run the following DBCC command: DBCC CLEANTABLE, DBCC SHOW_STATISTICS,
and DBCC SHOWCONTIG

EPITOME
SQL Server 2005 139

• Control full_text services by using the sp_fulltext_column and sp_full text_table system
stored procedures.
db_backupoperator
Members of the db_backupoperator fixed database role can perform all operations related
to backing up a database. They can do the following:
• Run the BACKUP DATABASE and BACKUP LOG Statements
• Issue a CHECKPOINT in a database.
db_datareader
Members of the db_datareader fixed database role have the SELECT permission on any
table or view in a database. They can’t grant permission to or revoke it from anyone else.
db_datawriter
Members of the db_datawriter fixed database role have the INSERT, UPDATE and DELETE
permissions on all tables or views in a database. They can’t grant permission to or revoke it
from anyone else.
db_denydatareader
Members of the db_denydatareader fixed database role can’t run the SELECT statement on
any table or view in the database. This option is useful if you want your database administra-
tor (DBA) to set up your objects but not be able to read any sensitive data in the database.

db_denydatawriter
Members of the db_denydatawriter fixed database role can’t run the INSERT, UPDATE, or
DELETE Statement on any table or view in the database.

User Permissions
Most people using the database will be ordinary users. The database users have no inherent
rights or permissions. All rights must be explicitly granted or assigned to the user. Permis-
sions granted to the users can be categorized as follows:
• Statement Permissions
• Object Permissions

Statement Permissions
Statement permissions allow users to create new databases, new objects within an existing
database, or backup the database or transaction log. Statement permissions allow a user to
run a particular command(s) rather than merely manipulate a particular object.
When a user creates an object, he becomes the owner of that object and has all the permis-
sions associated with database object ownership.
• Change the owner of any object by using the sp_changeobjectowner system stored proce-
dure.
• Configure full_text services within the database by using the following system stored pro-
cedure: sp_fulltext_catalog, sp_full text_column, sp_fulltext_database, and sp_full text_table.
db_accessadmin
Members of the db_accessadmin fixed database role manage which logins can access a
EPITOME
SQL Server 2005 140

database. As with the securityadmin role, your help desk staff might be the best candidates
for membership in this role. Members can perform the following operation:
• Run the following system stored procedure:
sp_addalias, sp_adduser, sp_dropalias, sp_dropuser, p_grantdbaccess, and
sp_revokedbaccess
db_securityadmin
Members of the db_securityadmin fixed database role can administer security within a data-
base, and they can perform the following operations:
• Run the GRANT, REVOKE or DENY Statements
• Run the following system stored procedure:
p_addapprole, sp_addgroup, sp_addrole, sp_addrolemember,
p_approlepassword, sp_changegroup, sp_changeobjectowner,
p_dropapprols, sp_dropgroup, sp_droprole, and sp_droprole members.
db.ddladmin
Member of the db_ddladmin fixed database rate can perform the following operations:
• Run any DDL command except GRANT, REVOKE, and DENY.
• Grant the REFERENCES permission on any table.
• Recompile stored procedure by using the sp_recompile system stored procedure.
• Rename any object by using the sp_rename system stored procedure.
• Modify some table-specific option by using the sp_tableoption system stored procedure.
• Change the owner of any object by using the sp_changeobjectowner system stored proce-
dure.
• Run the following DBCC command: DBCC CLEANTABLE, DBCC SHOW_STATISTICS,
and DBCC SHOWCONTIG
• Control full_text services by using the sp_fulltext_column and sp_full text_table system
stored procedures.
db_backupoperator
Members of the db_backupoperator fixed database role can perform all operations related
to backing up a database. They can do the following:
• Run the BACKUP DATABASE and BACKUP LOG Statements
• Issue a CHECKPOINT in a database.
db_datareader
Members of the db_datareader fixed database role have the SELECT permission on any
table or view in a database. They can’t grant permission to or revoke it from anyone else.
db_datawriter
Members of the db_datawriter fixed database role have the INSERT, UPDATE and DELETE
permission on all tables or view in a database. They can’t grant permission to or revoke it
from anyone else.
db_denydatareader
Members of The db_denydatareader fixed database role can’t run the SELECT statement
on any table or view in the database. This option is useful if you want your database
administrator (DBA) to set up your objects but not be able to read any sensitive data in the
database.

EPITOME
SQL Server 2005 141

db_denydatawriter
Member of the db_denydatawriter fixed database role can’t run the INSERT, UPDATE, or
DELETE statement on any table or view in the database.
User Permissions
Most people using the database will be ordinary users. The database users have no inherent
rights or permissions. All rights must be explicitly granted or assigned to the user. Permissions
granted to the users can be categoized as follows:
· Statement Permissions
· Object Permissions
Statement Permissions
Statement permissions allow users to create new database, new objects within an existing
database, or backup the database or transaction log. Statement permissions allow a user to
run a particular command(s) rather than merely manipulate a particular object.
When a user creates an object, she becomes the owner of that object and has all the
permissions associated with database object ownership.

Statement permissions should be granted only when explicitly needed. The statement per-
missions that can be granted, revoked, or denied include:
• CREATE DATABASE
• CREATE TABLE
• CREATE PROCEDURE
• CREATE DEFAULT
• CREATE RULE
• CREATE VIEW
• CREATE FUNCTION
• BACKUP DATABASE
• BACKUP LOG

These permissions can be granted individually or all at once (using the keyword ALL).
The CREATE DATABASE Permission
The CREATE DATABASE Permission enables users to create their own databases and thus
become dbo (database owner) of those databases. Database ownership can later be changed
with the sp_changedbowner system stored procedure. Only members of the sysadmin or
dbcreator fixed server role are allowed to grant a user the CREATE DATABASE permis-
sions. This permission must be granted to the user in the master database only. The CRE-
ATE DATABASE permission also allows you to use the ALTER DATABASE command.
The Create Table, View, Function, Procedure, Default, and Rule Permissions
The CREATE TABLE, VIEW, FUNCTION, PROCEDURE, DEFAULT, and RULE permis-
sions enable users to run referenced statement to create objects in the database where the
permissions were given. Programmers are frequently given these permissions to allow them
to create the resources they need in a database during development.
Assigning Statement Permissions
EPITOME
SQL Server 2005 142

Transact-SQL or SQL Server Enterprise Manager can be used to grant, revoke, and deny
statement permissions. Let’s now consider some of the statement permission commands:
(i) GRANT: This command gives a user statement permissions.
SYNTAX: GRANT {ALL |Statement_List |}To (account)
Where-ALL stands for all possible statement permissions.
• Statement_list is an enumerated list of the statement permissions you want to give to an
account.
• Account is the name of database user, database role, Windows user or Windows group.
Example
(a) GRANT CREATE VIEW TO [Rhome/JOHN]
(b) GRANT ALL TO [Rhome/JOHN]
(i) REVOKE: This command takes away statement permissions already granted.
(ii) SYNTAX: REVOKE { ALL | Statement_List}FROM {account}
Example
REVOKE ALL FROM ROLE
DENY: This command explicity takes away a statement permission. The permission
doesn’t have to be first granted to a user,
SYNTAX: DENY {ALL|Statement_List} TO {account}
Object Permissions
Object permissions allow a user to perform action against a particular object in a
database.Object permissions are applied only to the specific object named while granting
the permission, not to all the objects contained in the entire database. Object permissions
enable users to give individual user accounts the rights to run specific Transact-SQL state-
ments on an object. They are the most common types of permissions granted.
Some available object permissions are as follows:
SELECT - View data in a table, view, or column
Insert - Add data to a table, or a view
UPDATE - Modify existing data in a table, view, or column
DELETE - Remove data from a table or view
EXECUTE - Run a stored procedure
REFERENCES - Refer to a table with foreign keys
Assigning Object Permissions
You can use T-SQL or SQL Server Enterprise Manager to grant, revoke and deny object
permissions. In this section we will study how to grant object permissions with Transact-
SQL.
(i) GRANT: This command is used to give someone one or more object permission. It also
removes a DENY permission.
SYNTAX
GRANT {ALL [PRIVILEGES] | permission_list [, ...n] }
{
[(Column [, ...n] ) ] ON {table | view}
|ON {table|view} [(Column [, ...n] ) ]
|NO {stored_procedure | extended_stored_procedure}
|NO {user_defined_f unction}

EPITOME
SQL Server 2005 143

}
To account [ , ...n]
[WITH GRANT OPTION]
[AS {group | role}]
Here - ALL stands for all possible object permissions that apply to a particular object type
permission_list is an enumerated list of the object permissions you want to give to an ac-
count
(a) Column is the level down to which object permissions can be granted (only for SELECT
or UPDATE).
(b) Account is the name of a database user, database role, Windows user, or Windows
group
(c) WITH GRANT OPTION allows the user who’s the recipient of the grant to also give
away
the permission he has been granted to other users
(d) As {group| role} specifies which group or role you are using for a particular grant.
Example
GRANT SELECT ON SALES TO [Rhome/John]
(i) REVOKE: This command takes away one or more object permissions that have
already been granted. An error message is not received if a command, that hasn’t previously
been granted is revoked, it just doesn’t have any effect.
Syntax
REVOKE [GRANT OPTION FOR]
{ ALL [PRIVILEGES] | [, ... permission_list n] }
{
[(Column [, ...n] ) ] ON { table | view}
|ON {table | view} [(Column [, ... n] ) ]
| stored_procedure | extended_stored_procedure}
| {user_def ined_function}
}
FROM account [ , ......n]
[CASCADE]
[AS {group} | role]

Example
(a) REVOKE SELECT, INSERT ON AUTHORS FROM [Rhome | Mary],
[Rhome | John]
(b) RE VOKE SELECT, INSERT ON PUBLISHERS FROM [Rhome | Ann l]
CASCADE.
(i) DENY: Unlike a REVOKE command, DENY explicitly takes away an object
permission. The permission doesn’t have to first be granted to a user.
Syntax
DENY
{ALL [privileges] | permission List [, ...n] }
{
[(Column [, ... n] ) ] ON {table | view}
EPITOME
SQL Server 2005 144

| ON {table | view} [ (Column [, ... n] ) ]


| On {stored_procedure | extended_stored_procedure}
| ON {User_defined_function}
}
To account [,...... n]
[CASCADE]

Permissions on Views, Stored Procedures, and Functions


Views, stored procedures, and functions can help you administer permissions by allowing
you to grant fewer permissions directly to the tables that hold your data. They can also help
avoid using column level permissions as such permissions can overly complicate the secu-
rity administration model.

Permissions on Views
A view can be considered as a stored query that appears as a table to users. The stored
query appears as a SELECT statement. You can create a view that refers only to selected
columns of a table. Then permissions can be assigned to the view for those users, and they
won’t have any rights to see the underlying table. They will be able to view data from the table
only through the view.

Permissions on Stored Procedures


Permissions on Stored Procedures enable you to abstract users from the tables and not
grant permissions directly on your tables. Stored procedures can contain many statements
and operations (like mini programs). They can view or modify data in many tables or views
and can gather data from other databases even from other data sources. Therefore, they
make nice containers in which to put any operations together.

Permissions on User-Defined Functions


Permissions on functions allow you to abstract users from the tables and even views. User-
defined functions can be a little weird in their permissions. If a function returns a scalar value
(a single value), you need EXECUTE permissions to call the function.
However, if a table of data type is to be returned, then acting more like a view, you need
SELECT permissions on the function.

EPITOME

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy