Search Java Programs

Wednesday, March 3, 2010

Using the ALTER TABLE Statement to Change Primary and Foreign Keys

In addition to changing the width and data type of a column, you can use the ALTER TABLE statement to add table constraints such as a PRIMARY KEY and FOREIGN KEY. Tip 61, "Using the CREATE TABLE Statement to Assign the Primary Key," and Tip 62, "Using the CREATE TABLE Statement to Assign Foreign Key Constraints," will show you how to define keys as part of the CREATE TABLE statement when creating a new database table. For existing tables, use the ALTER TABLE statement to add named and unnamed PRIMARY KEY and FOREIGN KEY constraints.


Both PRIMARY KEY and FOREIGN KEY constraints are database "keys," which means that each is a column or a combination of columns that uniquely identifies a row in a table. While a PRIMARY key uniquely identifies a row in the table in which it is defined, a FOREIGN KEY uniquely identifies a row in another table. (A FOREIGN KEY in one table always references the PRIMARY key in another table.)


A table can have only one PRIMARY KEY, but it can have several FOREIGN KEYS. While the value of the column or combination of columns that makes up a PRIMARY key must be unique for each row in the table, the value of the column or combination of columns that makes up a FOREIGN KEY need not be (and most likely are not) unique within the table in which the FOREIGN KEY is defined.


You will learn more about the PRIMARY KEY constraint in Tip 172, "Using the PRIMARY KEY Column Constraint to Uniquely Identify Rows in a Table," and the FOREIGN KEY constraints in Tip 173, "Understanding Foreign Keys."


The syntax for using the ALTER TABLE statement to add a PRIMARY KEY constraint to a table is:


ALTER TABLE <table name> ADD CONSTRAINT

<constraint name> PRIMARY KEY (<column name>

[,<column name>...,<last column name>])


Therefore if you have a table created by


CREATE TABLE employee

(employee_id INTEGER NOT NULL,

badge_number SMALLINT NOT NULL,

first_name VARCHAR(20),

last_name VARCHAR(30))


you can add a single column PRIMARY KEY based on the EMPLOYEE_ID using the statement:


ALTER TABLE employee

ADD CONSTRAINT pk_employee PRIMARY KEY (employee_id)


If the values in a single column are not unique in each row of the table, but the values in a combination of columns are, you must use a composite, or multi-column PRIMARY KEY. Suppose, for example, that you had an EMPLOYEE table where two employees could have the same employee number, but no two employees with the same employee number would have the same badge number. To add the PRIMARY KEY to the table, use the ALTER TABLE statement


ALTER TABLE employee

ADD CONSTRAINT pk_employee

PRIMARY KEY (employee_id,badge_number)


to combine EMPLOYEE_ID and BADGE_NUMBER into a single, unique key value for each row of the table.


Note Since a table can have only one PRIMARY KEY, you just first use the ALTER TABLE statement


ALTER TABLE <table name> DROP CONSTRAINT <constraint name>


if you want to change a table's PRIMARY KEY. In other words, you must remove a table's existing PRIMARY KEY before you can use the ALTER TABLE statement to add a new PRIMARY KEY constraint to the table.


Adding FOREIGN KEY constraints to a table is similar to defining the PRIMARY KEY. However, when working with a FOREIGN KEY, you must identity not only the columns in the current table that make up the FOREIGN KEY but also the PRIMARY KEY columns in the table referenced by the FOREIGN KEY.


A FOREIGN KEY constraint is normally used to represent a parent/child relationship between two tables. When you place a FOREIGN KEY constraint on a column or combination of columns, you are saying that the value in the column (or combination of columns) in the child record (row in the child table) can be found in the column (or combination of columns) that makes up the PRIMARY KEY in the parent record (row in the parent table).


The syntax for using the ALTER TABLE statement to add a FOREIGN KEY constraint to a table is:


ALTER TABLE <table name>

[WITH NOCHECK]

ADD [CONSTRAINT <constraint name] FOREIGN KEY

