Search Java Programs

Wednesday, March 3, 2010

Understanding the CASCADE and RESTRICT Clauses in a DROP VIEW Statement

As mentioned in Tip 64, the DBMS will not erase any database data when you drop a view. However, you still have to be careful that the view you are dropping is not referenced by another view. Some DBMS products let you add the CASCADE or RESTRICT clause to a DROP VIEW statement to control the behavior of the DBMS when you tell the system to DROP a view that is referenced by another view.


If you execute the DROP VIEW statement with the CASCADE clause, the DBMS will not only remove the view you name in the DROP VIEW statement, but also any other view that references the view in the DROP VIEW statement. For example, if you have two views as defined by


CREATE VIEW vw_sales_production AS

SELECT rep_id, calls, sales, deliveries FROM production


and


CREATE VIEW vw_delivered_sales_commissions

(rep_id, deliveries, commission) AS

SELECT rep_id, deliveries, deliveries * 150.00

FROM vw_sales_production


when you execute


DROP VIEW vw_sales_production


the DBMS will remove only the VW_SALES_PRODUCTION view from the system tables. If you execute the SELECT statement


SELECT * FROM vw_delivered_sales_commissions


after you DROP the VW_SALES_PRODUCTION view, the DBMS will respond with an error message in the form:


Server: Msg 208, Level 16, State 1,

Procedure vw_delivered_sales_commissions, Line 1

Invalid object name 'vw_sales_production'.


Server: Msg 4413, Level 16, State 1, Line 1

Could not use view ' vw_delivered_sales_commissions'

previous binding errors.


If, on the other hand, you DROP the VW_SALES_PRODUCTION view with the DROP VIEW statement


DROP VIEW vw_sales_production CASCADE


the DBMS will remove both VW_SALES_PRODUCTION and VW_DELIVERED_SALES_COMMISSIONS (which references it) from the system tables.


Conversely, some DBMS products allow you to add the RESTRICT clause to the DROP VIEW statement. The RESTRICT clause will prevent you from dropping a view that is referenced by another view Thus, in the current example, executing the "restricted" DROP VIEW statement


DROP VIEW vw_sales_production RESTRICT


will fail because the view VW_SALES_PRODUCTION view is referenced by the VW_DELIVERED_SALES_COMMISSIONS view.


Note Not all DBMS products provide the CASCADE and RESTRICT clauses for the DROP VIEW statement-MS-SQL Server, for example, does not. As such, check your system documentation to see if you can add the CASCADE or RESTRICT clause to the DROP VIEW statement in your



Using the MS-SQL Server Enterprise Manager Create View Wizard to Create a View

Views are virtual tables. Although they look and act like regular relational database tables, views contain no data. Rather, a view is a set of instructions for the DBMS that tells it what data stored in physical (real) tables to display and how to display it. MS-SQL Server gives you two ways to define a view. You can use the CREATE VIEW statement (which you will learn about in Tip 206, "Using a View to Display Columns in One or More Tables or Views"), or you can use the MS-SQL Server's Create View Wizard. Whichever method you use to create the view, the DBMS will store its name in the system tables along with the SELECT statement that lists the view's columns and search criteria (its WHERE clause).

At the lowest level, all views are based on one or more physical database tables. (You can create views based on other views. However, at some point, one of the views in the chain has to be based on an actual database table.) Therefore, to see how you can use the Create View Wizard to create a view, you must start by deciding on the data you want to display. Suppose, for example, that you want to create a view based on the data in the PRODUCTION table shown in Figure 65.1.

PRODUCTION table

Rep_ID

Call

Appointments

Sales

Deliveries

1

100

4

3

2

2

255

7

4

4

3

750

12

6

5

4

400

15

9

7

5

625

10

8

6

6

384

11

6

4

7

295

17

4

1

Figure 65.1: PRODUCTION table with sample data to use in creating a view

