Professional Documents
Culture Documents
Introduction to
Microsoft SQL
Server 2000
Table of Contents
INTRODUCTION .......................................................................................INTRO-1
Courseware Conventions ..............................................................INTRO-2
The Practice Disks.........................................................................INTRO-3
Chapter Files......................................................................INTRO-3
Attaching the SQL Server Shark Database .......................INTRO-3
About the Authors ..........................................................................INTRO-6
BASIC QUERYING.............................................................................................4-1
Introduction to the Query Analyzer .........................................................4-2
Retrieving Data .......................................................................................4-5
Understanding Transact-SQL .....................................................4-5
The Shark Sample Database......................................................4-6
The SELECT Statement .............................................................4-7
The WHERE Clause .................................................................4-11
Sorting Data Using ORDER BY ................................................4-20
The GROUP BY Clause............................................................4-23
Joining Tables.......................................................................................4-30
Principles of Joining ..................................................................4-30
Inner Joins ................................................................................4-34
Outer Joins................................................................................4-38
Self Joins ..................................................................................4-45
ACTION QUERIES.............................................................................................5-1
Modifying Data........................................................................................5-2
What Is an Action Query? ...........................................................5-2
Inserting Data .........................................................................................5-3
Inserting a Single Value ..............................................................5-4
Inserting Multiple Values.............................................................5-6
Inserting Multiple Rows...............................................................5-8
Creating a New Table Using SELECT INTO ..............................5-9
Temporary Tables.......................................................................5-9
Using BULK INSERT ................................................................5-12
Updating Data.......................................................................................5-14
Updating a Single Row .............................................................5-14
Updating Multiple Rows ............................................................5-15
INDEX........................................................................................................INDEX-1
Designing and
Creating a
Database
Objectives
• Review relational database design principles.
• Create a SQL Server database based on sound design principles.
• Build tables using the Enterprise Manager.
• Learn about SQL Server data types.
• Create constraints, triggers, and indexes.
• Create a Database Diagram to enforce referential integrity.
There are several books on database design that provide greater depth of coverage for
database design concepts:
Key Terms
Primary key One of the candidate keys is selected to be the primary key.
Surrogate key Surrogate primary key attributes are created when none of the
candidate keys in a relation are considered to be suitable as a
primary key. This is often done simply to improve performance
and efficiency of storage. In SQL Server, identity columns are
often used as surrogate keys.
Also for convenience, if all candidate keys are very long, or composed of
many attributes, or subject to frequent changes, then a surrogate key is created
that is not only unique to each tuple, but also compact and relatively constant.
Access autonumber fields and SQL Server identity columns are examples of
surrogate keys.
It can be argued that surrogate keys should never be necessary, because every
tuple should have some other unique attribute or set of attributes reflecting
attributes of that entity in the “real world,” which is called the problem set
(also sometimes referred to as the problem domain or simply the problem
space). If database engines were perfect, then things like autonumbers and
identity columns wouldn’t be needed, because, for example, all customers
could be uniquely identified by their name; address; and the date, time, and
location of their first order. Even if two people at the same address had the
same name, they presumably couldn’t both place an order at the same location
at the same exact date and time. But, using all that data each time you needed
to identify a customer, and maintaining changes to all that data every place it
was used, would put an unacceptable burden on the system. So, surrogate keys
are often employed as a concession to the imperfection of our database
systems, to help them perform in the most efficient way possible.
Foreign key attributes allow tuples in one relation to reference tuples from
another relation. Foreign keys always contain values from the primary key of
another relation, creating a relationship between the two relations. For
example, the CustomerID column in the tblOrder contains primary key values
from tblCustomer, creating a relationship that allows customer data to be
referenced from order data. These relationships are covered later in the
chapter.
Data Normalization
See Normal.SQL Defining a primary key for each relation is a necessary first step toward
creating a well-designed database, but it’s just the beginning. Dr. Codd defined
a series of progressively more stringent standards, called normal forms, which
further optimize data for efficient storage and retrieval.
StudentID Name
The Name column holds the full name of each student, including the family
name, or last name, and the given name, or first name. Now you can see why
our definition of first normal form contained the somewhat awkward phrase,
“piece of information that you care about.” If all you ever cared about was the
full name, then this table would be in first normal form. However, if you ever
want to search or sort by the last name or first name separately, then this is a
violation of first normal form. Fix it by breaking the Name column up into
separate columns, one for each piece of the name that you care about:
Always break information down into the most atomic units needed to solve
your business problems. Relational databases make it very easy to join these
pieces back together later for presentation to the users.
Repeating Groups
If some students only enroll in one class, or two classes, then the additional
columns consume excess storage space. However, the most serious problem
with this arrangement is that it would be very difficult to figure out how many
students were signed up for Elementary Chemistry. You’d need to look in all
of the repeating columns for the information.
The following table structure supports an unlimited number of classes for each
student and allows you to efficiently count how many times a particular class
is being taken.
StudentID Course
The primary key for this table would need to include both columns in order to
uniquely identify each row. To add efficiency, you might want to create a
ClassID field and only store the full name of each class in a separate table.
The argument against violating third normal form is less convincing in SQL
Server, which supports computed columns and triggers, both of which are
capable of updating the Total value when the Unit or CostPerUnit values
There is more to third normal form, however, than just a ban on calculated,
redundant values. Third normal form builds on second normal form by
ensuring that all attributes that aren’t in the primary key not only are
functionally dependent on the full key, but also are not functionally dependent
on each other. In the following sample, PersonID is the primary key of the
Person table. The remaining columns are all dependent on PersonID. However,
the City and State columns are not only dependent on PersonID, they are also
dependent on the ZipCode. Theoretically, once you know the new zip code,
you could determine the new City and State. A perfectly normalized table
might only contain PersonID, StreetAddress, and ZipCode.
Third normal form is the most frequently violated normal form, for the sake of
convenience or performance. Few databases go to the trouble of maintaining
the postal lookup table that would be needed to bring the example above into
full compliance with third normal form.
Understanding Relationships
Once you’ve normalized your relations, logically related pieces of information
are segregated into multiple tables. To maintain consistent data, the database
must enforce the referential integrity of these logical relationships. For
example, if student data is stored in one table and enrollment information is
stored in another table, the database needs a way to know that every StudentID
in the Enrollment table has a corresponding record in the Student table.
One-to-Many Relationships
A one-to-many relationship is based on matching the values in the primary key
of one relation (table) with the values in the corresponding foreign key of
another relation. Each tuple in the first relation could potentially match up with
many tuples in the second relation. For example, one student could be enrolled
in many classes.
Many-to-Many Relationships
Each student can be enrolled in many classes, and many students can attend
each class. This is called a many-to-many relationship, and it can only be
represented in the database by using a third table. The Enrollment table, is used
to record the various pairings of students and classes. The primary key in the
Enrollment table is a composite key containing unique combinations of
StudentID and ClassID values.
Also consider that each course may be taught in several different classes, held
at different times during the week, taught by different instructors, and located
in different rooms. The Classes table itself represents several many-to-many
relationships between courses, instructors, and rooms. All of these
relationships are shown in Figure 3.
One-to-One Relationships
Sometimes, a foreign key can also be the entire primary key. This is called a
one-to-one relationship, since there can only be one matching record in each of
the two relations. The most common usage of one-to-one relationships is to
define attributes that only apply to a subset of the tuples (records) in a relation.
For example, you might have a Person table that holds general information
about all people in the database, and another Instructor table that holds extra
information that only applies to faculty. Each record in the Person table might
or might not have one matching record in the Instructor table, but each record
in the Instructor table would have exactly one matching record in the Person
table, as shown in Figure 4.
Enforced relationships require that every foreign key value have a matching
primary key value in the related table. In other words, you can’t have a
StudentID in the Enrollment table that doesn’t correspond to a matching
StudentID in the Student table.
Enforcing referential integrity also means that a student record can’t be deleted
while any enrollment records exist that depend on that student. In addition, the
StudentID can’t be changed for a student without making the same change to
the StudentID values in related enrollment records.
Unlike earlier versions of SQL Server, SQL Server 2000 allows you to enforce
referential integrity by cascading updates and/or deletes to related tables. So,
for example, if you try to change a StudentID value in the Student table that
was also used as a foreign key in the Enrollment table, SQL Server will
“cascade” the update, permitting the change in the Student table and updating
all related records in the Enrollment table as well. Cascading deletes would
entail deleting a student, and having all related records deleted from the
Enrollment table, leaving no orphans behind. Cascading deletes is potentially
dangerouscarelessly implementing cascading deletes can easily wipe out all
of your historical data.
Beyond Normalization
Even with fully normalized tables and well-enforced referential integrity, there
are plenty of ways that garbage can creep into your database. You can’t
prevent all data entry errors, but you can do a lot at the database level to
increase the chances that invalid data will be rejected.
However, these distinctions between different types of data integrity are not as
simple as they appear, since entity integrity and referential integrity could be
seen as forms of domain integrity. Domain integrity is the restriction of
attributes to a defined “domain” of valid values. When you select a data type
for a column, you are restricting the domain of values that can be stored in that
column. When you select whether Nulls will be permitted, you are refining the
definition of the domain. Designating a primary key or a unique index could
also be seen as restricting the domain to values that would not result in
duplicate key values. Even the creation of relationships can be seen as
restricting the domain of non-Null foreign key values to values that exist in the
corresponding primary key in the related table. So, in a sense all forms of data
integrity are variations on the basic concept of domain integrity.
Database Storage
SQL Server uses three underlying physical storage concepts:
• Pages
• Extents
• Files
Pages
A page is the smallest unit of SQL Server storage, at 8,192 bytes (or 8 KB).
This is also the maximum size of a row in a SQL Server table, not counting
large text and image columns, which are stored in separate pages. A page can
only contain data from a single object, although an object can occupy multiple
pages. For example, a table can span many pages, but a page can only contain
data from a single table.
Extents
An extent is eight contiguous pages, or 64 KB of data. When you create a new
table or index, it is given a single page in an existing extent that may contain
pages belonging to other objects. When the new object grows to the point
where it occupies eight pages in mixed extents, it gets moved to its own
uniform extent. SQL Server then creates additional extents as needed.
Files
Databases are stored directly in operating system files, which can be
configured to grow automatically as data is added to them. You can specify the
growth increment and an optional maximum size when you create the
database, as shown later in the chapter. Databases can be stored in multiple
files, but a single file must contain data from only one database. SQL Server
uses three file extensions for its data files, one for each of the three types of
files that it creates:
2. The data pages to be modified are read into the in-memory storage cache.
4. The checkpoint process saves the changes to disk. The checkpoint process
automatically executes at frequent intervals, writing data from the cache to
the physical drive the data is stored on. You can force the checkpoint
process manually by issuing the CHECKPOINT statement in Transact-
SQL, which immediately writes any cached pages to disk.
In the event of system failure, you can restore the database from a backup, then
apply transactions from the transaction log to recover data changes that
occurred after the last backup and that would otherwise be lost.
The transaction log is a separate data file (.ldf) that is normally located on a
separate device from the data files.
WARNING! Do not use a write-caching disk controller on any drives storing SQL
Server databases. A write-caching disk controller interferes with the
internal logic SQL Server uses during the checkpoint process. SQL
Server ensures that data can be recovered from the transaction log at
the time of any failure by storing disk writes internally and
committing them when the CPU is less busy. Since SQL Server
depends on knowing when the checkpoint process actually wrote to
the physical drive, a write-caching disk controller could make your
transaction log unrecoverable.
Creating Databases
Creating new databases can be done in the Enterprise Manager, either with the
Create Database Wizard, or through the menus. You can also use the Transact-
SQL CREATE DATABASE statement to create a new database. Both the
Enterprise Manager Wizard and menu options collect input and then execute
the CREATE DATABASE statement behind the scenes, using the parameter
values you’ve chosen in the dialog boxes. Almost all actions that you take
using graphical tools in SQL Server follow this pattern—behind the scenes it
all boils down to executing Transact-SQL statements.
Try It Out!
To use the menu options in the Enterprise Manager to create a new database,
follow these steps:
1. Expand the server node until the Databases node is exposed. Right-
click on Databases and choose New Database.
2. The Database Properties dialog box will then load, with the General
tab displayed, as shown in Figure 5. The name must be unique, and
conform to the rules for SQL Server identifiers, as listed in the sidebar
below. If you already have a sample database named School, use a
different name for the new one, such as School2. The Collation name
defaults to the collation used when installing SQL Server and it
defines the language and sort order for the data. SQL Server 2000
supports different collation orders for different databases, and even for
different columns in a single database.
Figure 5. Type in the Name of the new database and select the Collation name for
the language you want to use. Unless you have a good reason to do otherwise, just
select Server default for the Collation name.
3. Click the Data Files tab to specify the File Name and Location of the
data files for your database. This dialog box allows you to specify the
name and location of the primary filegroup, as shown in Figure 6. You
can also create additional filegroups at this time by typing in the
information on the lines under that displayed for the primary filegroup.
The File properties option at the bottom of the dialog box shows the
default settings, which include automatically growing the database file
as needed, and not setting a ceiling on file growth. One significant
improvement that was introduced in SQL Server 7.0 was the ability of
databases to grow as needed to accommodate data being entered.
Figure 6. Specifying the name and location of the data file in the primary
filegroup.
4. Click the Transaction Log tab to specify the name and location of the
transaction log. Figure 7 shows the name and location of the
transaction log, with the default options to grow the file as needed. As
mentioned earlier, it is recommended that the transaction log be
located on a different device from the primary data files, in case of a
disk failure. Click OK when finished, and the database will be created.
Identifiers are simply the names of objects, and SQL Server has the same rules
governing identifiers for all its objects, including databases, tables, columns, views,
and stored procedures.
• Identifiers must start with a letter or the symbols @, _, or #. This can be any
Unicode character, which includes a through z, A through Z, and most foreign
characters.
• Characters after the first character can be letters, decimal numbers, or the symbols
#, $, or _.
• Spaces and other special characters can only be used if the identifier is always
delimited with double quote marks or square brackets. Square brackets are always
supported; double quote marks are only allowed if the “Use quoted identifiers”
database option has been set.
• Identifiers must not be reserved words. There are two Books Online topics with
the title “Reserved Keywords” that list all reserved words for Transact-SQL and
Embedded SQL for C (ESQL/C).
The Options tab, shown in Figure 9, allows you to set additional database
options.
The options shown in Figure 9 are not the complete list of available options,
but merely the most commonly used ones. Table 1 shows the list of database
options you can set from the Enterprise Manager and what they mean.
Option Meaning
In addition, there are other useful database options not shown in the Enterprise
Manager that are listed in Table 2.
Option Meaning
To change database options not listed in the Enterprise Manager, use the
Transact-SQL syntax ALTER DATABASE. Database options can also be set
using the sp_dboption system stored procedure, which is supported in SQL
Server 2000 for backwards compatibility. Use the
DATABASEPROPERTYEX function to retrieve current settings for database
options. The following statement executed in a Query Analyzer window will
return 0 if the Auto Close property is not set, and 1 if it is:
Note that there’s quite a big difference in syntax between sp_dboption and
ALTER DATABASE. SQL Server Books Online warns that sp_dboption may
not be supported in future versions of SQL Server, so it probably makes sense
to get in the habit of using ALTER DATABASE to set options not available in
the Enterprise Manager.
Creating Tables
When you create a new database, it will contain systems tables, but no user
tables. SQL Server system tables contain metadata about the structure and
security settings of your database. All system tables have the prefix “sys” on
their names.
Tables you create, called “user tables,” must follow these rules:
• Each table has a name that is unique in the database and follows the
rules for identifiers. Tables can have the same name if they have
different owners, and must then be used with the
ownername.tablename syntax.
• Each column describes a single characteristic of a set, and must have a
unique name within that table.
To further conform to the rules for normalizing data outlined earlier in this
chapter, tables must also have the following characteristics:
• Each row must be unique and describe one set of related information
about the subject of the table. The primary key ensures the uniqueness
of each row.
• The order of the rows or columns should not be significant or
meaningful in any way.
Each column you define has as its most important characteristic a data type.
This limits the domain of possible values that can be inserted into the column.
SQL Server has built-in system data types, and also supports user-defined data
types (which are comprised of system data types). These are the SQL Server
system data types:
binary[(n)] The binary data type holds from 1 to 8,000 bytes of fixed-
length binary data, where n is a value between 1 and
8,000. The storage size includes whatever is stored in the
column plus 4 additional bytes. Binary is a fixed-length
data type, so if you define a column as binary(5) it will
always use 5 bytes of disk space plus the additional 4.
Using a fixed-length data type is efficient when data in the
column is close to the same size, since fixed-length
storage allows SQL Server to retrieve data more
efficiently.
varbinary[(n)] The varbinary data type is the same as binary, except that
it is a variable-length data type. Only the actual length of
the data is stored, and the (n) parameter merely specifies
the maximum length of the data. Use varbinary when the
length of the binary data is unknown or varies in length.
image The image data type is similar to the text data type in that
it consists of linked data pages consisting of binary data. It
can contain up to 2,147,483,647 bytes of binary data.
char[(n)] The char data type is fixed-width, and can contain from 1
to 8,000 non-Unicode characters. The storage size is (n)
regardless of the actual length of the data. Unused storage
is padded with trailing spaces. Use the char data type
when data entered in a column is the same length, such as
a column that contains state names (“NY”, “CA”, etc.).
nchar[(n)] The nchar is a fixed-length data type that can contain from
1 to 4,000 Unicode characters. It is similar to char, but
with twice the storage requirements. Use char when you
need to store strings that require Unicode character sets.
decimal[(p[, s])]
and
numeric[(p[, s])] The decimal and numeric data types are just two names
for the same thing. The decimal/numeric data types are
used for numbers with fixed precision and scale, indicated
by the (p, s) parameters. When maximum precision is
used, valid values are from - 10^38 -1 through 10^38 - 1.
The scale (s) is the maximum number of digits that can be
stored to the right of the decimal point, and it must be less
int The int data type uses 4 bytes of storage and can store
whole numbers from -2^31 (-2,147,483,648) through 2^31
- 1 (2,147,483,647).
tinyint The tinyint data type consumes only 1 byte of storage and
can store whole numbers from 0 through 255.
bigint The bigint data type is new in SQL Server 2000. It can
hold numbers in a range from –2^63 to 2^63-1, and uses 8
bytes of storage. Use bigint when you need a larger
version of int.
money The money data type can store decimal data scaled to four
digits of precision. Values range from -2^63 (-
922,337,203,685,477.5808) through 2^63 - 1
(+922,337,203,685,477.5807), with accuracy to a ten-
thousandth of a monetary unit. Storage is 8 bytes. The
money data type is useful when you don’t need more than
four decimal places of precision since values are preserved
exactly, with no rounding beyond the four digits.
bit The bit data type can hold a value of either 1 or 0. Null
values are not allowed. SQL Server stores bit fields
efficiently by collecting multiple bit fields and storing up
to eight in a single byte. Use the bit data type for true/false
yes/no types of data where you don’t need to store a Null
value.
sql_variant The sql_variant data type is new in SQL Server 2000. The
sql_variant data type can store int, binary, and char values,
but not text, ntext, image, or timestamp values. The
sql_variant is the least efficient data type and should be
used only when no other option seems practical.
Try It Out!
To create a new Person table in the School (or School2) database using the
Enterprise Manager, follow these steps:
2. Name the first column PersonID, and select a data type of int. Set the
Identity property to Yes. Click the gold key on the toolbar to set this
column as the primary key for the table. This will guarantee that each
new record added has a unique value that is generated automatically.
LastName varchar 30 No
FirstName varchar 30 No
MI char 1 Yes
Address varchar 50 Yes
City varchar 50 Yes
State char 2 Yes
ZipCode varchar 15 Yes
5. To try out entering data in the new table, right-click anywhere in the
table designer and choose Task|Open Table from the menu. Figure 10
shows entering some sample data in the new table. Note that the
PersonID is generated automatically.
Computed Columns
Computed columns, which were introduced in SQL Server 7.0, allow you to
have a de-normalized column that is automatically updated when the values in
the columns it is based on change. For example, in the Course table you could
have a PricePerUnit and a Units column, along with a Total column, as shown
in Figure 11. The Total column has the following Formula property:
([PricePerUnit] * [Units])
Figure 11. The Formula property allows you to configure a computed column.
If a value in either the PricePerUnit or the Units column changes, the Total
column will be automatically recomputed.
Creating Constraints
You can restrict the data entered in columns by setting restrictions, or
constraints, on the types of values allowed. Constraints can be placed on
columns as part of creating tables, or they can be added later. There are six
types of constraints that you can set on columns:
Default Constraints
A default constraint provides for a value to be automatically entered into a new
row when no other data is explicitly entered in that column. You can define
one default constraint per column. For example, Figure 12 shows creating a
default of an empty string (‘’) for the MI (or middle initial) column in the
Person table. If a person does not have a middle initial, then an empty string
will be entered in the table automatically.
Figure 12. Creating a default constraint for the MI (middle initial) column.
CHECK Constraints
A CHECK constraint checks the data before the record is saved. If the
incoming data does not conform to the constraint, then the record won’t be
saved. If the return value of the constraint expression is False, the constraint
has been violated and the record will not be saved.
Try It Out!
Follow these steps to create a CHECK constraint limiting the state values for
the Person table:
2. Type the definition of the constraint. You must type the expression
before you change the name of the constraint. The following
expression will limit the values entered into the State column to the
abbreviation for Florida:
State = 'FL'
If you have a list of more than one valid state, use the Transact-SQL IN
clause:
The options at the bottom of the dialog box have the following meanings:
• Check existing data on creation. This option ensures that all data that
exists in the table before the constraint was created is verified against
the constraint.
• Enforce constraint for replication. This option enforces the
constraint when the table is replicated into a different database.
• Enforce constraint for INSERTs and UPDATEs. This option causes
the constraint to be enforced when data is inserted or updated.
3. Click Close when finished. The constraint will be saved when you
save the table.
You can refer to multiple columns in a Check constraint (for example, making
sure that the delivery date falls after the order date), but you can’t refer to
columns in other tables. To validate data in one table against data in other
table, you need to create a trigger.
Be careful when creating Check constraints. If you really did want to limit the
values for the State column to a particular set of states, it would probably be
better to create a separate table of allowed states and to create a foreign key.
That way, as the list of allowed states changed, you would only need to
maintain the data in the related table, not the constraint. In general, such data-
driven restrictions are easier to maintain than ones encoded in Check
constraints.
Creating Rules
If you have a constraint that you use over and over again, you can create a
Rule instead. A Rule can be applied to multiple tables.
To create a rule, right-click on the Rules node in the Enterprise Manager, and
select New Rule from the menu. This loads the Rule Properties dialog box.
Type a name for the rule, and an expression that defines the rule. The
following expression will create a rule:
@State = 'FL'
The variable, @State, represents the column name, which can vary from table
to table.
Once the rule is saved, right-click on it and select Properties from the menu.
You can bind the rule to user-defined data types (UDTs) or to columns in a
table. Figure 14 shows binding the StateFlorida rule (@State = 'FL') to the
State column in the Person table.
You can create your own user-defined data types, which are composed of
system data types. Each system data type has specific parameters that you can
specify when designing your user-defined data type for a column. This allows
you to fine tune, standardize, and document a column’s data type.
You would create your own data type when you want something more specific
than the built-in data types. For example, you might want to create a user-
defined data type for a product code that always consisted of two alphabetical
characters followed by six numeric characters. A user-defined data type that
incorporated a rule limiting the number and kind of characters that are allowed
in the column could limit entries to ones like this:
BE123456
To create the rule, right-click on the Rules node and select New Rule from the
menu. Name the rule IDRule and enter the following expression:
The dialog box should look like the one shown in Figure 15. Click OK when
finished.
To create the user-defined data type, select the database and right-click on
User-defined datatypes. Select New user-defined data type from the menu.
This will load the User-Defined Data Type Properties dialog box, as shown in
Figure 16. You can also specify a rule and a default value for the data type
where appropriate.
When defining the data type for a column in a table, the custom data type will
show up at the bottom of the data type drop-down list, after the system data
types, as shown in Figure 17.
TIP: User-defined data types and rules created in the model database will
automatically be included in all subsequent databases that you create.
Triggers
A trigger is a Transact-SQL procedure that executes only on INSERT,
UPDATE, or DELETE statements—there’s no such thing as a trigger for a
SELECT statement. A trigger becomes part of the statement or transaction that
fires it, and a ROLLBACK TRANSACTION statement issued in a trigger
cancels the whole transaction.
Triggers support conditional logic and can alter values in other tables. To
understand triggers, you really need to understand Transact-SQL and
transactions, which are both covered later in the course, as is a more detailed
look at triggers.
Creating Indexes
The Indexes/Keys tab on the table’s Properties dialog box allows you to
create both indexes and unique constraints. Index creation is a very important
part of defining the columns and tables in your database because of the impact
that indexes have on the speed of data retrieval.
To create a new index, click the New button. Select the column name (or
namesyou can create an index on more than one column) and specify the
index type. Figure 18 shows creating a unique index/constraint on the
LastName column.
The various options you can set for the index or constraint are explained in
Table 3.
Option Meaning
Create Unique indexes are extremely efficient and SQL Server will
UNIQUE generally favor them over non-unique indexes given a choice.
If you have a column that you know will always contain
unique data, check off the Create UNIQUE checkbox when
creating the index. When you create a UNIQUE constraint, a
unique index is always created to support it. Nulls are treated
as individual values in an index that’s defined as unique, so a
single-column index can contain only one Null.
Ignore The Ignore duplicate key check box for unique indexes allows
duplicate key you to specify that if multiple rows are inserted into the table
and some are duplicates, only the duplicates will be rejected.
Otherwise, all the rows, including those with acceptably
unique values, would be rejected if any were duplicates.
Fill factor The Fill factor option determines how densely the index is
packed when it is created. If the table is empty at the time you
create the index, then you can ignore this setting since it is
meaningful only if there is already data in the table. If the
table is going to have many updates and inserts, then create an
index with a low fill factor to leave room for the future keys
to be inserted. However, if the table is read-only or will
otherwise not change much, then a high fill factor will reduce
the physical size of the index, lowering the number of disk
reads needed. The fill factor only applies when you create the
index—indexes stabilize at a certain density over time as keys
are inserted and deleted.
Create as Only one index per table can be clustered, and generally it
CLUSTERED should be on a column with unique values, although this is
not required. If necessary, SQL Server will add a 4-byte value
called a uniqueifier to each entry, ensuring that it points to
one unique row of data. The data in the table is physically
stored according to the order defined by the clustered index,
just as the pages of a book are ordered by page number.
Database Diagrams
You can define relationships in the Table Designer by choosing the Properties
dialog box and clicking on the Relationships tab. However, database diagrams
offer a more complete environment for creating relationships and performing
other design tasks on your tables. A single database can support multiple
database diagrams, each diagramming a different set of tables.
Figure 19. Creating a relationship between the Student and Enrollment tables.
The meaning of the various options you can set on the foreign key constraint
are listed in Table 4.
Option Meaning
Check existing data on Data already existing in the table will be checked to
creation make sure it matches the constraint.
Enforce relationship for If you leave this option blank, the constraint will be
replication enforced on users, but not on data changes that result
from the replication process. In other words, the
constraint won’t let users violate it, but if a row is
inserted from another database through replication, the
constraint will be ignored.
Enforce relationship for The constraint will be enforced for data being inserted
INSERTs and UPDATEs into the table, as well as for data being updated.
Cascade Update Related Checking this option will cause changed primary key
Fields values to be cascaded to the corresponding foreign key
fields in related tables.
Cascade Delete Related Checking this option will cause records containing
Fields foreign keys to be deleted automatically when records
containing the matching primary keys are deleted.
Table 4. Relationship constraint options.
WARNING! If you choose the Cascade Delete Related Fields option, you stand to
lose your historical data should a record on the primary side of the
relationship be deleted. For example, setting Cascade Delete on a
customer/orders relationship will cause all orders for that customer
to be lost if a customer is deleted from the database. If you do not
choose the Cascade Delete option, then a customer cannot be deleted
who has outstanding orders. The attempted deletion will fail, and
neither the customer nor the orders will be deleted.
Try It Out!
Follow these steps to add a new column to the Enrollment table and make it
part of the primary key:
2. Set the column name to Semester, the data type to varchar (20), and
clear the Allow Nulls checkbox.
4. Click the Save button on the database diagram toolbar to save changes
to the table.
Figure 20. Changing the view in the database diagram to edit a table.
TIP: Not all column properties are displayed in the Standard view. You can choose
to create a Custom view of the table, which allows you to specify the column
properties you wish to modify. Only columns that are displayed in the
database diagram view can be modified.
Taking time at the outset to properly design and specify your database will
save you countless hours during the implementation phase. A well-designed
database is amenable to change, and can be modified easily to conform to new
requirements. The Enterprise Manager provides a robust and easy to use
graphical user interface for creating your tables and defining columns. By
selecting the proper data types for your columns and by adding constraints and
triggers, you can protect the domain integrity of your data and enforce business
rules. Database diagrams allow you to build relationships between your tables
and to work with table and column properties.
Summary
• A solid database design is essential to the success of your SQL Server
database application.
• Database relationships can be one-to-many, one-to-one, or many-to-
many.
• SQL Server 2000 supports cascading updates and deletes.
• Data is stored in SQL Server in files and filegroups.
• The transaction log records all database activity before saving it to
disk.
• Database integrity is ensured through data types, constraints, and
relationships.
• Complex business rules can be implemented through triggers.
• Unique constraints are created at the same time as an index.
• Database diagrams allow you to set relationships as well as modify
table properties.
Questions
1. What do you need in addition to knowledge of relational design principles
to build a successful database application?
Answers
1. What do you need in addition to knowledge of relational design principles
to build a successful database application?
Knowledge of the business
Lab 3:
Designing and
Creating a
Database
Lab 3 Overview
In this lab you’ll learn how to create a database. You’ll then create two tables,
defining the columns and setting the primary key. You’ll learn how to create a
CHECK constraint to limit the values in a table. You’ll then learn how to
create a relationship between the tables using a database diagram. Each
exercise will build on the objects created in the previous exercise.
Objective
In this exercise, you’ll create a new SQL Server database named “Orders”
using the Enterprise Manager. Locate the new database in the default data
directory on your SQL Server.
Things to Consider
• When creating a new database, make sure that there is sufficient room
on the device chosen to store the database files.
• Consider whether you want to locate the transaction log on the same
device as the main data files.
Step-by-Step Instructions
1. Right-click on the Databases node in the Enterprise Manager and choose
New Database.
2. Name the new database Orders and click the Data Files tab.
Figure 21. Creating a new database and setting the file to automatically grow.
4. Click the Transaction Log tab. If possible, locate the transaction log on
another device. If you’re only working on a single machine, then simply
leave it in the default folder. Click OK when finished and the database is
created.
Objective
In this exercise, you’ll create two tables in the Orders database you created in
the first exercise: Customers and CustomerOrders. The Customers table will
contain information about each customer. Columns you define will include a
CustomerID identity column to serve as the primary key, LastName,
FirstName, Address, City, State, and ZipCode.
Things to Consider
• Table names must be unique in the database.
• Identity columns must be defined as “Not Null.”
• The data type for character columns should be varying for character
data that will be different lengths.
• The datetime data type encompasses a larger date range than
smalldatetime. Which one is better suited for orders that start from
today?
• The expression used in a CHECK constraint must evaluate to either
True or False.
Step-by-Step Instructions
1. Right-click on the Tables node in the Orders database and choose New
Table from the menu.
2. This loads the Table Designer. For the first column, define the name as
CustomerID, with a data type of int. Clear the Allow Nulls checkbox.
3. In the Columns section of the designer, set the Identity property to Yes.
4. To set CustomerID as the primary key, click the gold key button on the
toolbar.
LastName varchar 30 No
FirstName varchar 30 No
Address varchar 50 Yes
City varchar 20 Yes
State char 2 Yes
ZipCode varchar 11 Yes
6. Click the Save button and enter the name Customers. The table should
look similar to that shown in Figure 22. Close the Table Designer when
finished.
7. Repeat step 1 to create another new table. Define the following columns:
OrderID int 4 No
CustomerID int 4 No
OrderDate smalldatetime 4 No
DeliveryDate smalldatetime 4 Yes
8. Select the OrderID column and set the Identity property to Yes. Click the
gold key button on the toolbar to set OrderID as the primary key.
9. Select the OrderDate column. Set the Default Value property to the
getdate() function. This causes the default value of the current date to be
inserted.
10. Save the table and name it CustomerOrders. Right-click anywhere in the
designer and choose Task|Open Table from the menu. Type in any
number in the CustomerID column and move off of the row. Note that
both the OrderID and OrderDate values are automatically filled in. Select
the row and delete it. Close the Table view and return to the designer.
11. To create a constraint that limits the values entered in the DeliveryDate to
be later than those entered in the OrderDate, right-click anywhere in the
designer and choose Check Constraints from the menu.
12. Click the New button to enable the fields to enter the check constraint.
Type the following in the Constraint expression window:
13. Click Close when finished. To save the constraint, click the Save button
on the Designer toolbar.
14. To test the constraint, choose Task|Open Table from the menu. Try
entering a DeliveryDate that is earlier than the OrderDate. You should not
be able to save the record.
Objective
In this exercise, you’ll use a database diagram to create a relationship between
the Customers and the CustomerOrders tables created in the previous exercise.
Things to Consider
• Any work done in the Database Diagram Designer is not saved in the
underlying tables until you explicitly save the database diagram.
• When creating a relationship between the Customers and the
CustomerOrders table, should you set the option to cascade deletes?
Or will it be necessary to prevent orders from being deleted when a
customer is deleted in order to save a sales history?
Step-by-Step Instructions
1. To create a new database diagram in the Orders database, right-click on
the Diagrams node and select New Database Diagram from the menu.
2. This launches the Create Database Diagram Wizard. Follow the steps to
complete the wizard, adding the Customers and the CustomerOrders
tables. Click Finish to complete the wizard.
3. This opens the database diagram with the two tables displayed. Because
each customer can have many orders, start with the Customers table and
select the CustomerID field. Holding down the left mouse button, drag and
drop it on top of the CustomerID field in the CustomerOrders table and
release the mouse. This loads the Create Relationship dialog box as shown
in Figure 23.
Figure 23. Creating a relationship between the Customers and the CustomerOrders
tables.
4. Check the option for Cascade Update Related Fields. This causes any
updates to the CustomerID in the Customers table to cascade to any
existing entries in the CustomerOrders table. Leave the Cascade Delete
Related Records option blank. This way a customer who has outstanding
orders cannot be deleted. Click OK when finished.
5. The relationship will show up as a join line between the Customers and the
CustomerOrders tables.
6. Click the Save change script toolbar button. Click Yes to save the change
script, and select the path to the lab directory. Save the file as
DiagramChangeScript.sql (you don’t need to type the .sql file
extensionit will be filled in automatically for you).
7. Click the Save button and save the diagram as OrdersDiagram. Click Yes
to save changes to the tables.