(<column name>[,<column name>...,<last column name>]

REFERENCES <foreign table name>

(<foreign column name>

[,<foreign column name>...,<last foreign column name>])


As such, to create a parent/child relationship between a (parent) CUSTOMER table created by


CREATE TABLE customer

(customer_number INTEGER PRIMARY KEY,

first_name VARCHAR(20),

last_name VARCHAR(30),

address VARCHAR(35))


and a (child) ORDER table created by


CREATE TABLE order

(placed_by_customer_num INTEGER,

order_date DATETIME,

item_number INTEGER,

quantity SMALLINT)


you might use the ALTER TABLE statement


ALTER TABLE order ADD

CONSTRAINT fk_order_column

FOREIGN KEY (placed_by_customer_num)

REFERENCES customer (customer_number)


which links each row in the ORDER table to one (and only one) of the rows in the CUSTOMER table. In other words, each and every value in the PLACED BY_CUSTOMER_NUM column in the ORDER table can be found in the CUSTOMER_NUMBER column of the customer table. Thus, every order (child) must have an associated customer (parent) that placed the order.


Note When you use the ALTER TABLE statement to add a FOREIGN KEY to a table, the DBMS will check existing data to make sure it does not violate the constraint. In the current example, the DBMS will ensure that every value in the PLACED_BY_CUSTOMER_NUM of the ORDER table exists in the CUSTOMER_NUMBER table of the CUSTOMER table. If the check fails, the DBMS will not create the FOREIGN KEY, thereby maintaining referential data integrity.


If you are sure that existing data will not violate the FOREIGN KEY constraint, you can speed up the execution of the ALTER TABLE statement by adding the WITH NOCHECK clause. If you do so, the DBMS will not apply the FOREIGN KEY constraint to existing rows of the table. Only rows subsequently updated or inserted will be checked to make sure that the FOREIGN KEY value exists in the PRIMARY KEY of the referenced (parent) table.


Using the ALTER TABLE Statement to Change to Width or Data Type of a Column

Unlike many DBMS products, MS-SQL Server allows you to change not only the width of a column but also its data type. There are, however, a few restrictions on data type changes. You cannot change the data type of a column if the column:


Is of type TEXT, IMAGE, NTEXT, or TIMESTAMP


Is part of an index, unless the original data type is VARCHAR or VARBINARY and you are not changing the original data type or making the column width shorter


Is part of a PRIMARY KEY or FOREIGN KEY


Is used in a CHECK constraint


Is used in a UNIQUE constraint


Has a default associate with it


Is replicated


Is computed or used in a computed column


When changing a column's data type, all of the existing data in the column must be compatible with the new data type. As such, you can always convert from INTEGER to character since a CHARACTER column can hold numeric digits, letters, and special symbols. However, when converting a CHARACTER column to INTEGER, you must ensure that every row of the table has numeric digits or NULL in the CHARACTER field you are converting.


Once you've identified the column as one whose type you can change, use the ALTER TABLE statement in the form


ALTER TABLE <table name>

ALTER COLUMN <column name> <new data type>


to change the width or data type of a column. For example, if you have an EMPLOYEE table defined by


CREATE TABLE employee

(employee_id INTEGER,

first_name VARCHAR(20),

last_name VARCHAR(30),

social_security_number CHAR(11),

street_address CHAR(30),

health_card_number CHAR(15),

sheriff_card_number CHAR(15),

PRIMARY KEY (employee_id))


you can use the ALTER TABLE statement


ALTER TABLE employee

ALTER COLUMN street_address CHAR(35)


to change the width of the STREET_ADDRESS column from CHAR(30) to CHAR(35).


You can also use the ALTER TABLE statement to change a column's data type. For example, to change the HEALTH_CARD_NUMBER from CHAR(15) to INTEGER, use the ALTER TABLE statement:


ALTER TABLE employee

ALTER COLUMN health_card_number INTEGER


When converting a column from one data type to another, remember that all of the existing data in the column must be compatible with the new data type. Thus, the conversion of HEALTH_CARD_NUMBER from character to integer will work only if all of the current health card numbers are NULL or if they are all composed of only digits. As such, if any health card number includes a non-numeric character, the ALTER TABLE statement converting the column's data type from CHARACTER to INTEGER will fail.


Using the MS-SQL Server ALTER TABLE DROP COLUMN Clause to Remove a Table Column

The SQL-92 standard does not specify a DROP COLUMN clause as part of the ALTER TABLE statement. As a result, some DBMS products require that you unload data from the table, use the DROP TABLE statement to erase the table, execute the CREATE TABLE statement to re-create the table without the column you want to drop, and then reload the data you unloaded before dropping the table. (Given the steps involved, you might be tempted to just ignore the column you want to drop.)


Fortunately, MS-SQL Server provides a DROP COLUMN clause as part of its ALTER TABLE statement. The syntax for dropping a column is:


ALTER TABLE <table name>

DROP COLUMN <column name>

[,<column name>...,<last column name]


Thus, to drop columns from an EMPLOYEE table defined by


CREATE TABLE employee

(employee_id INTEGER,

first_name VARCHAR(20),

last_name VARCHAR(30),

social_security_number CHAR(11),

street_address VARCHAR(35),

health_card_number CHAR(15),

sheriff_card_number CHAR(15),

badge_number IDENTITY(100,100)

PRIMARY KEY (employee_id))


you could use the ALTER TABLE statement


ALTER TABLE employee

DROP COLUMN health_card_number, sheriff_card_number


to drop the HEALTH_CARD_NUMBER and SHERIFF_CARD_NUMBER columns.


MS-SQL Server will prevent you from dropping a column to which a constraint or default value is assigned. Moreover, you cannot drop a column identified as a FOREIGN KEY in another table. For example, if you attempt to drop the EMPLOYEE_ID from the EMPLOYEE table, MS-SQL Server will respond with the error message


Server: Msg 4922, Level 16, State 3, Line 1

ALTER TABLE DROP COLUMN employee_id failed because PRIMARY

KEY CONSTRAINT PK__employee__6E01572D access this column.


and the ALTER TABLE statement will fail.


In order to drop a column with a default value or constraint, you must first drop the constraint using an ALTER TABLE statement in the form:


ALTER TABLE <table name> DROP CONSTRAINT <constraint name>


In the current example, the CREATE TABLE statement did not specify a name for the PRIMARY KEY constraint on the EMPLOYEE_ID column of the EMPLOYEE table. As a result, the DBMS created the unique constraint name PK_employee_6E01572D for the PRIMARY KEY constraint. Thus, in order to remove the PRIMARY KEY constraint from the EMPLOYEE table in the example, use the Transact-SQL statement:


Note The name the DBMS assigns to an unnamed constraint will differ each time you create a constraint, even if you drop and respecify the same constraint. Also, when dropping a constraint with a DBMS-generated name, be sure to note and use double (vs. single) underscores (__) in the constraint name.


If you want to drop a column that is a FOREIGN KEY in another table, you must first use the ALTER TABLE statement to drop the FOREIGN KEY reference in the other table, and then you drop the column in the current table. (You will learn more about using the ALTER TABLE statement to work with FOREIGN KEY constraints in Tip 60.)


Website Design by Mayuri Multimedia