To use the Create View Wizard to create a view that displays data from a single table, perform the following steps:

  1. Start the Enterprise Manager by clicking your mouse on the Start button. When Windows displays the Start menu, move your mouse pointer to Programs, select Microsoft SQL Server 7.0, and then click your mouse on Enterprise Manager.

  2. To display the list of SQL servers, click your mouse on the plus (+) to the left of SQL Server Group.

  3. Click your mouse on the icon for the SQL Server with the database in which you wish to create the view. For example, if you want to create a view in a database on a server named NVBIZNET2, click your mouse on the icon for NVBIZNET2.

  4. Select the Tools menu Wizards option (or click your mouse on the Wizards button, the magic wand on the Standard Toolbar). Enterprise Manager will display the Select Wizard dialog box so that you can select the wizard you want to use.

  5. Click your mouse on the plus (+) to the left of Database to display the list of database object wizards.

  6. Click your mouse on Create View Wizard to select it, and then click your mouse on the OK button. Enterprise Manager will start the Create View Wizard, which displays its "Welcome to the Create View Wizard" screen.

  7. Click your mouse on the Next button. The Create View Wizard will display the Select Database dialog box.

  8. Click your mouse on the drop-down list button to the right of the Database Name field to display the list of databases on the SQL Server you selected in Step 3.

  9. Click your mouse on the database in which you wish to create the view. For the current example, click your mouse on SQLTips to select the SQLTips database.

  10. Click your mouse on the Next button. The Create View Wizard will display a Select Tables dialog box, similar to that shown in Figure 65.2.

    1. Figure 65.2: The MS-SQL Server Create View Wizard's Select Tables dialog box

    2. Click your mouse on the check boxes of the tables whose data you want to include your view. For the current example, click your mouse on the check box for the PRODUCTION table until the check mark appears.

    3. Click your mouse on the Next button. The Create View Wizard will display a Select Columns dialog box, similar to that shown in Figure 65.3.

    4. Figure 65.3: The MS-SQL Server Create View Wizard's Select Columns dialog box

    5. Click your mouse on the check boxes of the columns you want to display. For the current example, select: PRODUCTION.REP_ID, PRODUCTION.CALLS, PRODUCTION. SALES, and PRODUCTION.DELIVERIES.


      Note

      The list of columns in the selection area of the Select Columns dialog box includes all of the columns for all of the tables selected in Step 11. The Create View Wizard shows you which columns belong in which tables by using the qualified column name for each column-that is, it displays the column name as

      . (where
      is the name of the table that contains ).

    6. Click your mouse on the Next button. The Create View Wizard will display the Define Restriction dialog box. If you do not want to display all of the rows in the tables you selected (in Step 11), enter the WHERE clause that you want the DBMS to use as the criteria for selecting the rows to display. For the current example, enter WHERE PRODUCTION.SALES > 4 to have the DBMS display only rows where the value in the SALES column of the PRODUCTION table is greater than 4.

    7. Click your mouse on the Next button. The Create View Wizard will display the Name the View dialog box.

    8. Enter a name for the view in the View Name field. For the current example, enter vw_sales_production into the View Name field.


      Note

      It is best to keep view names consistent so that you can distinguish them from actual tables when looking at a list of database objects. For example, if you start all of your view names (and only your view names) with "vw_", you will know that any database object starting with "vw_" is a view.

    9. Click your mouse on the Next button. The Create View Wizard will display the SQL statements the DBMS will use to create the view, in a Completing the Create View Wizard dialog box similar to that shown in Figure 65.4.

    10. Figure 65.4: The MS-SQL Server Create View Wizard's Completing the Create View Wizard dialog box

    11. Make any necessary corrections to the WHERE clause and any other changes necessary to further refine the view. (You can add or remove columns, change the view name, change the selection criteria in the WHERE clause, and so on.)

    12. Click your mouse on the Finish button.

    13. After you complete Step 19, the Create View Wizard will check the syntax of the statements in the Completing the Create View Wizard dialog box and will prompt you to correct any errors. (If there are any errors, the problem will most likely be with the WHERE clause you entered in Step 14.)

      Repeat Steps 18 and 19 until the Create View Wizard displays the "Wizard Complete!" message box, with the message "The view was created successfully." Once you see the message box, click your mouse on its OK button to return to the MS-SQL Server Enterprise Manager application window.

      Once the DBMS stores your view in its system tables, use the SELECT statement to display the view data. For example, to display all of the columns and rows in the view you created in the current example, execute the SELECT statement:

       SELECT * FROM vw_sales_production

      Given that the PRODUCTION table has the data shown in Figure 65.1,

    14. MS-SQL Server will display the virtual contents of your view table, VW_SALES_PRODUCTION as

       rep_id      calls  sales  deliveries
      ----------- ------ ------ ----------
      3 750 6 5
      4 400 9 7
      5 625 8 6
      6 384 6 4
      (4 row(s) affected)

Using the DROP VIEW Statement to Remove a View

To remove a database view that you no longer need, execute the DROP VIEW statement. Unlike the DROP TABLE statement, the DROP VIEW command does not erase any database tables or data. When you DROP a view, the DBMS simply removes its definition (the name and the SELECT statement that defines the view) from the system tables. If you later decide you need the view again, simply use the CREATE VIEW statement or a tool like the MS-SQL Server Create View Wizard to re-create the view. As long as the underlying table is still in the database, re-creating the view will bring back the virtual table and its data.

