To remove a database from an MS-SQL Server-while leaving the database data (.mdf) and transaction log (.ldf) files intact on the hard drive-call the built-in stored procedure sp_detach_db. Although you cannot access the data within a database while it is not attached to an MS-SQL Server, you can copy or move the database .mdf file (which contains the database data and all its objects) onto another hard drive or onto another server altogether. Then, as we will discuss later within this tip, you can reattach the database data file (and optionally, its transaction log file) onto the same or a different MS-SQL Server. When that is completed, you can once again work with the data and objects within the database.
The built-in stored procedure sp_detach_db, which allows you to remove a database from the MS-SQL Server without deleting the database's files from the hard drive, has the following syntax
sp_detach_db [@dbname=]'' [, [@skipchecks=]{'TRUE'|'FALSE'}]
where:
Note that the MS-SQL Server keeps statistics about the distribution of key values within an index and (sometimes) the same statistics about values stored within some of the table's non-indexed columns. The optimizer uses these statistics to determine which index or table column to use when executing a query. Whenever there is a significant change to the values stored within a table, or if someone added a large amount of data (with a bulk INSERT INTO) or removed a lot of data (with a TRUNCATE), you should set @SKIPCHECKS to FALSE so the DBMS will update table and index statistics. In addition, if you plan to move the DBMS to a read-only device, set @SKIPCHECKS to FALSE, so that permanent database has the most up-to-date indexes, which will allow queries to retrieve data as efficiently and quickly as possible. Otherwise, set @SKIPCHECKS TRUE or omit its value from the stored procedure call.
To remove the database SQLTips from an MS-SQL Server without updating statistics on INDEXES and table column values, submit the following EXEC statement to the DBMS:
EXEC sp_detach_db @dbname='SQLTips', @skipchecks='TRUE'
When you must reattach to an MS-SQL Server a database (.mdf) file that you previously detached with sp_detach_db, use the built-in stored procedure call sp_attach_db, whose syntax is shown here
sp_attach_db [@dbname=]'' ,[@filename<n>=] '' [...,@filename16]
where:
Suppose, for example, that you want to reattach the SQLTips database whose data is stored within the file C:MSSQLDataSQLTips_data.mdf and whose transaction log is stored within the file in D:MSSQLLogFilesSQLTips_log.ldf. To reattach SQLTips to an MS-SQL Server, you would execute the following EXEC statement:
EXEC sp_attach_db @dbname='MySQLTips', @filenamel='C:MSSQLDataSqlTips_data.mdf', @filename2='D:MSSQLLogFilesSQLTips_log.ldf'
If you have only the database data (.mdf) file, you would call sp_attach_db as follows, instead:
EXEC sp_attach_db @dbname='MySQLTips', @filename1='C:MSSQLDataSqlTips_data.mdf'
When you have only the database .mdf (data), the stored procedure will attach the data file to the MS-SQL Server and then create a new transaction log.
When you reattach a database to an MS-SQL Server, the database will again be accessible to DBMS users who were previously granted permission to use the database. All database objects and data, as well as user and role definitions are stored within a database .mdf file. As such, after executing the sp_attach_db procedure, the objects, data, logins, and security created within the original, previously detached database will be available within the database on the MS-SQL Server to which it was reattached.
While creating a table, you must assign each column a data type that defines the type of data the column can hold. For example, if a column is of type INTEGER, users and applications can store only whole numbers within the column-characters and numbers with a decimal point are not allowed within the column. Similarly, when you define a column as being of type CHAR(10), the column can hold up to 10 characters, symbols, or numeric digits.
By creating a user-defined data, you can assign a descriptive name to one of the standard SQL data types. The name you assign should describe for the user the type of data and/or range of data values a user will find within a column. Suppose, for example, that you are working with the SALARY column in an EMPLOYEE table. You could define the column's data type as NUMERIC(10,2), or you could use a more descriptive user-defined data type such as EXECUTIVE_SALARY, MANAGER_SALARY, or SUPERVISOR_SALARY. Moreover, by creating a rule and binding it to the user-defined data type assigned to a column, you can ensure that numbers entered into the column (SALARY, in this example) fall within a certain range of values.
Tip 53 "Using the MS-SQL Server Enterprise Manager to Create a User-Defined Data Type," showed you how to create user-defined data types. In addition to creating data types within the Enterprise Manager, MS-SQL Server lets you create data types from the command line by calling the built-in stored procedure sp_addtype, which has the following syntax
sp_addtype [@typename=]'' ,[@phystype=]'' [,[@nulltype=]'{NULL|NOT NULL|NONULL}' [,[@owner=]'']
where:
For example, to create the user-defined data type SALES_TAX, which defines a numeric value with a maximum of six digits, five of which might follow the decimal point, you would call sp_addtype as shown here:
EXEC sp_addtype @typename='SALES_TAX', @phystype='NUMERIC(6,5),@owner='dbo'
Note that the sp_addtype stored procedure call in this example makes the DBO the user-defined data type's owner. Whenever you make the DBO a user-defined data type's owner, all users can refer to the new data type by name. If a user other than DBO owns a data type, the user must provide both the owner's username and user-defined data type's name when using the data type within a column definition.
When you no longer need a data type, you can drop it from the database using the sp_droptype stored procedure, with the following syntax
sp_droptype [@typename=]''
where:
Note |
You can only drop (that is, delete) user-defined types not currently in use. Thus, before you can drop a user-defined type, you must remove it from all table definitions in which it is applied to a column. In addition, you must unbind any rules or defaults (using sp_unbindrule or sp_unbindrule fault) you previously bound to the data type. |
Thus, to drop the user-defined data type "SSAN" from the DBMS use:
EXEC sp_droptype @typename='SSAN'
The built-in stored procedure sp_help lets you display the properties of objects within a database. Just as Windows displays an object's description after you right-click the object and select Properties from the pop-up menu, sp_help returns a description of the object whose name you pass as a parameter to the stored procedure.
The syntax of the sp_help stored procedure call is
sp_help [[@objname=]]
where:
If you call sp_help without supplying the name of an object (within the @OBJNAME parameter) as shown in the following code line, the MS-SQL Server will return a results set that lists the name, owner, and data type of each object within the database:
EXEC sp_help
Therefore, calling sp_help without supplying an object's name is a convenient way to get a list of all database objects. You can then pass the names of objects, one at a time, to sp_help and get additional information on the objects you want.
The results set (that is, the specific properties information) that the DBMS returns when you call sp_help, depends on the type of object you pass to the stored procedure through its @OBJNAME parameter. For example, if you pass the name of a constraint, the DBMS will return a table listing:
Similarly, to display information about a stored procedure such as USP_PROCESS_CHECK, for example, you would call sp_help as follows:
EXEC sp_help 'USP_PROCESS_CHECK'
MS-SQL Server will display the name of the stored procedure, the username of its owner, and the date and time it was created. Next, the DBMS will return a results set with information about each of the stored procedure's parameters. The results set includes:
MS-SQL Server stores the batch of statements you enter to define a stored procedure, user-defined function, trigger, default, rule, or view within the TEXT column of a row within the SYSCOMMENTS table. If you did not encrypt the stored procedure, function, or trigger when you created it, you can display its statements by calling the stored procedure sp_helptext using the following syntax
sp_helptext [[@objname=]]
where:
@objname is the name of the stored procedure, user-defined data type, function, trigger, default, rule or view.
You can only use sp_helptext to display the statement batch for objects within the current database. For example, the built-in stored procedure sp_helptext is defined within the MASTER database. As such, to display the definition of the stored procedure sp_helptext, you must first execute a "USE master" statement and then you call the stored procedure sp_helptext as shown here:
EXEC sp_helptext 'sp_helptext'
If you encrypt an object's definition by including the WITH ENCRYPTION clause with the CREATE statement that you executed to create the object, sp_helptext will not be able to display the object's text. Instead, sp_helptext will display the message "The object has been encrypted." Sp_helptext will, of course, display the object's name in place for .
Before altering tables or views, especially when changing the number or order of columns in either type of object, be sure to call sp_depends. As you learned in Tip 11 "Understanding Views," a view is a virtual table that derives its columns and its rows of data either from other views or from base tables within the database. Therefore, if you drop a table, views that reference column values within the table will no longer work. When a user queries a view whose underlying table (or view) has been deleted, the DBMS returns error messages such as the following:
Server: Msg 208, State 1, Procedure vw_show_high_rollers, Line2 Invalid object name 'high_rollers'. Server: Msg 4413, Level 16, State 1, Line 1 Could not use view or function 'vw_show_high_rollers' because of binding errors
While the actual text of the error messages will vary, their point is the same: Views whose base tables (or base views) have been deleted stop displaying data. Moreover, views that stop working may cause a cascade of errors throughout the DBMS as stored procedures and user-defined functions may stop working because the views that feed data to them no longer work. To prevent such data outages, you must remove dependencies before dropping tables or views upon which other views are dependant.
When database object A references a column within database object B, object A is said to be dependent on object B. A view, for example, is dependant on a table when a column within the view references a column within the table. Similarly, a view is dependant upon another view when one of the columns within the first view references a column within the second.
MS-SQL Server makes a note of all dependencies between database objects within the SYSDEPENDS table. Unfortunately, SYSDEPENDS refers to all database objects by ID number rather than by name. As a result, checking which objects are dependant by querying SYSDEPENDS can be challenging. Fortunately, you can use the built-in stored procedure sp_depends to check the dependencies between and among objects by name.
The syntax for the sp_depends stored procedure call is
sp_depends [[@objname=]]
where:
@objname is the name of the view, table, or other database object whose dependencies you want to examine.
Sp_depends reports not only those objects that depend on the object whose name you pass to the stored procedure (through the @OBJNAME parameter), but also the database objects on which the object itself depends. Thus, before dropping or altering the view VW_HIGH_ROLLERS, for example, call sp_depends (as shown by the following code) to determine if there are any database views that reference columns within the VW_HIGH_ROLLERS view:
sp_depends 'vw_high_rollers'
If sp_depends reports there are database objects dependant on the view you want to delete, don't delete it. Or, if you delete the view anyway, either change the references within dependant objects, such that they refer to other database objects that have the same data, or delete the dependant objects views as well, because they will no longer work. Of course, before you delete any dependant objects, you should use sp_depends to see if other objects depend on them as well.
A constraint, as you learned in Tip 15 "Understanding Constraints," is a database object that restricts the range of values and type of data a user or application can place within a table column. There are seven types of constraints: assertions, domains, check constraints, foreign key constraints, primary key constraints, required data, and uniqueness constraints. Tip 15 explains the role that each type of constraint plays in maintaining database integrity. The bottom line is that the DBMS prevents users and applications from inserting rows with data that violates any constraints on the table's column or on the table as a whole.
If you are inserting rows manually (by executing INSERT statements through the SQL Query Analyzer, for example), the MS-SQL Server will report any constraint violations onscreen if it rejects the rows you are trying to insert. When you use an external application to insert data into a database table or when you call on a stored procedure to do so, the DBMS still rejects rows with illegal values. However, if the application or stored procedure does not handle errors properly, you might never see the system's error messages—data that you think was inserted into the database will simply go missing.
When writing batch routines that insert or update table data, it is critical that you understand the table's column constraints. Therefore, before you write stored procedures or external applications that update the database, call the built-in stored procedure sp_ helpconstraint to get a list of all constraints to which column values in new rows must adhere. Then, include within your programs and stored procedures code that ensures that data to be inserted does not violate these constraints.
The syntax of an sp_helpconstraint stored procedure call is
sp_helpconstraint [@objname=]'' [,[@ncmsg=}{'nomsg'}]
where:
For each table constraint, sp_helpconstraint returns a results set that includes:
In addition to the preceding information about column constraints, sp_helpconstraint also lists any FOREIGN KEY constraints that reference the table—giving the name of each FOREIGN KEY and the name of the table in which the FOREIGN KEY is defined.
For example, to display the constraints on the AUTHORS table within the PUBS database you would execute the following statement batch:
USE PUBS EXEC sp_helpconstraint 'authors'
Note |
You must call sp_helpconstraint from within the database that has the table for which you want the stored procedure to report constraints. In this example, PUBS must be the current database for the sp_helpconstraint procedure to report the constraints on the AUTHORS table as shown in Figure 566.1.
|
To display the text of CHECK and DEFAULT constraints, use the built-in stored procedure sp_helptext (which you learned about in Tip 564 "Using the MS-SQL Server Stored Procedure sp_helptext to Display the Text that Defines a Stored Procedure, User-Defined Function, Trigger, Default, Rule, or View"). In this example, you would execute the following EXEC command to display the text of the CHECK constraint on the AU_ID column within the AUTHORS table:
EXEC sp_helptext 'CK__authors__au_id__77BFCB91
When passing a system-supplied constraint name to the sp_helptext stored procedure, be sure to note the two underscores that precede the table name (AUTHORS), the column name (AU_ID), and the random string ("77BFCB91") within the constraint.
You can establish a parent/child relationship between any two tables by making a FOREIGN KEY reference within the child table to the PRIMARY KEY within the parent table. A PRIMARY KEY is nothing more than one or more columns within a table to which the PRIMARY KEY constraint has been applied. Similarly, a FOREIGN KEY is a column or set of columns that have a FOREIGN KEY constraint. The importance of the PRIMARY KEY is that each PRIMARY KEY value uniquely identifies a single row within the parent table. In other words, every row in the column (or set of columns) that is the table's PRIMARY KEY must have a unique, non-NULL value. The values within the rows of a FOREIGN KEY column, on the other hand, need not be, and, in fact, are ideally not unique to any row within the child table.
Suppose, for example you want to setup a parent/child relationship between a CUSTOMERS table and an ORDERS table. In this relationship, the rows within the CUSTOMERS table are "parents" and the "child" rows are within the ORDERS table. A customer can (and hopefully does) place more than one order. However, any particular order can only belong to one customer.
To setup the parent/child relationship between CUSTOMERS and ORDERS, you would use the built-in stored procedure sp_pkeys to identify the PRIMARY KEY columns that uniquely identifies each customer (that is, each row) within the CUSTOMERS table. Then you can define within the child table (ORDERS) a FOREIGN KEY constraint that references the PRIMARY KEY within the parent table (CUSTOMERS).
The syntax of an sp_pkeys stored procedure call is
sp_pkeys [@table_name=]'' [,[@table_owner=]'
' [,[@table_qualifier=]''
where:
among the tables you own, and then among the tables owned by the database owner (DBO).
Thus, to display information about the PRIMARY KEY defined on the CUSTOMERS table within the NORTHWIND database, you might write the following EXEC statement:
EXEC sp_pkeys @table_name='customers', @table_qualifier='Northwind'
When called, sp_pkeys will return a results set with the following information about the PRIMARY KEY:
After calling the sp_pkeys stored procedure, look in the COLUMN_NAME column within the results table to determine the column your FOREIGN KEY (within the ORDERS table, in this example) must reference within the parent (CUSTOMERS) table. Then, apply a FOREIGN KEY constraint to the appropriate columns within the child (ORDERS) table. You learned how to apply FOREIGN KEY constraints while creating a new table within Tip 62, "Using the CREATE TABLE Statement to Assign Foreign Key Constraints." You also learned how to change the structure of an existing table within Tip 60, "Using the ALTER TABLE Statement to Change Primary and Foreign Keys."
If the PRIMARY KEY has multiple columns, the results set returned by the sp_pkeys stored procedure will have multiple rows-one for each column within the PRIMARY KEY. When working with multi-column PRIMARY KEYs, pay particular attention to the value in both the COLUMN_NAME and KEY_SEQ columns. Make sure you list each column within the FOREIGN KEY in the same ordinal position as its corresponding column within the PRIMARY KEY. In other words, the number of columns within the FOREIGN KEY must match the number of columns in the PRIMARY KEY, and corresponding columns must be in the same ordinal position within each key. The number in the KEY_SEQ column gives you the ordinal position within the PRIMARY KEY of the column named in the COLUMN_NAME column.
When creating a relational database, be sure to exploit the ability of the DBMS to maintain referential integrity. Although you can set up multi-table SELECT statements that join parent and child rows without PRIMARY KEY and FOREIGN KEY constraints, resist the temptation to do so. While it takes some prior planning to set up PRIMARY KEY and FOREIGN KEY constraints properly, doing so frees you from having to worry about users being able to insert duplicate rows into the parent table or being able to create orphan rows within the child table.
Duplicate rows in a parent table and/or orphans within a child table are undesirable because they lead to errors in reporting and can cause real-life problems. Suppose, for example, that you have a CUSTOMERS parent table and an ORDERS child table. If you have duplicate rows within the CUSTOMERS (parent) table, a child row within the ORDERS table could have two (or more) parents within the CUSTOMERS table-which means a customer will likely be billed twice for the one order that shipped. Conversely, orphan rows within the child (ORDERS) table means there are orders with no customer information. Therefore, if the "Ship To" address is stored within the ORDERS table and the "Bill To" information is stored in the CUSTOMERS table, orders will ship without customers being billed.
After you set up PRIMARY KEY and FOREIGN KEY constraints that let the DBMS manage parent/child relationships between related tables (that is, to maintain referential integrity within the database), you will find it convenient to produce a list of FOREIGN KEY constraints that reference each parent table. This list will come in handy when you want to drop a parent table or change its structure. In addition, when executing a DELETE statement to remove parent rows or an UPDATE statement that changes values within PRIMARY KEY columns, you may have to drop or update columns in rows within the child table as well. The list of FOREIGN KEY references to the parent table's PRIMARY KEY will tell you which child tables require attention when you make changes within the parent table.
The built-in stored procedure sp_fkeys lets you get a list of FOREIGN_KEY references on any table within a database managed by an MS-SQL Server. To call sp_fkeys, use the following syntax
sp_fkeys [@pktable_name=]'' [,[@pktable_owner=]'' [,[@fktable_name=]'' [,[@fktable_owner=]'' [,[@fktable_qualifier=]''
where:
Thus, if you want a list of all FOREIGN KEY constraints that reference the PRIMARY KEY within the CUSTOMERS table in the NORTHWIND database, you would execute the following statement batch:
USE Northwind EXEC sp_fkeys @pktable_name='Customers'
The stored procedure sp_fkeys, in turn, will return a results set with at least one row per FOREIGN KEY reference and the following columns within each row:
To display the above listed information for all parent tables referenced by FOREIGN KEYS within a child table, you would call sp_fkey and supply to it only the information about the child table (which has the FOREIGN KEY constraints). For example, to list all tables referenced by FOREIGN KEY constraints within the ORDERS table in the NORTHWIND database, you would execute the following statement batch:
USE Northwind EXEC sp_fkeys @fktable_name='Orders'
In Tips 530-532 you learned what a stored procedure does, how to use the CREATE PROCEDURE statement to create a stored procedure, and how to call a stored procedure using the Transact-SQL EXEC command. In short, a stored procedure is a batch of SQL and/or Transact-SQL statements the DBMS executes whenever a user calls the stored procedure by name. Stored procedures are a powerful feature, because they let you write SQL Programs. That is, stored procedures let you combine SQL data management statements with procedural Transact-SQL programming statements so you can create statement batches that perform complex queries, database updates, or execute any sequence of SQL (and Transact-SQL statements) you like. Stored procedures make it possible for a database user to execute complex queries or a large batch of database management statements by submitting a single EXEC statement that calls the stored procedure, which then performs the work required.
In addition to letting users and external applications execute stored procedures, you can have the MS-SQL Server execute specific stored procedures automatically each time you start the DBMS. For example, if you have set of maintenance tasks such as creating and or clearing global temporary tables or cursors, creating executive summary tables, or some other cleanup/preparatory tasks that you want the DBMS to perform each time you start the MS-SQL Server, put the statements that perform the work into one or several stored procedures. Then, use the built-in stored procedure sp_procoption to mark the stored procedures you want to be called at startup.
To create stored procedures the DBMS will execute at startup, you must login to the MASTER database as the database owner (DBO). As DBO, and within the MASTER database, use the CREATE PROCEDURE statement to create a stored procedure you want the DBMS to execute at startup. Next, call the sp_procoption stored procedure with the the following syntax to mark the stored procedure you created for execution at startup
sp_procoption [@procname=]'' ,[@optionname=]'startup' [@optionvalue=]'{true|false}'
where:
Suppose for example, that you create the stored procedure su_sp_CreateExecSummary as the DBO within the MASTER database. To have the DBMS call su_sp_CreateExecSummary each time you restart the MS-SQL Server, execute the following statement batch:
USE master EXEC sp_procoption @procname = 'su_sp_CreateExecSummary', @optionname = 'startup', @optionvalue = 'true'
SQL Tips and Techniques