1. Altering Tables
Tables can be altered using SSMS or through DDL
statements. To alter an existing table using SSMS, simply select Design
from the context menu of the desired table. You can freely modify
the table using the UI, or you can modify a table using a DDL statement.
ALTER TABLE
is the DDL statement used to change tables using T-SQL. A plethora of options are available for ALTER TABLE
.
To see ALTER TABLE
in action, add a column called Store Manager
to the Store Location
table you just created:
ALTER TABLE [Store Location]
ADD [Store Manager] VARCHAR(50)
In the following sections, you will
also see other examples of altering a column including adding a
constraint to an existing column.
2. Adding Constraints
With data types, you can limit the kind of data that can be stored within the column. For example, once you defined the store_id
column as an integer, you could not insert the word boston
for the store_id
since a word is a sequence of characters and not an integer value.
However, what if you had a column such as the weight of a pet that was
an integer, and you knew your application would provide integers, but
you wanted to make sure that only realistic or valid values were
entered? This is where constraints come into play.
NULL Constraints
The keywords NOT NULL
and NULL
tell SQL Server whether a null value is allowed to be entered as a valid value for the column.
Note A null value is unknown and not meant to be confused with a zero value or empty value.
In some cases, you might have required value,
such as a store ID, where a null value might not make any sense,
because, for example, a store must have one specific ID to be a store.
In this case, the column store_id
must not allow null values; thus, you give NOT NULL
as a parameter to the column definition. In other cases, you might be
storing answers to a survey. Perhaps this survey accepts answers of yes
or no, but the respondent didn’t answer a particular question. The
absence of an answer is a null value, and you should allow the answer
column to have NULL
s.
CHECK Constraints
Previously, we defined the Pets table as follows:
CREATE TABLE [Pets]
(pet_id INT PRIMARY KEY,
pet_name VARCHAR(50) NOT NULL,
pet_weight INT NOT NULL)
To make sure that the user cannot enter an
unrealistic weight for a pet, such as a negative weight or a weight
greater than 1,000 pounds, you can define a CHECK
constraint. A CHECK
constraint requires that the value entered passes an arbitrary expression. To restrict the list of valid values for the pet_weight
column, you can apply the CHECK
constraint as follows:
ALTER TABLE Pets WITH CHECK
ADD CONSTRAINT [CK_Pets]
CHECK (([pet_weight]>0 AND [pet_weight]<1000))
GO
The keyword WITH CHECK
means that existing data in the table will be checked against the constraint. If any values violate the constraint, the ALTER TABLE
statement will fail. If you wanted to apply this constraint only for new data added to the table, you would specify WITH NOCHECK
.
Primary Keys and Unique Constraints
In the Pets
table defined earlier, notice pet_id
is an integer data type, and it has a PRIMARY KEY
constraint defined on it. The purpose of a primary key is to ensure
that each row of data is unique for the given column or columns where
the primary key is defined. In our example, we want a pet to appear
only once in this table, so defining a primary key is one way to ensure
this behavior.
Without a primary key, the data in Table 1 would be valid.
If pet_id
is used as a reference throughout the database application, how would you know if you were referring to Sasha or Jake, given a pet_id
of 10
? To mitigate this problem, you would define a primary key or unique constraint.
There can be only one primary key defined on a
table, and the row value for a primary key column can never be null.
The reason for this is that, when you define a primary key, SQL Server
will create an index on the column or columns that you specify.
Depending on whether an existing index is already defined, SQL Server
may create a clustered index that physically sorts the data within the
database files with respect to the key value. If there is already a
clustered index defined on the table and you add a primary key, SQL
Server will create a UNQIUE
constraint to ensure that the
values for the primary key column are unique.
A UNIQUE
constraint is similar to a PRIMARY KEY
constraint in that it enforces uniqueness of the data. However, the UNIQUE
constraint creates a nonclustered index and does not physically change
the structure of the data within the data files. You can have multiple
unique constraints per table.
To illustrate the UNIQUE
constraint, let’s create a table called Medication
. Since the veterinary practice can stock drugs from only one manufacturer, you need to define a unique constraint on the med_name
column. The code for the table creation is as follows:
CREATE TABLE Medication
(med_id INT PRIMARY KEY,
med_name VARCHAR(50) CONSTRAINT u_med_name UNIQUE,
med_supplier VARCHAR(50) NOT NULL)
GO
From the previous code, you can define constraints at the time of creation and after the fact using the ALTER TABLE
statement. Now that the Medication
table is created, try to insert a medication that has the same name but from a different manufacturer, as follows:
INSERT INTO Medication VALUES (1, 'Cyclosporine 5mg', 'Generic Drugs Inc')
INSERT INTO Medication VALUES (2, 'Cyclosporine 5mg', 'ACME Vet Drugs')
When this code is executed, the first medication from Generic Drugs Inc
will be successfully inserted, but the second will fail because of the
violation of the constraint. The actual error message is as follows:
(1 row(s) affected)
Msg 2627, Level 14, State 1, Line 2
Violation of UNIQUE KEY constraint 'u_med_name'.
Cannot insert duplicate key in object 'dbo.Medication'.
The statement has been terminated.
Foreign Key Constraints
You can create an Owners
table that will reference the Pets
table. The table creation code follows:
CREATE TABLE [Owners]
(owner_id INT PRIMARY KEY,
pet_id INT REFERENCES Pets(pet_id),
owner_name VARCHAR(50) NOT NULL)
GO
There can be only one owner for each pet, so you create a primary key on the owner_id
column. You create a foreign key on the pet_id
column to enforce a link between the Owners
table’s pet_id
column and the Pets
table’s pet_id
column. This link is important in this scenario because you always want
to ensure that pets belong to owners. There is a logical connection
between these two entities. You cannot arbitrarily add a value to the pet_id
column in the Owners
table; the value must match an existing value in the pet_id
column in the Pets
table. This behavior is known as referential integrity.
To observe this behavior, add an owner associated with a pet that doesn’t exist yet in the Pets
database, as follows:
INSERT INTO Owners VALUES (1,20,'Julie')
Upon execution of the statement, you will get the following error:
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the FOREIGN KEY constraint
"FK__Owners__pet_id__1FCDBCEB". The conflict occurred in database
"VetClinic", table "dbo.Pets", column 'pet_id'.
The statement has been terminated.