The syntax of the DROP VIEW statement is:DROP VIEW <view name> [,<view name>...[,<last view name>]]As such, to remove a VIEW named VW_SALES_PRODUCTION from the database, you would execute the SQL statement:DROP VIEW vw_sales_productionYou can remove several views at once by separating the names of the views with commas in a single DROP VIEW statement. For example, to remove views VW_SALES_PRODUCTION_EAST and VW_SALES_PRODUCTION_WEST, you would use the SQL statement:DROP VIEW

vw_sales_production_east, vw_sales_production_west

Although no data is erased when you drop a view, you do need to make sure that no stored procedures or other views reference the view you are about to drop. If you run a stored procedure or use view that references a dropped view, the DBMS will respond with an error message in the form:Server: Msg 208, Level 16, State 1, Procedure


<name of referencing view>, Line 2

Invalid object name '<name of dropped view>'.

Server: Msg 4413, Level 16, State 1, Line 1


Could not use view '<name of referencing view>' because of

previous binding errors.

(The DBMS, of course, substitutes the actual name of the dropped view for "<name of dropped view>" and the actual name of the view that references the dropped view for "<name of referencing view>." )

Using the DROP TABLE Statement to Remove a Table from the Database

When you no longer need a table, use the DROP TABLE statement to remove it from the database. Before dropping a table, however, make sure that you no longer need it! When the DBMS executes the DROP TABLE statement, it erases the table data and index(es) from the database and removes the definition of the table and its constraints from the system tables. Thus, the only way to recover a dropped table is to re-create the table and restore data by reading it from the most recent backup. As such, make sure you really no longer need the table or its data before you execute the DROP TABLE statement.


The syntax of the DROP TABLE statement is:


DROP TABLE

[[<schema name>.]<table owner name>.]]<table name>


Thus, to drop the CUSTOMER table in Tip 62, "Using the CREATE TABLE Statement to Assign Foreign Key Constraints," you would execute the SQL statement:


DROP TABLE customer


When it receives the DROP TABLE command, the DBMS checks to see if the table you want to drop is referenced by a FOREIGN KEY in another table. If it is (as is the case with CUSTOMER in the current example), the DROP TABLE statement will fail, and the DBMS will display an error message similar to:


Server: Msg 3726, Level 16, State 1, Line1

Could not drop object 'customer' because it is referenced

by a FOREIGN KEY constraint


Before you can remove a table reference by a FOREIGN KEY, you must first use the ALTER TABLE statement to remove the FOREIGN KEY constraint from the other table. In the current example, you must execute the ALTER TABLE statement


ALTER TABLE order DROP CONSTRAINT fk_customer_table


before the DBMS will let you drop the CUSTOMER table.


Note While the DBMS checks its system tables for FOREIGN KEY references to the table you want to remove, it does not check VIEWs (which you learned about in Tip 11, "Understanding Views") and stored procedures to see if they reference the table or its columns. Stored procedures that reference a dropped table will fail to run, and the DBMS will return an error message in place of VIEWs data that includes columns from a dropped table. As such, check your database documentation carefully to make sure that you are the only one that uses the table you are about to drop-before you drop the table.



Using the CREATE TABLE Statement to Assign Foreign Key Constraints

As was previously discussed, a database key uniquely identifies a row in a table. In Tip 61, "Using the CREATE TABLE Statement to Assign the Primary Key," you learned that each row in a PRIMARY KEY uniquely identifies single row within the table in which the PRIMARY KEY is declared. A FOREIGN KEY, on the other hand, references the PRIMARY KEY in a table other than the one in which the FOREIGN KEY is declared. As such, each row within a FOREIGN KEY in one table uniquely identifies a single row in another table. While each PRIMARY KEY value must be unique within a table, the values within a FOREIGN KEY need not be (and most likely is not) unique.


A FOREIGN KEY is normally represents 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 a column (or combination of columns) within the row in the child table can be found in the column (or combination of columns) that makes up the PRIMARY KEY value of a specific row within the parent table.


The syntax of the FOREIGN KEY constraint declaration is:


[CONSTRAINT <constraint name>]

FOREIGN KEY (<column name>

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

REFERENCES <foreign table name>

(<foreign table column name>

[,<foreign table column name>...

[,<last foreign table column name>]]}


Suppose, for example, that you want to track customer orders using the CUSTOMER (parent) table and ORDER (child) table created by:


CREATE TABLE customer

(customer_number INTEGER,

first_name VARCHAR(20),

last_name VARCHAR(30),

address VARCHAR(35),

CONSTRAINT pk_customer_table

PRIMARY KEY (customer_number))


CREATE TABLE order

(placed_by_customer_num INTEGER

FOREIGN KEY (placed_by_customer_num) REFERENCES

customer(customer_number),

order_date DATETIME,

item_number INTEGER,

quantity SMALLINT,


CONSTRAINT pk_order_table

PRIMARY KEY

(placed_by_customer_num, order_date, item_number))


The FOREIGN KEY defined in the ORDER table tells you that you can find the value in the PLACED_BY_CUSTOMER_NUM column (of the child table ORDER) in the PRIMARY KEY column CUSTOMER_NUMBER of a row in the CUSTOMER (parent) table.


Because the column PLACED_BY_CUST_NUM is a foreign and not a primary key in the ORDER table, you can have more than one ORDER row with the same value in the PLACED_BY_CUST_NUM column, indicating that an individual customer ordered more than one item or placed more than one order.


The FOREIGN KEY constraint on the PLACED_BY_CUSTOMER_NUM column also tells you that the value in the PLACED_BY_CUST_NUM column will appear once and only once in the CUSTOMER_NUMBER field of the CUSTOMER table (because a FOREIGN KEY in a table always refers to the PRIMARY KEY in another table). As such, you will be able to uniquely identify the customer that placed the order because the FOREIGN KEY value (PLACED_BY_CUSTOMER_NUM) in the current table uniquely identifies a row (a customer) in the foreign (CUSTOMER) table.


When you do not provide a name for a FOREIGN KEY constraint, the system will generate one for you so that it can store the constraint in its system tables. In the current example, the FOREIGN KEY in the ORDER table was not explicitly named. As such, the system will generate a name.


If you are using MS-SQL Server, you can determine the name of the FOREIGN KEY by executing the stored procedure sp_help and supplying the name of the parent table (CUSTOMER, in the current example) for <table name> in the statement:


EXEC sp_help <table name>


MS-SQL Server will respond with a description of the table and will list the FOREIGN KEY names in the "Table Is Referenced By" section of the report.


If you want to select a name for the FOREIGN KEY (instead of having the DBMS generate one), change the CREATE TABLE statement in the current example to:


CREATE TABLE order

(placed_by_customer_num INTEGER

CONSTRAINT fk_customer_table FOREIGN KEY

(placed_by_customer_num) REFERENCES

customer(customer_number),

order_date DATETIME,

item_number INTEGER,

quantity SMALLINT,

CONSTRAINT pk_order_table

PRIMARY KEY

(placed_by_customer_num, order_date, item_number))


As you learned in Tip 61, a PRIMARY KEY may consist of more than one column. When a FOREIGN KEY in one table references a composite (or multi-column) PRIMARY KEY in another table, the FOREIGN key, too, will consist of multiple columns. Suppose, for example, that the ITEM_MASTER table for the orders in the current example was defined by:


CREATE TABLE item_master

(item_number INTEGER,

vendor_id INTEGER,

quantity_on_hand SMALLINT


CONSTRAINT pk_item_master_table

PRIMARY KEY (item_number, vendor_id))


You could reference the composite PRIMARY KEY in the ITEM_MASTER table with the FOREIGN KEY constraint FK_ITEM_MASTER_TABLE using the CREATE TABLE statement:


CREATE TABLE order

(placed_by_customer_num INTEGER

order_date DATETIME,

item_number INTEGER,

vendor_id_number INTEGER,

quantity SMALLINT,


CONSTRAINT fk_item_master_table FOREIGN KEY

(item_number, vendor_id_number) REFERENCES

item_master (item_number, vendor_id),


CONSTRAINT fk_customer_table FOREIGN KEY

(placed_by_customer_num) REFERENCES

customer (customer_number),


CONSTRAINT pk_order_table

PRIMARY KEY

(placed_by_customer_num, order_date, item_number))


The important thing to know about the FOREIGN KEY constraint is that it specifies that the value in the column or combination of columns in one table must be found as the value in the PRIMARY KEY of the table, which it references. As such, if you have a single-column PRIMARY KEY, you will use a single-column FOREIGN KEY. Conversely, if you need to reference a multi-column or composite PRIMARY KEY, you will use a multi-column FOREIGN KEY.


Using the CREATE TABLE Statement to Assign the Primary Key

A key is a column or combination of columns that uniquely identifies a row in a table. As such, a key gives you way to distinguish one particular row in a table from all of the others. Because a key must be unique, you should not include NULL values in any of the columns that make up a key. Remember, the DBMS cannot make any assumptions about the actual value of NULL in a column. Thus, a row with NULL in a key column will be indistinguishable from any other row in the table because the NULL value could, in fact, be equal to the value in any other row.


Each table can have one (and only one) PRIMARY KEY. Because the PRIMARY KEY must uniquely identify each row in a table, the DBMS automatically applies the NOT NULL constraint to each of the columns that make up the PRIMARY KEY. When creating a new table, you can create a single-column PRIMARY KEY by including the key words "PRIMARY KEY" in the column definition.


The syntax of a PRIMARY KEY definition in a CREATE TABLE statement comes in one of two forms


[CONSTRAINT <constraint name>] PRIMARY KEY


if the PRIMARY KEY is an unnamed constraint defined as part of the PRIMARY KEY column's definition, or


CONSTRAINT <constraint name>

PRIMARY KEY (<column name>

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


for a multiple-column (or composite) PRIMARY KEY or a single-column named PRIMARY KEY.


For example, the CREATE TABLE statement


CREATE TABLE employee

(employee_id INTEGER PRIMARY KEY,

first_name VARCHAR(20),

last_name VARCHAR(30))


identifies the EMPLOYEE_ID column as the PRIMARY KEY in the EMPLOYEE record. As such, every row in the EMPLOYEE table must have a unique, non-NULL value in the EMPLOYEE_ID column.


The system stores the PRIMARY KEY as a constraint in the system tables. As such, if you don't give the PRIMARY KEY a name, the DBMS will generate one for you. The name the system assigns becomes important to you if you ever want to drop a table's PRIMARY KEY so that you can change it. (Since a table can have only one PRIMARY KEY, you will need to drop the existing PRIMARY KEY and create a new one when if you want to change its column[s].)


Note If you are using MS-SQL Server, you can call the stored procedure sp_help to display the name that the DBMS assigned to the PRIMARY KEY by executing the command


EXEC sp_help <table name>


(where <table name> is the name of the table with the PRIMARY KEY whose name you want to know).


MS-SQL Server will respond with a description of the table identified by <table name>. Look in the index_name column of the section of the report titled PRIMARY to see the name the DBMS assigned to the PRIMARY KEY.


If you don't want the DBMS to generate its own name for the PRIMARY KEY, you can name it yourself by specifying the name when you identify the column that makes up the PRIMARY KEY. For example, to give the name pk_employee_table to the PRIMARY KEY in the current example, use the CREATE TABLE statement:


CREATE TABLE employee

(employee_id INTEGER,

CONSTRAINT pk_employee_table PRIMARY KEY,

first_name VARCHAR(20),

last_name VARCHAR(30))


Sometimes no single column in a table has a unique value in every row. Suppose, for example, that each division in your company issues its own employee numbers. Division #1 has employees #123, #124, and #126; division #2 has employees #121, #122, and #123. If you identify EMPLOYEE_ID as the PRIMARY KEY, you will be able to insert all division #1 employees into the EMPLOYEE table. However, when you try to insert division #2 employee #123, the DBMS will not allow you to do so. Because the EMPLOYEE table already has a row with an EMPLOYEE_ID of 123, the DBMS rejects your attempt to add a second row with 123 in the EMPLOYEE_ID column because EMPLOYEE_ID, the PRIMARY KEY, must be unique in each row of the table.


You can still create a PRIMARY KEY for the table where no single column is unique by identifying a set of multiple columns that, when taken together, is different in every row of the table. In the current example, you know that employee numbers are unique by division. Thus, you can use a two-column PRIMARY KEY consisting of EMPLOYEE_ID and DIVISION, such as


CREATE TABLE employee

(employee_id INTEGER,

division SMALLINT,

first_name VARCHAR(20),

last_name VARCHAR(30)


CONSTRAINT pk_employee_table

PRIMARY KEY (employee_id, division))


to create a PRIMARY KEY for the EMPLOYEE table.


Note The Placement of the PRIMARY KEY definition within the CREATE TABLE statement is not important. As such, the CREATE TABLE statement


CREATE TABLE employee

(employee_id INTEGER

CONSTRAINT pk_employee_table

PRIMARY KEY (employee_id, division),

division SMALLINT,

first_name VARCHAR(20),

last_name VARCHAR(30))


is equivalent to the one in the example just prior to this note.



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